diff --git a/apps/gui/bitmap/list-skinned.c b/apps/gui/bitmap/list-skinned.c
index 208b2df..4b2493f 100644
--- a/apps/gui/bitmap/list-skinned.c
+++ b/apps/gui/bitmap/list-skinned.c
@@ -175,22 +175,23 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list)
     for (cur_line = 0; cur_line < display_lines; cur_line++)
     {
         struct skin_element* viewport;
-        struct skin_viewport* skin_viewport;
+        struct skin_viewport* skin_viewport = NULL;
         if (list_start_item+cur_line+1 > list->nb_items)
             break;
         current_drawing_line = list_start_item+cur_line;
         is_selected = list->show_selection_marker &&
                 list_start_item+cur_line == list->selected_item;
         
-        for (viewport = listcfg[screen]->data->tree;
+        for (viewport = SKINOFFSETTOPTR(skin_buffer, listcfg[screen]->data->tree);
              viewport;
-             viewport = viewport->next)
+             viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next))
         {
             int origional_x, origional_y;
             int origional_w, origional_h;
+            char *viewport_label = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label);
             skin_viewport = (struct skin_viewport*)viewport->data;
-            if (viewport->children == 0 || !skin_viewport->label ||
-                (skin_viewport->label && strcmp(label, skin_viewport->label))
+            if (viewport->children == 0 || !viewport_label ||
+                (skin_viewport->label && strcmp(label, viewport_label))
                 )
                 continue;
             if (is_selected)
@@ -220,15 +221,17 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list)
             display->set_viewport(&skin_viewport->vp);
 #ifdef HAVE_LCD_BITMAP
             /* Set images to not to be displayed */
-            struct skin_token_list *imglist = wps.data->images;
+            struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, wps.data->images);
             while (imglist)
             {
-                struct gui_img *img = (struct gui_img *)imglist->token->value.data;
+                struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, imglist->token);
+                struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, token->value.data);
                 img->display = -1;
-                imglist = imglist->next;
+                imglist = SKINOFFSETTOPTR(skin_buffer, imglist->next);
             }
 #endif
-            skin_render_viewport(viewport->children[0],
+            struct skin_element** children = SKINOFFSETTOPTR(skin_buffer, viewport->children);
+            skin_render_viewport(children[0],
                                  &wps, skin_viewport, SKIN_REFRESH_ALL);
 #ifdef HAVE_LCD_BITMAP
             wps_display_images(&wps, &skin_viewport->vp);
diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c
index 95e4310..4ee7b25 100644
--- a/apps/gui/skin_engine/skin_display.c
+++ b/apps/gui/skin_engine/skin_display.c
@@ -102,7 +102,7 @@ void skin_statusbar_changed(struct gui_wps *skin)
     struct wps_data *data = skin->data;
     const struct screen *display = skin->display;
     const int   screen = display->screen_type;
-    struct skin_viewport *svp = skin_find_item(VP_DEFAULT_LABEL, SKIN_FIND_VP, data);
+    struct skin_viewport *svp = skin_find_item(VP_DEFAULT_LABEL_STRING, SKIN_FIND_VP, data);
 
     struct viewport *vp = &svp->vp;
     viewport_set_defaults(vp, screen);
@@ -131,7 +131,7 @@ void skin_statusbar_changed(struct gui_wps *skin)
 void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
 {
     struct screen *display = gwps->display;
-    struct viewport *vp = pb->vp;
+    struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, pb->vp);
     struct wps_state *state = skin_get_global_state();
     struct mp3entry *id3 = state->id3;
     int x = pb->x, y = pb->y, width = pb->width, height = pb->height;
@@ -226,9 +226,9 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
         flags |= INNER_NOFILL;
     }
 
-    if (pb->slider)
+    if (SKINOFFSETTOPTR(skin_buffer, pb->slider))
     {
-        struct gui_img *img = pb->slider;
+        struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, pb->slider);
         /* clear the slider */
         screen_clear_area(display, x, y, width, height);
 
@@ -245,9 +245,9 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
         }
     }
     
-    if (pb->backdrop)
+    if (SKINOFFSETTOPTR(skin_buffer, pb->backdrop))
     {
-        struct gui_img *img = pb->backdrop;
+        struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, pb->backdrop);
         char *img_data = core_get_data(img->buflib_handle);
 #if LCD_DEPTH > 1
         if(img->bm.format == FORMAT_MONO) {
@@ -269,11 +269,12 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
     
     if (!pb->nobar)
     {
-        if (pb->image)
+        struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, pb->image);
+        if (img)
         {
-            char *img_data = core_get_data(pb->image->buflib_handle);
-            pb->image->bm.data = img_data;
-            gui_bitmap_scrollbar_draw(display, &pb->image->bm,
+            char *img_data = core_get_data(img->buflib_handle);
+            img->bm.data = img_data;
+            gui_bitmap_scrollbar_draw(display, &img->bm,
                                     x, y, width, height,
                                     length, 0, end, flags);
         }
@@ -282,11 +283,11 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
                                length, 0, end, flags);
     }
 
-    if (pb->slider)
+    if (SKINOFFSETTOPTR(skin_buffer, pb->slider))
     {
         int xoff = 0, yoff = 0;
         int w = width, h = height;
-        struct gui_img *img = pb->slider;
+        struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, pb->slider);
         char *img_data = core_get_data(img->buflib_handle);
 
         if (flags&HORIZONTAL)
@@ -391,11 +392,12 @@ void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
 
     struct wps_data *data = gwps->data;
     struct screen *display = gwps->display;
-    struct skin_token_list *list = data->images;
+    struct skin_token_list *list = SKINOFFSETTOPTR(skin_buffer, data->images);
 
     while (list)
     {
-        struct gui_img *img = (struct gui_img*)list->token->value.data;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, list->token);
+        struct gui_img *img = (struct gui_img*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
         if (img->using_preloaded_icons && img->display >= 0)
         {
             screen_put_icon(display, img->x, img->y, img->display);
@@ -406,20 +408,21 @@ void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
             {
                 wps_draw_image(gwps, img, img->display);
             }
-            else if (img->always_display && img->vp == vp)
+            else if (img->always_display && SKINOFFSETTOPTR(skin_buffer, img->vp) == vp)
             {
                 wps_draw_image(gwps, img, 0);
             }
         }
-        list = list->next;
+        list = SKINOFFSETTOPTR(skin_buffer, list->next);
     }
 #ifdef HAVE_ALBUMART
     /* now draw the AA */
-    if (data->albumart && data->albumart->vp == vp
-        && data->albumart->draw_handle >= 0)
+    struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart);
+    if (aa && SKINOFFSETTOPTR(skin_buffer, aa->vp) == vp
+        && aa->draw_handle >= 0)
     {
-        draw_album_art(gwps, data->albumart->draw_handle, false);
-        data->albumart->draw_handle = -1;
+        draw_album_art(gwps, aa->draw_handle, false);
+        aa->draw_handle = -1;
     }
 #endif
 
@@ -442,8 +445,8 @@ int evaluate_conditional(struct gui_wps *gwps, int offset,
 
     int intval = num_options < 2 ? 2 : num_options;
     /* get_token_value needs to know the number of options in the enum */
-    value = get_token_value(gwps, conditional->token, offset,
-                            result, sizeof(result), &intval);
+    value = get_token_value(gwps, SKINOFFSETTOPTR(skin_buffer, conditional->token),
+                    offset, result, sizeof(result), &intval);
 
     /* intval is now the number of the enum option we want to read,
        starting from 1. If intval is -1, we check if value is empty. */
diff --git a/apps/gui/skin_engine/skin_engine.c b/apps/gui/skin_engine/skin_engine.c
index bd875fe..1e0304c 100644
--- a/apps/gui/skin_engine/skin_engine.c
+++ b/apps/gui/skin_engine/skin_engine.c
@@ -48,7 +48,7 @@ void theme_init_buffer(void)
     skins_initialising = false;
 }
 #else
-static char skin_buffer[SKIN_BUFFER_SIZE];
+char skin_buffer[SKIN_BUFFER_SIZE];
 void theme_init_buffer(void)
 {
     skins_initialising = false;
@@ -95,8 +95,13 @@ void gui_sync_skin_init(void)
             skins[j][i].gui_wps.display = &screens[i];
             memset(skins[j][i].gui_wps.data, 0, sizeof(struct wps_data));
             skins[j][i].data.wps_loaded = false;
+            skins[j][i].data.tree = PTRTOSKINOFFSET(skin_buffer, NULL);
+#ifdef HAVE_LCD_BITMAP
+            skins[j][i].data.font_ids = PTRTOSKINOFFSET(skin_buffer, NULL);
+            skins[j][i].data.images = PTRTOSKINOFFSET(skin_buffer, NULL);
+#endif
 #ifdef HAVE_ALBUMART
-            skins[j][i].data.albumart = NULL;
+            skins[j][i].data.albumart = PTRTOSKINOFFSET(skin_buffer, NULL);
             skins[j][i].data.playback_aa_slot = -1;
 #endif
         }
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index d207a1f..de25216 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -78,11 +78,35 @@
 
 #define GLYPHS_TO_CACHE 256
 
+#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
+static char *backdrop_filename;
+#endif
+
 static bool isdefault(struct skin_tag_parameter *param)
 {
     return param->type == DEFAULT;
 }
 
+static inline char*
+get_param_text(struct skin_element *element, int param_number)
+{
+    struct skin_tag_parameter* params = SKINOFFSETTOPTR(skin_buffer, element->params);
+    return SKINOFFSETTOPTR(skin_buffer, params[param_number].data.text);
+}
+
+static inline struct skin_element*
+get_param_code(struct skin_element *element, int param_number)
+{
+    struct skin_tag_parameter* params = SKINOFFSETTOPTR(skin_buffer, element->params);
+    return SKINOFFSETTOPTR(skin_buffer, params[param_number].data.code);
+}
+
+static inline struct skin_tag_parameter*
+get_param(struct skin_element *element, int param_number)
+{
+    struct skin_tag_parameter* params = SKINOFFSETTOPTR(skin_buffer, element->params);
+    return &params[param_number];
+}
 
 /* which screen are we parsing for? */
 static enum screen_type curr_screen;
@@ -103,16 +127,19 @@ typedef int (*parse_function)(struct skin_element *element,
 /* add a skin_token_list item to the list chain. ALWAYS appended because some of the
  * chains require the order to be kept.
  */
-static void add_to_ll_chain(struct skin_token_list **list, struct skin_token_list *item)
+static void add_to_ll_chain(skinoffset *listoffset, struct skin_token_list *item)
 {
-    if (*list == NULL)
-        *list = item;
+    struct skin_token_list *list = SKINOFFSETTOPTR(skin_buffer, *listoffset);
+    if (list == NULL)
+    {
+        list = item;
+        *listoffset = PTRTOSKINOFFSET(skin_buffer, list);
+    }
     else
     {
-        struct skin_token_list *t = *list;
-        while (t->next)
-            t = t->next;
-        t->next = item;
+        while (SKINOFFSETTOPTR(skin_buffer, list->next))
+            list = SKINOFFSETTOPTR(skin_buffer, list->next);
+        list->next = PTRTOSKINOFFSET(skin_buffer, item);
     }
 }
 
@@ -133,22 +160,22 @@ void *skin_find_item(const char *label, enum skin_find_what what,
     {
         case SKIN_FIND_UIVP:
         case SKIN_FIND_VP:
-            list.vplist = data->tree;
+            list.vplist = SKINOFFSETTOPTR(skin_buffer, data->tree);
             isvplist = true;
         break;
 #ifdef HAVE_LCD_BITMAP
         case SKIN_FIND_IMAGE:
-            list.linkedlist = data->images;
+            list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->images);
         break;
 #endif
 #ifdef HAVE_TOUCHSCREEN
         case SKIN_FIND_TOUCHREGION:
-            list.linkedlist = data->touchregions;
+            list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->touchregions);
         break;
 #endif
 #ifdef HAVE_SKIN_VARIABLES
         case SKIN_VARIABLE:
-            list.linkedlist = data->skinvars;
+            list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->skinvars);
         break;
 #endif
     }
@@ -156,31 +183,37 @@ void *skin_find_item(const char *label, enum skin_find_what what,
     while (list.linkedlist)
     {
         bool skip = false;
+        struct wps_token *token = NULL;
+        if (!isvplist)
+            token = SKINOFFSETTOPTR(skin_buffer, list.linkedlist->token);
         switch (what)
         {
             case SKIN_FIND_UIVP:
             case SKIN_FIND_VP:
-                ret = list.vplist->data;
-                itemlabel = ((struct skin_viewport *)ret)->label;
+                ret = SKINOFFSETTOPTR(skin_buffer, 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);
                 skip = !(((struct skin_viewport *)ret)->is_infovp == 
                     (what==SKIN_FIND_UIVP));
                 break;
 #ifdef HAVE_LCD_BITMAP
             case SKIN_FIND_IMAGE:
-                ret = list.linkedlist->token->value.data;
-                itemlabel = ((struct gui_img *)ret)->label;
+                ret = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+                itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct gui_img *)ret)->label);
                 break;
 #endif
 #ifdef HAVE_TOUCHSCREEN
             case SKIN_FIND_TOUCHREGION:
-                ret = list.linkedlist->token->value.data;
-                itemlabel = ((struct touchregion *)ret)->label;
+                ret = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+                itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct touchregion *)ret)->label);
                 break;
 #endif
 #ifdef HAVE_SKIN_VARIABLES
             case SKIN_VARIABLE:
-                ret = list.linkedlist->token->value.data;
-                itemlabel = ((struct skin_var *)ret)->label;
+                ret = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+                itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct skin_var *)ret)->label);
                 break;
 #endif
                 
@@ -189,9 +222,9 @@ void *skin_find_item(const char *label, enum skin_find_what what,
             return ret;
         
         if (isvplist)
-            list.vplist = list.vplist->next;
+            list.vplist = SKINOFFSETTOPTR(skin_buffer, list.vplist->next);
         else
-            list.linkedlist = list.linkedlist->next;
+            list.linkedlist = SKINOFFSETTOPTR(skin_buffer, list.linkedlist->next);
     }
     return NULL;
 }
@@ -212,10 +245,10 @@ static struct skin_token_list *new_skin_token_list_item(struct wps_token *token,
         token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token));
     if (!llitem || !token)
         return NULL;
-    llitem->next = NULL;
-    llitem->token = token;
+    llitem->next = PTRTOSKINOFFSET(skin_buffer, NULL);
+    llitem->token = PTRTOSKINOFFSET(skin_buffer, token);
     if (token_data)
-        llitem->token->value.data = token_data;
+        token->value.data = PTRTOSKINOFFSET(skin_buffer, token_data);
     return llitem;
 }
 
@@ -226,12 +259,12 @@ static int parse_statusbar_tags(struct skin_element* element,
     (void)element;
     if (token->type == SKIN_TOKEN_DRAW_INBUILTBAR)
     {
-        token->value.data = (void*)&curr_vp->vp;
+        token->value.data = PTRTOSKINOFFSET(skin_buffer, (void*)&curr_vp->vp);
     }
     else
     {
-        struct skin_element *def_vp = wps_data->tree;
-        struct skin_viewport *default_vp = def_vp->data;
+        struct skin_element *def_vp = SKINOFFSETTOPTR(skin_buffer, wps_data->tree);
+        struct skin_viewport *default_vp = SKINOFFSETTOPTR(skin_buffer, def_vp->data);
         if (def_vp->params_count == 0)
         {
             wps_data->wps_sb_tag = true;
@@ -279,7 +312,7 @@ static int parse_image_display(struct skin_element *element,
                                struct wps_token *token,
                                struct wps_data *wps_data)
 {
-    char *label = element->params[0].data.text;
+    char *label = get_param_text(element, 0);
     char sublabel = '\0';
     int subimage;
     struct gui_img *img;
@@ -297,9 +330,9 @@ static int parse_image_display(struct skin_element *element,
     {
         return WPS_ERROR_INVALID_PARAM;
     }
-    id->label = label;
+    id->label = PTRTOSKINOFFSET(skin_buffer, label);
     id->offset = 0;
-    id->token = NULL;
+    id->token = PTRTOSKINOFFSET(skin_buffer, NULL);
     if (img->using_preloaded_icons)
     {
         token->type = SKIN_TOKEN_IMAGE_DISPLAY_LISTICON;
@@ -307,13 +340,13 @@ static int parse_image_display(struct skin_element *element,
     
     if (element->params_count > 1)
     {
-        if (element->params[1].type == CODE)
-            id->token = element->params[1].data.code->data;
+        if (get_param(element, 1)->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 (element->params[1].type == INTEGER)
-            id->subimage = element->params[1].data.number - 1;
+        else if (get_param(element, 1)->type == INTEGER)
+            id->subimage = get_param(element, 1)->data.number - 1;
         if (element->params_count > 2)
-            id->offset = element->params[2].data.number;
+            id->offset = get_param(element, 2)->data.number;
     }
     else
     {
@@ -326,7 +359,7 @@ static int parse_image_display(struct skin_element *element,
             id->subimage = 0;
         }
     }
-    token->value.data = id;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, id);
     return 0;
 }
 
@@ -344,10 +377,10 @@ static int parse_image_load(struct skin_element *element,
        or %xl(n,filename.bmp,x,y,num_subimages)
     */
 
-    id = element->params[0].data.text;
-    filename = element->params[1].data.text;
-    x = element->params[2].data.number;
-    y = element->params[3].data.number;
+    id = get_param_text(element, 0);
+    filename = get_param_text(element, 1);
+    x = get_param(element, 2)->data.number;
+    y = get_param(element, 3)->data.number;
 
     /* check the image number and load state */
     if(skin_find_item(id, SKIN_FIND_IMAGE, wps_data))
@@ -360,7 +393,7 @@ static int parse_image_load(struct skin_element *element,
         return WPS_ERROR_INVALID_PARAM;
     /* save a pointer to the filename */
     img->bm.data = (char*)filename;
-    img->label = id;
+    img->label = PTRTOSKINOFFSET(skin_buffer, id);
     img->x = x;
     img->y = y;
     img->num_subimages = 1;
@@ -370,7 +403,7 @@ static int parse_image_load(struct skin_element *element,
     img->buflib_handle = -1;
 
     /* save current viewport */
-    img->vp = &curr_vp->vp;
+    img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
 
     if (token->type == SKIN_TOKEN_IMAGE_DISPLAY)
     {
@@ -378,7 +411,7 @@ static int parse_image_load(struct skin_element *element,
     }
     else if (element->params_count == 5)
     {
-        img->num_subimages = element->params[4].data.number;
+        img->num_subimages = get_param(element, 4)->data.number;
         if (img->num_subimages <= 0)
             return WPS_ERROR_INVALID_PARAM;
     }
@@ -408,13 +441,13 @@ static int parse_font_load(struct skin_element *element,
                            struct wps_data *wps_data)
 {
     (void)wps_data; (void)token;
-    int id = element->params[0].data.number;
-    char *filename = element->params[1].data.text;
+    int id = get_param(element, 0)->data.number;
+    char *filename = get_param_text(element, 1);
     int  glyphs;
     char *ptr;
     
     if(element->params_count > 2)
-        glyphs = element->params[2].data.number;
+        glyphs = get_param(element, 2)->data.number;
     else
         glyphs = GLYPHS_TO_CACHE;
     if (id < 2)
@@ -452,12 +485,12 @@ static int parse_playlistview(struct skin_element *element,
         (struct playlistviewer *)skin_buffer_alloc(sizeof(struct playlistviewer));
     if (!viewer)
         return WPS_ERROR_INVALID_PARAM;
-    viewer->vp = &curr_vp->vp;
+    viewer->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
     viewer->show_icons = true;
-    viewer->start_offset = element->params[0].data.number;
-    viewer->line = element->params[1].data.code;
+    viewer->start_offset = get_param(element, 0)->data.number;
+    viewer->line = PTRTOSKINOFFSET(skin_buffer, get_param_code(element, 1));
     
-    token->value.data = (void*)viewer;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, (void*)viewer);
     
     return 0;
 }
@@ -474,12 +507,12 @@ static int parse_viewport_gradient_setup(struct skin_element *element,
     cfg = (struct gradient_config *)skin_buffer_alloc(sizeof(struct gradient_config)); 
     if (!cfg)
         return 1;
-    if (!parse_color(curr_screen, element->params[0].data.text, &cfg->start) ||
-        !parse_color(curr_screen, element->params[1].data.text, &cfg->end))
+    if (!parse_color(curr_screen, get_param_text(element, 0), &cfg->start) ||
+        !parse_color(curr_screen, get_param_text(element, 1), &cfg->end))
         return 1;
     if (element->params_count > 2)
     {
-        if (!parse_color(curr_screen, element->params[2].data.text, &cfg->text))
+        if (!parse_color(curr_screen, get_param_text(element, 2), &cfg->text))
             return 1;
     }
     else
@@ -487,7 +520,7 @@ static int parse_viewport_gradient_setup(struct skin_element *element,
         cfg->text = curr_vp->vp.fg_pattern;
     }
 
-    token->value.data = cfg;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, cfg);
     return 0; 
 }
 #endif
@@ -500,14 +533,14 @@ static int parse_listitem(struct skin_element *element,
     struct listitem *li = (struct listitem *)skin_buffer_alloc(sizeof(struct listitem));
     if (!li)
         return 1;
-    token->value.data = li;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, li);
     if (element->params_count == 0)
         li->offset = 0;
     else
     {
-        li->offset = element->params[0].data.number;
+        li->offset = get_param(element, 0)->data.number;
         if (element->params_count > 1)
-            li->wrap = strcasecmp(element->params[1].data.text, "nowrap") != 0;
+            li->wrap = strcasecmp(get_param_text(element, 1), "nowrap") != 0;
         else
             li->wrap = true;
     }
@@ -526,17 +559,17 @@ static int parse_listitemviewport(struct skin_element *element,
         return -1;
     cfg->data = wps_data;
     cfg->tile = false;
-    cfg->label = element->params[0].data.text;
+    cfg->label = get_param_text(element, 0);
     cfg->width = -1;
     cfg->height = -1;
-    if (!isdefault(&element->params[1]))
-        cfg->width = element->params[1].data.number;
-    if (!isdefault(&element->params[2]))
-        cfg->height = element->params[2].data.number;
+    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;
     if (element->params_count > 3 &&
-        !strcmp(element->params[3].data.text, "tile"))
+        !strcmp(get_param_text(element, 3), "tile"))
         cfg->tile = true;
-    token->value.data = (void*)cfg;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, (void*)cfg);
 #endif
     return 0;
 }
@@ -548,7 +581,7 @@ static int parse_viewporttextstyle(struct skin_element *element,
 {
     (void)wps_data;
     int style;
-    char *mode = element->params[0].data.text;
+    char *mode = get_param_text(element, 0);
     unsigned colour;
     
     if (!strcmp(mode, "invert"))
@@ -558,7 +591,7 @@ static int parse_viewporttextstyle(struct skin_element *element,
     else if (!strcmp(mode, "colour") || !strcmp(mode, "color"))
     {
         if (element->params_count < 2 ||
-            !parse_color(curr_screen, element->params[1].data.text, &colour))
+            !parse_color(curr_screen, get_param_text(element, 1), &colour))
             return 1;
         style = STYLE_COLORED|(STYLE_COLOR_MASK&colour); 
     }
@@ -571,7 +604,7 @@ static int parse_viewporttextstyle(struct skin_element *element,
         else /* atoi() instead of using a number in the parser is because [si]
               * will select the number for something which looks like a colour
               * making the "colour" case (above) harder to parse */
-            num_lines = atoi(element->params[1].data.text);
+            num_lines = atoi(get_param_text(element, 1));
         style = STYLE_GRADIENT|NUMLN_PACK(num_lines)|CURLN_PACK(0);
     }
 #endif
@@ -590,7 +623,7 @@ static int parse_viewportcolour(struct skin_element *element,
                                 struct wps_data *wps_data)
 {
     (void)wps_data;
-    struct skin_tag_parameter *param = element->params;
+    struct skin_tag_parameter *param = get_param(element, 0);
     struct viewport_colour *colour = 
         (struct viewport_colour *)skin_buffer_alloc(sizeof(struct viewport_colour));
     if (!colour)
@@ -602,11 +635,12 @@ static int parse_viewportcolour(struct skin_element *element,
     }
     else
     {
-        if (!parse_color(curr_screen, param->data.text, &colour->colour))
+        if (!parse_color(curr_screen, SKINOFFSETTOPTR(skin_buffer, param->data.text),
+                    &colour->colour))
             return -1;
     }
-    colour->vp = &curr_vp->vp;
-    token->value.data = colour;
+    colour->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, colour);
     if (element->line == curr_viewport_element->line)
     {
         if (token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR)
@@ -634,18 +668,18 @@ static int parse_image_special(struct skin_element *element,
     char *filename;
     if (token->type == SKIN_TOKEN_IMAGE_BACKDROP)
     {
-        if (isdefault(&element->params[0]))
+        if (isdefault(get_param(element, 0)))
         {
             filename = "-";
         }
         else
         {
-            filename = element->params[0].data.text;
+            filename = get_param_text(element, 0);
             /* format: %X(filename.bmp) or %X(d) */
             if (!strcmp(filename, "d"))
                 filename = NULL;
         }
-        wps_data->backdrop = filename;
+        backdrop_filename = filename;
     }
 #endif
 
@@ -665,7 +699,7 @@ static int parse_setting_and_lang(struct skin_element *element,
      * If that ever changes remove the #ifndef __PCTOOL__'s here 
      */
     (void)wps_data;
-    char *temp = element->params[0].data.text;
+    char *temp = get_param_text(element, 0);
     int i;
     
     if (token->type == SKIN_TOKEN_TRANSLATEDSTRING)
@@ -692,12 +726,12 @@ static int parse_logical_if(struct skin_element *element,
                              struct wps_data *wps_data)
 {
     (void)wps_data;
-    char *op = element->params[1].data.text;
+    char *op = get_param_text(element, 1);
     struct logical_if *lif = skin_buffer_alloc(sizeof(struct logical_if));
     if (!lif)
         return -1;
-    token->value.data = lif;
-    lif->token = element->params[0].data.code->data;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, lif);
+    lif->token = PTRTOSKINOFFSET(skin_buffer, get_param_code(element, 0)->data);
     
     if (!strncmp(op, "=", 1))
         lif->op = IF_EQUALS;
@@ -712,9 +746,9 @@ static int parse_logical_if(struct skin_element *element,
     else if (!strncmp(op, "<", 1))
         lif->op = IF_LESSTHAN;
     
-    memcpy(&lif->operand, &element->params[2], sizeof(lif->operand));
+    memcpy(&lif->operand, get_param(element, 2), sizeof(lif->operand));
     if (element->params_count > 3)
-        lif->num_options = element->params[3].data.number;
+        lif->num_options = get_param(element, 3)->data.number;
     else
         lif->num_options = TOKEN_VALUE_ONLY;
     return 0;
@@ -743,7 +777,7 @@ static int parse_timeout_tag(struct skin_element *element,
         }
     }
     else
-        val = element->params[0].data.number;
+        val = get_param(element, 0)->data.number;
     token->value.i = val * TIMEOUT_UNIT;
     return 0;
 }
@@ -756,13 +790,13 @@ static int parse_substring_tag(struct skin_element* element,
     struct substring *ss = (struct substring*)skin_buffer_alloc(sizeof(struct substring));
     if (!ss)
         return 1;
-    ss->start = element->params[0].data.number;
-    if (element->params[1].type == DEFAULT)
+    ss->start = get_param(element, 0)->data.number;
+    if (get_param(element, 1)->type == DEFAULT)
         ss->length = -1;
     else
-        ss->length = element->params[1].data.number;
-    ss->token = element->params[2].data.code->data;
-    token->value.data = ss;
+        ss->length = get_param(element, 1)->data.number;
+    ss->token = PTRTOSKINOFFSET(skin_buffer, get_param_code(element, 2)->data);
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, ss);
     return 0;
 }
 
@@ -773,7 +807,7 @@ static int parse_progressbar_tag(struct skin_element* element,
 #ifdef HAVE_LCD_BITMAP
     struct progressbar *pb;
     struct viewport *vp = &curr_vp->vp;
-    struct skin_tag_parameter *param = element->params;
+    struct skin_tag_parameter *param = get_param(element, 0);
     int curr_param = 0;
     char *image_filename = NULL;
     
@@ -782,17 +816,17 @@ static int parse_progressbar_tag(struct skin_element* element,
         return 0; /* nothing to do */
     pb = (struct progressbar*)skin_buffer_alloc(sizeof(struct progressbar));
     
-    token->value.data = pb;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, pb);
     
     if (!pb)
         return WPS_ERROR_INVALID_PARAM;
-    pb->vp = vp;
+    pb->vp = PTRTOSKINOFFSET(skin_buffer, vp);
     pb->follow_lang_direction = follow_lang_direction > 0;
     pb->nofill = false;
     pb->nobar = false;
-    pb->image = NULL;
-    pb->slider = NULL;
-    pb->backdrop = NULL;
+    pb->image = PTRTOSKINOFFSET(skin_buffer, NULL);
+    pb->slider = PTRTOSKINOFFSET(skin_buffer, NULL);
+    pb->backdrop = PTRTOSKINOFFSET(skin_buffer, NULL);
     pb->invert_fill_direction = false;
     pb->horizontal = true;
     
@@ -849,7 +883,7 @@ static int parse_progressbar_tag(struct skin_element* element,
     /* optional params, first is the image filename if it isnt recognised as a keyword */
     
     curr_param = 4;
-    if (isdefault(&element->params[curr_param]))
+    if (isdefault(get_param(element, curr_param)))
     {
         param++;
         curr_param++;
@@ -858,75 +892,79 @@ static int parse_progressbar_tag(struct skin_element* element,
     pb->horizontal = pb->width > pb->height;
     while (curr_param < element->params_count)
     {
+        char* text;
         param++;
-        if (!strcmp(param->data.text, "invert"))
+        text = SKINOFFSETTOPTR(skin_buffer, param->data.text);
+        if (!strcmp(text, "invert"))
             pb->invert_fill_direction = true;
-        else if (!strcmp(param->data.text, "nofill"))
+        else if (!strcmp(text, "nofill"))
             pb->nofill = true;
-        else if (!strcmp(param->data.text, "nobar"))
+        else if (!strcmp(text, "nobar"))
             pb->nobar = true;
-        else if (!strcmp(param->data.text, "slider"))
+        else if (!strcmp(text, "slider"))
         {
             if (curr_param+1 < element->params_count)
             {
                 curr_param++;
                 param++;
-                pb->slider = skin_find_item(param->data.text, 
-                                            SKIN_FIND_IMAGE, wps_data);
+                text = SKINOFFSETTOPTR(skin_buffer, param->data.text);
+                pb->slider = PTRTOSKINOFFSET(skin_buffer,
+                        skin_find_item(text, SKIN_FIND_IMAGE, wps_data));
             }
             else /* option needs the next param */
                 return -1;
         }
-        else if (!strcmp(param->data.text, "image"))
+        else if (!strcmp(text, "image"))
         {
             if (curr_param+1 < element->params_count)
             {
                 curr_param++;
                 param++;
-                image_filename = param->data.text;
-                
+                image_filename = SKINOFFSETTOPTR(skin_buffer, param->data.text);
             }
             else /* option needs the next param */
                 return -1;
         }
-        else if (!strcmp(param->data.text, "backdrop"))
+        else if (!strcmp(text, "backdrop"))
         {
             if (curr_param+1 < element->params_count)
             {
                 curr_param++;
                 param++;
-                pb->backdrop = skin_find_item(param->data.text, 
-                                              SKIN_FIND_IMAGE, wps_data);
+                text = SKINOFFSETTOPTR(skin_buffer, param->data.text);
+                pb->backdrop = PTRTOSKINOFFSET(skin_buffer, 
+                        skin_find_item(text, SKIN_FIND_IMAGE, wps_data));
                 
             }
             else /* option needs the next param */
                 return -1;
         }
-        else if (!strcmp(param->data.text, "vertical"))
+        else if (!strcmp(text, "vertical"))
         {
             pb->horizontal = false;
-            if (isdefault(&element->params[3]))
+            if (isdefault(get_param(element, 3)))
                 pb->height = vp->height - pb->y;
         }
-        else if (!strcmp(param->data.text, "horizontal"))
+        else if (!strcmp(text, "horizontal"))
             pb->horizontal = true;
         else if (curr_param == 4)
-            image_filename = param->data.text;
+            image_filename = text;
             
         curr_param++;
     }
 
     if (image_filename)
     {
-        pb->image = skin_find_item(image_filename, SKIN_FIND_IMAGE, wps_data);
-        if (!pb->image) /* load later */
+        pb->image = PTRTOSKINOFFSET(skin_buffer, 
+                skin_find_item(image_filename, SKIN_FIND_IMAGE, wps_data));
+        if (!SKINOFFSETTOPTR(skin_buffer, pb->image)) /* load later */
         {           
             struct gui_img* img = (struct gui_img*)skin_buffer_alloc(sizeof(struct gui_img));
             if (!img)
                 return WPS_ERROR_INVALID_PARAM;
             /* save a pointer to the filename */
             img->bm.data = (char*)image_filename;
-            img->label = image_filename;
+            img->label = PTRTOSKINOFFSET(skin_buffer, image_filename);
             img->x = 0;
             img->y = 0;
             img->num_subimages = 1;
@@ -934,13 +972,13 @@ static int parse_progressbar_tag(struct skin_element* element,
             img->display = -1;
             img->using_preloaded_icons = false;
             img->buflib_handle = -1;
-            img->vp = &curr_vp->vp;
+            img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
             struct skin_token_list *item = 
                     (struct skin_token_list *)new_skin_token_list_item(NULL, img);
             if (!item)
                 return WPS_ERROR_INVALID_PARAM;
             add_to_ll_chain(&wps_data->images, item);
-            pb->image = img;
+            pb->image = PTRTOSKINOFFSET(skin_buffer, img);
         }
     }    
         
@@ -993,12 +1031,12 @@ 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 = element->params[0].data.number;
-    aa->y = element->params[1].data.number;
-    aa->width = element->params[2].data.number;
-    aa->height = element->params[3].data.number;
+    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;
     
-    aa->vp = &curr_vp->vp;
+    aa->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
     aa->draw_handle = -1;
 
     /* if we got here, we parsed everything ok .. ! */
@@ -1016,7 +1054,7 @@ static int parse_albumart_load(struct skin_element* element,
         aa->x = LCD_WIDTH - (aa->x + aa->width);
 
     aa->state = WPS_ALBUMART_LOAD;
-    wps_data->albumart = aa;
+    wps_data->albumart = PTRTOSKINOFFSET(skin_buffer, aa);
 
     dimensions.width = aa->width;
     dimensions.height = aa->height;
@@ -1026,9 +1064,9 @@ static int parse_albumart_load(struct skin_element* element,
     if (0 <= albumart_slot)
         wps_data->playback_aa_slot = albumart_slot;
         
-    if (element->params_count > 4 && !isdefault(&element->params[4]))
+    if (element->params_count > 4 && !isdefault(get_param(element, 4)))
     {
-        switch (*element->params[4].data.text)
+        switch (*get_param_text(element, 4))
         {
             case 'l':
             case 'L':
@@ -1050,9 +1088,9 @@ static int parse_albumart_load(struct skin_element* element,
                 break;
         }
     }
-    if (element->params_count > 5 && !isdefault(&element->params[5]))
+    if (element->params_count > 5 && !isdefault(get_param(element, 5)))
     {
-        switch (*element->params[5].data.text)
+        switch (*get_param_text(element, 5))
         {
             case 't':
             case 'T':
@@ -1082,7 +1120,7 @@ static struct skin_var* find_or_add_var(const char* label,
         ret = (struct skin_var*)skin_buffer_alloc(sizeof(struct skin_var));
         if (!ret)
             return NULL;
-        ret->label = label;
+        ret->label = PTRTOSKINOFFSET(skin_buffer, label);
         ret->value = 1;
         ret->last_changed = 0xffff;
         struct skin_token_list *item = new_skin_token_list_item(NULL, ret);
@@ -1096,14 +1134,14 @@ static int parse_skinvar(  struct skin_element *element,
                            struct wps_token *token,
                            struct wps_data *wps_data)
 {
-    const char* label = element->params[0].data.text;
+    const char* label = get_param_text(element, 0);
     struct skin_var* var = find_or_add_var(label, wps_data);
     if (!var)
         return WPS_ERROR_INVALID_PARAM;
     switch (token->type)
     {
         case SKIN_TOKEN_VAR_GETVAL:
-            token->value.data = var;
+            token->value.data = PTRTOSKINOFFSET(skin_buffer, var);
             break;
         case SKIN_TOKEN_VAR_SET:
         {
@@ -1112,23 +1150,23 @@ static int parse_skinvar(  struct skin_element *element,
                                             sizeof(struct skin_var_changer));
             if (!data)
                 return WPS_ERROR_INVALID_PARAM;
-            data->var = var;
-            data->newval = element->params[2].data.number;
+            data->var = PTRTOSKINOFFSET(skin_buffer, var);
+            data->newval = get_param(element, 2)->data.number;
             data->max = 0;
-            if (!strcmp(element->params[1].data.text, "set"))
+            if (!strcmp(get_param_text(element, 1), "set"))
                 data->direct = true;
-            else if (!strcmp(element->params[1].data.text, "inc"))
+            else if (!strcmp(get_param_text(element, 1), "inc"))
             {
                 data->direct = false;
             }
-            else if (!strcmp(element->params[1].data.text, "dec"))
+            else if (!strcmp(get_param_text(element, 1), "dec"))
             {
                 data->direct = false;
                 data->newval *= -1;
             }
             if (element->params_count > 3)
-                data->max = element->params[3].data.number;
-            token->value.data = data;
+                data->max = get_param(element, 3)->data.number;
+            token->value.data = PTRTOSKINOFFSET(skin_buffer, data);
         }
         break;
         case SKIN_TOKEN_VAR_TIMEOUT:
@@ -1138,12 +1176,12 @@ static int parse_skinvar(  struct skin_element *element,
                                             sizeof(struct skin_var_lastchange));
             if (!data)
                 return WPS_ERROR_INVALID_PARAM;
-            data->var = var;
+            data->var = PTRTOSKINOFFSET(skin_buffer, var);
             data->timeout = 10;
             if (element->params_count > 1)
-                data->timeout = element->params[1].data.number;
+                data->timeout = get_param(element, 1)->data.number;
             data->timeout *= TIMEOUT_UNIT;
-            token->value.data = data;
+            token->value.data = PTRTOSKINOFFSET(skin_buffer, data);
         }
         break;
         default: /* kill the warning */
@@ -1161,23 +1199,25 @@ static int parse_lasttouch(struct skin_element *element,
             (struct touchregion_lastpress*)skin_buffer_alloc(
                                 sizeof(struct touchregion_lastpress));
     int i;
+    struct touchregion *region = NULL;
     if (!data)
         return WPS_ERROR_INVALID_PARAM;
-    data->region = NULL;
+    
     data->timeout = 10;
     
     for (i=0; i<element->params_count; i++)
     {
-        if (element->params[i].type == STRING)
-            data->region = skin_find_item(element->params[i].data.text,
+        if (get_param(element, i)->type == STRING)
+            region = skin_find_item(get_param_text(element, i),
                                           SKIN_FIND_TOUCHREGION, wps_data);
-        else if (element->params[i].type == INTEGER ||
-                 element->params[i].type == DECIMAL)
-            data->timeout = element->params[i].data.number;
+        else if (get_param(element, i)->type == INTEGER ||
+                 get_param(element, i)->type == DECIMAL)
+            data->timeout = get_param(element, i)->data.number;
     }
 
+    data->region = PTRTOSKINOFFSET(skin_buffer, region);
     data->timeout *= TIMEOUT_UNIT;
-    token->value.data = data;
+    token->value.data = PTRTOSKINOFFSET(skin_buffer, data);
     return 0;
 }
 
@@ -1221,7 +1261,7 @@ static int touchregion_setup_setting(struct skin_element *element, int param_no,
 {
 #ifndef __PCTOOL__
     int p = param_no;
-    char *name = element->params[p++].data.text;
+    char *name = get_param_text(element, p++);
     int j;
 
     region->setting_data.setting = find_setting_by_cfgname(name, &j);
@@ -1237,11 +1277,11 @@ static int touchregion_setup_setting(struct skin_element *element, int param_no,
         if (element->params_count < p+1)
             return -1;
 
-        text = element->params[p++].data.text;
+        text = get_param_text(element, p++);
         switch (settings[j].flags&F_T_MASK)
         {
         case F_T_CUSTOM:
-            setting->value.text = text;
+            setting->value.text = PTRTOSKINOFFSET(skin_buffer, text);
             break;                              
         case F_T_INT:
         case F_T_UINT:
@@ -1301,34 +1341,34 @@ static int parse_touchregion(struct skin_element *element,
     /* should probably do some bounds checking here with the viewport... but later */
     region->action = ACTION_NONE;
     
-    if (element->params[0].type == STRING)
+    if (get_param(element, 0)->type == STRING)
     {
-        region->label = element->params[0].data.text;
+        region->label = PTRTOSKINOFFSET(skin_buffer, get_param_text(element, 0));
         p = 1;
         /* "[SI]III[SI]|SS" is the param list. There MUST be 4 numbers
          * followed by at least one string. Verify that here */
         if (element->params_count < 6 ||
-            element->params[4].type != INTEGER)
+            get_param(element, 4)->type != INTEGER)
             return WPS_ERROR_INVALID_PARAM;
     }
     else
     {
-        region->label = NULL;
+        region->label = PTRTOSKINOFFSET(skin_buffer, NULL);
         p = 0;
     }
     
-    region->x = element->params[p++].data.number;
-    region->y = element->params[p++].data.number;
-    region->width = element->params[p++].data.number;
-    region->height = element->params[p++].data.number;
-    region->wvp = curr_vp;
+    region->x = get_param(element, p++)->data.number;
+    region->y = get_param(element, p++)->data.number;
+    region->width = get_param(element, p++)->data.number;
+    region->height = get_param(element, p++)->data.number;
+    region->wvp = PTRTOSKINOFFSET(skin_buffer, curr_vp);
     region->armed = false;
     region->reverse_bar = false;
     region->value = 0;
     region->last_press = 0xffff;
     region->press_length = PRESS;
     region->allow_while_locked = false;
-    action = element->params[p++].data.text;
+    action = get_param_text(element, p++);
 
     /* figure out the action */
     if(!strcmp(pb_string, action))
@@ -1364,7 +1404,7 @@ static int parse_touchregion(struct skin_element *element,
     }
     while (p < element->params_count)
     {
-        char* param = element->params[p++].data.text;
+        char* param = get_param_text(element, p++);
         if (!strcmp(param, "allow_while_locked"))
             region->allow_while_locked = true;
         else if (!strcmp(param, "reverse_bar"))
@@ -1441,21 +1481,23 @@ void skin_data_free_buflib_allocs(struct wps_data *wps_data)
     (void)wps_data;
 #ifdef HAVE_LCD_BITMAP
 #ifndef __PCTOOL__
-    struct skin_token_list *list = wps_data->images;
+    struct skin_token_list *list = SKINOFFSETTOPTR(skin_buffer, wps_data->images);
+    int *font_ids = SKINOFFSETTOPTR(skin_buffer, wps_data->font_ids);
     while (list)
     {
-        struct gui_img *img = (struct gui_img*)list->token->value.data;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, list->token);
+        struct gui_img *img = (struct gui_img*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
         if (img->buflib_handle > 0)
             core_free(img->buflib_handle);
-        list = list->next;
+        list = SKINOFFSETTOPTR(skin_buffer, list->next);
     }
-    wps_data->images = NULL;
-    if (wps_data->font_ids != NULL)
+    wps_data->images = PTRTOSKINOFFSET(skin_buffer, NULL);
+    if (font_ids != NULL)
     {
         while (wps_data->font_count > 0)
-            font_unload(wps_data->font_ids[--wps_data->font_count]);
+            font_unload(font_ids[--wps_data->font_count]);
     }
-    wps_data->font_ids = NULL;
+    wps_data->font_ids = PTRTOSKINOFFSET(skin_buffer, NULL);
 #endif
 #endif
 }
@@ -1469,22 +1511,22 @@ static void skin_data_reset(struct wps_data *wps_data)
 {
     skin_data_free_buflib_allocs(wps_data);
 #ifdef HAVE_LCD_BITMAP
-    wps_data->images = NULL;
+    wps_data->images = PTRTOSKINOFFSET(skin_buffer, NULL);
 #endif
-    wps_data->tree = NULL;
+    wps_data->tree = PTRTOSKINOFFSET(skin_buffer, NULL);
 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
     if (wps_data->backdrop_id >= 0)
         skin_backdrop_unload(wps_data->backdrop_id);
-    wps_data->backdrop = NULL;
+    backdrop_filename = NULL;
 #endif
 #ifdef HAVE_TOUCHSCREEN
-    wps_data->touchregions = NULL;
+    wps_data->touchregions = PTRTOSKINOFFSET(skin_buffer, NULL);
 #endif
 #ifdef HAVE_SKIN_VARIABLES
-    wps_data->skinvars = NULL;
+    wps_data->skinvars = PTRTOSKINOFFSET(skin_buffer, NULL);
 #endif
 #ifdef HAVE_ALBUMART
-    wps_data->albumart = NULL;
+    wps_data->albumart = PTRTOSKINOFFSET(skin_buffer, NULL);
     if (wps_data->playback_aa_slot >= 0)
     {
         playback_release_aa_slot(wps_data->playback_aa_slot);
@@ -1598,16 +1640,17 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
     bool retval = true; /* return false if a single image failed to load */
     
     /* regular images */
-    list = wps_data->images;
+    list = SKINOFFSETTOPTR(skin_buffer, wps_data->images);
     while (list)
     {
-        struct gui_img *img = (struct gui_img*)list->token->value.data;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, list->token);
+        struct gui_img *img = (struct gui_img*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
         if (img->bm.data)
         {
             if (img->using_preloaded_icons)
             {
                 img->loaded = true;
-                list->token->type = SKIN_TOKEN_IMAGE_DISPLAY_LISTICON;
+                token->type = SKIN_TOKEN_IMAGE_DISPLAY_LISTICON;
             }
             else
             {
@@ -1619,11 +1662,11 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
                     retval = false;
             }
         }
-        list = list->next;
+        list = SKINOFFSETTOPTR(skin_buffer, list->next);
     }
 
 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
-    wps_data->backdrop_id = skin_backdrop_assign(wps_data->backdrop, bmpdir, curr_screen);
+    wps_data->backdrop_id = skin_backdrop_assign(backdrop_filename, bmpdir, curr_screen);
 #endif /* has backdrop support */
     return retval;
 }
@@ -1637,11 +1680,12 @@ static bool skin_load_fonts(struct wps_data *data)
     struct skin_element *vp_list;
     int font_id;
     /* walk though each viewport and assign its font */
-    for(vp_list = data->tree; vp_list; vp_list = vp_list->next)
+    for(vp_list = SKINOFFSETTOPTR(skin_buffer, data->tree);
+        vp_list; vp_list = SKINOFFSETTOPTR(skin_buffer, vp_list->next))
     {
         /* first, find the viewports that have a non-sys/ui-font font */
         struct skin_viewport *skin_vp =
-                (struct skin_viewport*)vp_list->data;
+                SKINOFFSETTOPTR(skin_buffer, vp_list->data);
         struct viewport *vp = &skin_vp->vp;
 
         font_id = skin_vp->parsed_fontid;
@@ -1697,19 +1741,20 @@ static bool skin_load_fonts(struct wps_data *data)
         /* finally, assign the font_id to the viewport */
         vp->font = font->id;
     }
-    data->font_ids = skin_buffer_alloc(font_count * sizeof(int));
-    if (!success || data->font_ids == NULL)
+    int *font_ids = skin_buffer_alloc(font_count * sizeof(int));
+    if (!success || font_ids == NULL)
     {
         while (font_count > 0)
         {
             if(id_array[--font_count] != -1)
                 font_unload(id_array[font_count]);
         }
-        data->font_ids = NULL;
+        data->font_ids = PTRTOSKINOFFSET(skin_buffer, NULL);
         return false;
     }
-    memcpy(data->font_ids, id_array, sizeof(int)*font_count);
+    memcpy(font_ids, id_array, sizeof(int)*font_count);
     data->font_count = font_count;
+    data->font_ids = PTRTOSKINOFFSET(skin_buffer, font_ids);
     return success;
 }
 
@@ -1724,10 +1769,10 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element)
         return CALLBACK_ERROR;
         
     skin_vp->hidden_flags = 0;
-    skin_vp->label = NULL;
+    skin_vp->label = PTRTOSKINOFFSET(skin_buffer, NULL);
     skin_vp->is_infovp = false;
     skin_vp->parsed_fontid = 1;
-    element->data = skin_vp;
+    element->data = PTRTOSKINOFFSET(skin_buffer, skin_vp);
     curr_vp = skin_vp;
     curr_viewport_element = element;
     
@@ -1744,11 +1789,11 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element)
 #endif
     
 
-    struct skin_tag_parameter *param = element->params;
+    struct skin_tag_parameter *param = get_param(element, 0);
     if (element->params_count == 0) /* default viewport */
     {
-        if (!data->tree) /* first viewport in the skin */
-            data->tree = element;
+        if (!SKINOFFSETTOPTR(skin_buffer, data->tree)) /* first viewport in the skin */
+            data->tree = PTRTOSKINOFFSET(skin_buffer, element);
         skin_vp->label = VP_DEFAULT_LABEL;
         return CALLBACK_OK;
     }
@@ -1858,7 +1903,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
             else
                 curr_line->update_mode |= element->tag->flags&SKIN_REFRESH_ALL;
             
-            element->data = token;
+            element->data = PTRTOSKINOFFSET(skin_buffer, token);
             
             /* Some tags need special handling for the tag, so add them here */
             switch (token->type)
@@ -1907,7 +1952,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
                     break;
 #endif
                 case SKIN_TOKEN_FILE_DIRECTORY:
-                    token->value.i = element->params[0].data.number;
+                    token->value.i = get_param(element, 0)->data.number;
                     break;
 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
                 case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
@@ -1939,7 +1984,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
                     break;
                 case SKIN_TOKEN_VIEWPORT_ENABLE:
                 case SKIN_TOKEN_UIVIEWPORT_ENABLE:
-                    token->value.data = element->params[0].data.text;
+                    token->value.data = PTRTOSKINOFFSET(skin_buffer, get_param_text(element, 0));
                     break;
                 case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
                     function = parse_image_display;
@@ -1962,8 +2007,11 @@ static int skin_element_callback(struct skin_element* element, void* data)
 #endif
 #ifdef HAVE_ALBUMART
                 case SKIN_TOKEN_ALBUMART_DISPLAY:
-                    if (wps_data->albumart)
-                        wps_data->albumart->vp = &curr_vp->vp;
+                    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;
@@ -2000,7 +2048,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
                 (struct line *)skin_buffer_alloc(sizeof(struct line));
             line->update_mode = SKIN_REFRESH_STATIC;
             curr_line = line;
-            element->data = line;
+            element->data = PTRTOSKINOFFSET(skin_buffer, line);
         }
         break;
         case LINE_ALTERNATOR:
@@ -2011,7 +2059,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
 #ifndef __PCTOOL__
             alternator->next_change_tick = current_tick;
 #endif
-            element->data = alternator;
+            element->data = PTRTOSKINOFFSET(skin_buffer, alternator);
         }
         break;
         case CONDITIONAL:
@@ -2020,7 +2068,7 @@ static int skin_element_callback(struct skin_element* element, void* data)
                 (struct conditional *)skin_buffer_alloc(sizeof(struct conditional));
             conditional->last_value = -1;
             conditional->token = element->data;
-            element->data = conditional;
+            element->data = PTRTOSKINOFFSET(skin_buffer, conditional);
             if (!check_feature_tag(element->tag->type))
             {
                 return FEATURE_NOT_AVAILABLE;
@@ -2049,11 +2097,12 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
     struct mp3entry *curtrack;
     long offset;
     struct skin_albumart old_aa = {.state = WPS_ALBUMART_NONE};
-    if (wps_data->albumart)
+    struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, wps_data->albumart);
+    if (aa)
     {
-        old_aa.state = wps_data->albumart->state;
-        old_aa.height = wps_data->albumart->height;
-        old_aa.width = wps_data->albumart->width;
+        old_aa.state = aa->state;
+        old_aa.height = aa->height;
+        old_aa.width = aa->width;
     }
 #endif
 #ifdef HAVE_LCD_BITMAP
@@ -2114,15 +2163,16 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
         wps_buffer = (char*)buf;
     }
 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
-    wps_data->backdrop = "-";
+    backdrop_filename = "-";
     wps_data->backdrop_id = -1;
 #endif
     /* parse the skin source */
 #ifndef APPLICATION
     skin_buffer_save_position();
 #endif
-    wps_data->tree = skin_parse(wps_buffer, skin_element_callback, wps_data);
-    if (!wps_data->tree) {
+    struct skin_element *tree = skin_parse(wps_buffer, skin_element_callback, wps_data);
+    wps_data->tree = PTRTOSKINOFFSET(skin_buffer, tree);
+    if (!SKINOFFSETTOPTR(skin_buffer, wps_data->tree)) {
         skin_data_reset(wps_data);
 #ifndef APPLICATION
         skin_buffer_restore_position();
@@ -2157,7 +2207,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
     status = audio_status();
     if (status & AUDIO_STATUS_PLAY)
     {
-        struct skin_albumart *aa = wps_data->albumart;
+        struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, wps_data->albumart);
         if (aa && ((aa->state && !old_aa.state) ||
             (aa->state &&
             (((old_aa.height != aa->height) ||
diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
index 4d41a6f..7a6df62 100644
--- a/apps/gui/skin_engine/skin_render.c
+++ b/apps/gui/skin_engine/skin_render.c
@@ -81,6 +81,14 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer,
                                        unsigned long refresh_type);
 #endif
 
+static inline struct skin_element*
+get_child(OFFSETTYPE(struct skin_element**) children, int child)
+{
+    struct skin_element **kids = SKINOFFSETTOPTR(skin_buffer, children);
+    return kids[child];
+}
+
+
 static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
                              struct skin_element *element, struct viewport* vp)
 {
@@ -88,7 +96,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
     (void)vp; /* silence warnings */
     (void)info;
 #endif    
-    struct wps_token *token = (struct wps_token *)element->data;
+    struct wps_token *token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, element->data);
 
 #ifdef HAVE_LCD_BITMAP
     struct wps_data *data = gwps->data;
@@ -99,14 +107,16 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
         case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
         {
-            struct viewport_colour *col = token->value.data;
-            col->vp->fg_pattern = col->colour;
+            struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp);
+            vp->fg_pattern = col->colour;
         }
         break;
         case SKIN_TOKEN_VIEWPORT_BGCOLOUR:
         {
-            struct viewport_colour *col = token->value.data;
-            col->vp->bg_pattern = col->colour;
+            struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp);
+            vp->bg_pattern = col->colour;
         }
         break;
         case SKIN_TOKEN_VIEWPORT_TEXTSTYLE:
@@ -116,7 +126,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
 #ifdef HAVE_LCD_COLOR
         case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP:
         {
-            struct gradient_config *cfg = token->value.data;
+            struct gradient_config *cfg = SKINOFFSETTOPTR(skin_buffer, token->value.data);
             vp->lss_pattern = cfg->start;
             vp->lse_pattern = cfg->end;
             vp->lst_pattern = cfg->text;
@@ -125,14 +135,18 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
 #endif
         case SKIN_TOKEN_VIEWPORT_ENABLE:
         {
-            char *label = token->value.data;
+            char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data);
             char temp = VP_DRAW_HIDEABLE;
-            struct skin_element *viewport = gwps->data->tree;
+            struct skin_element *viewport = SKINOFFSETTOPTR(skin_buffer, gwps->data->tree);
             while (viewport)
             {
-                struct skin_viewport *skinvp = (struct skin_viewport*)viewport->data;
-                if (skinvp->label && !skinvp->is_infovp &&
-                    !strcmp(skinvp->label, label))
+                struct skin_viewport *skinvp = SKINOFFSETTOPTR(skin_buffer, viewport->data);
+                
+                char *vplabel = SKINOFFSETTOPTR(skin_buffer, skinvp->label);
+                if (skinvp->label == VP_DEFAULT_LABEL)
+                    vplabel = VP_DEFAULT_LABEL_STRING;
+                if (vplabel && !skinvp->is_infovp &&
+                    !strcmp(vplabel, label))
                 {
                     if (skinvp->hidden_flags&VP_DRAW_HIDDEN)
                     {
@@ -140,7 +154,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
                     }    
                     skinvp->hidden_flags = temp;
                 }
-                viewport = viewport->next;
+                viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next);
             }
         }
         break;
@@ -148,11 +162,11 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
         case SKIN_TOKEN_LIST_ITEM_CFG:
             if (do_refresh)
                 skinlist_set_cfg(gwps->display->screen_type, 
-                                    token->value.data);
+                                    SKINOFFSETTOPTR(skin_buffer, token->value.data));
             break;
         case SKIN_TOKEN_UIVIEWPORT_ENABLE:
             sb_set_info_vp(gwps->display->screen_type, 
-                           token->value.data);
+                           SKINOFFSETTOPTR(skin_buffer, token->value.data));
             break;
         case SKIN_TOKEN_PEAKMETER:
             data->peak_meter_enabled = true;
@@ -173,7 +187,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
         case SKIN_TOKEN_TUNER_RSSI_BAR:
         case SKIN_TOKEN_LIST_SCROLLBAR:
         {
-            struct progressbar *bar = (struct progressbar*)token->value.data;
+            struct progressbar *bar = (struct progressbar*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
             if (do_refresh)
                 draw_progressbar(gwps, info->line_number, bar);
         }
@@ -183,12 +197,12 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
         case SKIN_TOKEN_IMAGE_DISPLAY_LISTICON:
         case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
         {
-            struct image_display *id = token->value.data;
-            const char* label = id->label;
+            struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            const char* label = SKINOFFSETTOPTR(skin_buffer, id->label);
             struct gui_img *img = skin_find_item(label,SKIN_FIND_IMAGE, data);
             if (img && img->loaded)
             {
-                if (id->token == NULL)
+                if (SKINOFFSETTOPTR(skin_buffer, id->token) == NULL)
                 {
                     img->display = id->subimage;
                 }
@@ -197,8 +211,8 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
                     char buf[16];
                     const char *out;
                     int a = img->num_subimages;
-                    out = get_token_value(gwps, id->token, info->offset, 
-                                          buf, sizeof(buf), &a);
+                    out = get_token_value(gwps, SKINOFFSETTOPTR(skin_buffer, id->token),
+                            info->offset, buf, sizeof(buf), &a);
 
                     /* NOTE: get_token_value() returns values starting at 1! */
                     if (a == -1)
@@ -224,29 +238,32 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
         }
 #ifdef HAVE_ALBUMART
         case SKIN_TOKEN_ALBUMART_DISPLAY:
+        {
+            struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart);
             /* now draw the AA */
-            if (do_refresh && data->albumart)
+            if (do_refresh && aa)
             {
                 int handle = playback_current_aa_hid(data->playback_aa_slot);
 #if CONFIG_TUNER
                 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
                 {
-                    struct dim dim = {data->albumart->width, data->albumart->height};
+                    struct dim dim = {aa->width, aa->height};
                     handle = radio_get_art_hid(&dim);
                 }
 #endif
-                data->albumart->draw_handle = handle;
+                aa->draw_handle = handle;
             }
             break;
+        }
 #endif
         case SKIN_TOKEN_DRAW_INBUILTBAR:
             gui_statusbar_draw(&(statusbars.statusbars[gwps->display->screen_type]),
                                info->refresh_type == SKIN_REFRESH_ALL,
-                               token->value.data);
+                               SKINOFFSETTOPTR(skin_buffer, token->value.data));
             break;
         case SKIN_TOKEN_VIEWPORT_CUSTOMLIST:
             if (do_refresh)
-                skin_render_playlistviewer(token->value.data, gwps,
+                skin_render_playlistviewer(SKINOFFSETTOPTR(skin_buffer, token->value.data), gwps,
                                            info->skin_vp, info->refresh_type);
             break;
         
@@ -255,23 +272,24 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
         case SKIN_TOKEN_VAR_SET:
             if (do_refresh)
             {
-                struct skin_var_changer *data = token->value.data;
+                struct skin_var_changer *data = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+                struct skin_var *var = SKINOFFSETTOPTR(skin_buffer, data->var);
                 if (data->direct)
-                    data->var->value = data->newval;
+                    var->value = data->newval;
                 else
                 {
-                    data->var->value += data->newval;
+                    var->value += data->newval;
                     if (data->max)
                     {
-                        if (data->var->value > data->max)
-                            data->var->value = 1;
-                        else if (data->var->value < 1)
-                            data->var->value = data->max;
+                        if (var->value > data->max)
+                            var->value = 1;
+                        else if (var->value < 1)
+                            var->value = data->max;
                     }
                 }
-                if (data->var->value < 1)
-                    data->var->value = 1;
-                data->var->last_changed = current_tick;
+                if (var->value < 1)
+                    var->value = 1;
+                var->last_changed = current_tick;
             }
             break;
 #endif
@@ -297,12 +315,12 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch,
         int i;
         for (i=0; i<branch->children_count; i++)
         {
-            do_tags_in_hidden_conditional(branch->children[i], info);
+            do_tags_in_hidden_conditional(get_child(branch->children, i), info);
         }
     }
     else if (branch->type == LINE && branch->children_count)
     {
-        struct skin_element *child = branch->children[0];
+        struct skin_element *child = get_child(branch->children, 0);
 #if defined(HAVE_LCD_BITMAP) || defined(HAVE_ALBUMART)
         struct wps_token *token;
 #endif
@@ -313,25 +331,25 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch,
                 int i;
                 for (i=0; i<child->children_count; i++)
                 {
-                    do_tags_in_hidden_conditional(child->children[i], info);
+                    do_tags_in_hidden_conditional(get_child(branch->children, i), info);
                 }
-                child = child->next;
+                child = SKINOFFSETTOPTR(skin_buffer, child->next);
                 continue;
             }
-            else if (child->type != TAG || !child->data)
+            else if (child->type != TAG || !SKINOFFSETTOPTR(skin_buffer, child->data))
             {
-                child = child->next;
+                child = SKINOFFSETTOPTR(skin_buffer, child->next);
                 continue;
             }
 #if defined(HAVE_LCD_BITMAP) || defined(HAVE_ALBUMART)
-            token = (struct wps_token *)child->data;
+            token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, child->data);
 #endif
 #ifdef HAVE_LCD_BITMAP
             /* clear all pictures in the conditional and nested ones */
             if (token->type == SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY)
             {
-                struct image_display *id = token->value.data;
-                struct gui_img *img = skin_find_item(id->label, 
+                struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+                struct gui_img *img = skin_find_item(SKINOFFSETTOPTR(skin_buffer, id->label), 
                                                      SKIN_FIND_IMAGE, data);
                 clear_image_pos(gwps, img);
             }
@@ -341,14 +359,18 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch,
             }
             else if (token->type == SKIN_TOKEN_VIEWPORT_ENABLE)
             {
-                char *label = token->value.data;
+                char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data);
                 struct skin_element *viewport;
-                for (viewport = data->tree;
+                for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
                      viewport;
-                     viewport = viewport->next)
+                     viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next))
                 {
-                    struct skin_viewport *skin_viewport = (struct skin_viewport*)viewport->data;
-                    if (skin_viewport->label && strcmp(skin_viewport->label, label))
+                    struct skin_viewport *skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
+                    
+                    char *vplabel = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label);
+                    if (skin_viewport->label == VP_DEFAULT_LABEL)
+                        vplabel = VP_DEFAULT_LABEL_STRING;
+                    if (vplabel && strcmp(vplabel, label))
                         continue;
                     if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
                     {
@@ -377,7 +399,7 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch,
                         playback_current_aa_hid(data->playback_aa_slot), true);
             }
 #endif
-            child = child->next;
+            child = SKINOFFSETTOPTR(skin_buffer, child->next);
         }
     }
 }
@@ -433,7 +455,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
     if (line->children_count == 0)
         return false; /* empty line, do nothing */
         
-    struct skin_element *child = line->children[0];
+    struct skin_element *child = get_child(line->children, 0);
     struct conditional *conditional;
     skin_render_func func = skin_render_line;
     int old_refresh_mode = info->refresh_type;
@@ -442,7 +464,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
         switch (child->type)
         {
             case CONDITIONAL:
-                conditional = (struct conditional*)child->data;
+                conditional = SKINOFFSETTOPTR(skin_buffer, child->data);
                 last_value = conditional->last_value;
                 value = evaluate_conditional(info->gwps, info->offset, 
                                              conditional, child->children_count);
@@ -456,20 +478,20 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
                     {
                         /* we are in a false branch of a %?aa<true> conditional */
                         if (last_value == 0)
-                            do_tags_in_hidden_conditional(child->children[0], info);
+                            do_tags_in_hidden_conditional(get_child(child->children, 0), info);
                         break;
                     }
                 }
                 else
                 {
                     if (last_value >= 0 && value != last_value && last_value < child->children_count)
-                        do_tags_in_hidden_conditional(child->children[last_value], info);
+                        do_tags_in_hidden_conditional(get_child(child->children, last_value), info);
                 }
-                if (child->children[value]->type == LINE_ALTERNATOR)
+                if (get_child(child->children, value)->type == LINE_ALTERNATOR)
                 {
                     func = skin_render_alternator;
                 }
-                else if (child->children[value]->type == LINE)
+                else if (get_child(child->children, value)->type == LINE)
                     func = skin_render_line;
                 
                 if (value != last_value)
@@ -478,7 +500,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
                     info->force_redraw = true;
                 }
                     
-                if (func(child->children[value], info))
+                if (func(get_child(child->children, value), info))
                     needs_update = true;
                 else
                     needs_update = needs_update || (last_value != value);
@@ -493,14 +515,14 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
                 
                 fix_line_alignment(info, child);
                 
-                if (!child->data)
+                if (!SKINOFFSETTOPTR(skin_buffer, child->data))
                 {
                     break;
                 }
                 if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp))
                 {
                     static char tempbuf[128];
-                    const char *valuestr = get_token_value(info->gwps, child->data,
+                    const char *valuestr = get_token_value(info->gwps, SKINOFFSETTOPTR(skin_buffer, child->data),
                                                         info->offset, tempbuf,
                                                         sizeof(tempbuf), NULL);
                     if (valuestr)
@@ -517,7 +539,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
                 }
                 break;
             case TEXT:
-                strlcat(info->cur_align_start, child->data, 
+                strlcat(info->cur_align_start, SKINOFFSETTOPTR(skin_buffer, child->data), 
                         info->buf_size - (info->cur_align_start-info->buf));
                 needs_update = needs_update || 
                                 (info->refresh_type&SKIN_REFRESH_STATIC) != 0;
@@ -527,7 +549,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
                 break;
         }
 
-        child = child->next;
+        child = SKINOFFSETTOPTR(skin_buffer, child->next);
     }
     return needs_update;
 }
@@ -541,29 +563,29 @@ static int get_subline_timeout(struct gui_wps *gwps, struct skin_element* line)
     {
         if (element->children_count == 0)
             return retval; /* empty line, so force redraw */
-        element = element->children[0];
+        element = get_child(element->children, 0);
     }
     while (element)
     {
         if (element->type == TAG &&
             element->tag->type == SKIN_TOKEN_SUBLINE_TIMEOUT )
         {
-            token = element->data;
+            token = SKINOFFSETTOPTR(skin_buffer, element->data);
             return token->value.i;
         }
         else if (element->type == CONDITIONAL)
         {
-            struct conditional *conditional = element->data;
+            struct conditional *conditional = SKINOFFSETTOPTR(skin_buffer, element->data);
             int val = evaluate_conditional(gwps, 0, conditional,
                                            element->children_count);
             if (val >= 0)
             {
-                retval = get_subline_timeout(gwps, element->children[val]);
+                retval = get_subline_timeout(gwps, get_child(element->children, val));
                 if (retval >= 0)
                     return retval;
             }
         }
-        element = element->next;
+        element = SKINOFFSETTOPTR(skin_buffer, element->next);
     }
     return retval;
 }
@@ -571,7 +593,7 @@ static int get_subline_timeout(struct gui_wps *gwps, struct skin_element* line)
 bool skin_render_alternator(struct skin_element* element, struct skin_draw_info *info)
 {
     bool changed_lines = false;
-    struct line_alternator *alternator = (struct line_alternator*)element->data;
+    struct line_alternator *alternator = SKINOFFSETTOPTR(skin_buffer, element->data);
     unsigned old_refresh = info->refresh_type;
     if (info->refresh_type == SKIN_REFRESH_ALL)
     {
@@ -597,11 +619,11 @@ bool skin_render_alternator(struct skin_element* element, struct skin_draw_info
             try_line++;
             if (try_line >= element->children_count)
                 try_line = 0;
-            if (element->children[try_line]->children_count != 0)
+            if (get_child(element->children, try_line)->children_count != 0)
             {
-                current_line = element->children[try_line];
+                current_line = get_child(element->children, try_line);
                 rettimeout = get_subline_timeout(info->gwps, 
-                                                 current_line->children[0]);
+                                    get_child(current_line->children, 0));
                 if (rettimeout > 0)
                 {
                     suitable = true;
@@ -619,7 +641,7 @@ bool skin_render_alternator(struct skin_element* element, struct skin_draw_info
         info->refresh_type = SKIN_REFRESH_ALL;
         info->force_redraw = true;
     }
-    bool ret = skin_render_line(element->children[alternator->current_line], info);
+    bool ret = skin_render_line(get_child(element->children, alternator->current_line), info);
     info->refresh_type = old_refresh;
     return changed_lines || ret;
 }
@@ -648,12 +670,13 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
     bool needs_update;
 #ifdef HAVE_LCD_BITMAP
     /* Set images to not to be displayed */
-    struct skin_token_list *imglist = gwps->data->images;
+    struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images);
     while (imglist)
     {
-        struct gui_img *img = (struct gui_img *)imglist->token->value.data;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, imglist->token);
+        struct gui_img *img = (struct gui_img *)SKINOFFSETTOPTR(skin_buffer, token->value.data);
         img->display = -1;
-        imglist = imglist->next;
+        imglist = SKINOFFSETTOPTR(skin_buffer, imglist->next);
     }
 
     /* fix font ID's */
@@ -716,7 +739,7 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
         }
         if (!info.no_line_break)
             info.line_number++;
-        line = line->next;
+        line = SKINOFFSETTOPTR(skin_buffer, line->next);
     }
 #ifdef HAVE_LCD_BITMAP
     wps_display_images(gwps, &skin_viewport->vp);
@@ -730,6 +753,7 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
     
     struct skin_element* viewport;
     struct skin_viewport* skin_viewport;
+    char *label;
     
     int old_refresh_mode = refresh_mode;
     
@@ -741,18 +765,21 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
             data->wps_progress_pat[i] = display->get_locked_pattern();
     }
 #endif
-    viewport = data->tree;
-    skin_viewport = (struct skin_viewport *)viewport->data;
-    if (skin_viewport->label && viewport->next &&
-        !strcmp(skin_viewport->label,VP_DEFAULT_LABEL))
+    viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
+    skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
+    label = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label);
+    if (skin_viewport->label == VP_DEFAULT_LABEL)
+        label = VP_DEFAULT_LABEL_STRING;
+    if (label && SKINOFFSETTOPTR(skin_buffer, viewport->next) &&
+        !strcmp(label,VP_DEFAULT_LABEL_STRING))
         refresh_mode = 0;
     
-    for (viewport = data->tree;
+    for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
          viewport;
-         viewport = viewport->next)
+         viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next))
     {
         /* SETUP */
-        skin_viewport = (struct skin_viewport*)viewport->data;
+        skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
         unsigned vp_refresh_mode = refresh_mode;
 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
         skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour;
@@ -789,7 +816,7 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
         }
         /* render */
         if (viewport->children_count)
-            skin_render_viewport(viewport->children[0], gwps,
+            skin_render_viewport(get_child(viewport->children, 0), gwps,
                                  skin_viewport, vp_refresh_mode);
         refresh_mode = old_refresh_mode;
     }
@@ -826,7 +853,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer,
     struct align_pos * align = &info.align;
     bool needs_update;
     int cur_pos, start_item, max;
-    int nb_lines = viewport_get_nb_lines(viewer->vp);
+    int nb_lines = viewport_get_nb_lines(SKINOFFSETTOPTR(skin_buffer, viewer->vp));
 #if CONFIG_TUNER
     if (get_current_activity() == ACTIVITY_FM)
     {
@@ -848,7 +875,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer,
     if (max-start_item > nb_lines)
         max = start_item + nb_lines;
     
-    line = viewer->line;
+    line = SKINOFFSETTOPTR(skin_buffer, viewer->line);
     while (start_item < max)
     {
         linebuf[0] = '\0';
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c
index 7c43045..853dab4 100644
--- a/apps/gui/skin_engine/skin_tokens.c
+++ b/apps/gui/skin_engine/skin_tokens.c
@@ -732,18 +732,21 @@ static const char* NOINLINE get_lif_token_value(struct gui_wps *gwps,
 {
     int a = lif->num_options;
     int b;
-    const char* out_text = get_token_value(gwps, lif->token, offset,
-                                           buf, buf_size, &a);            
-    if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
+    struct wps_token *liftoken = SKINOFFSETTOPTR(skin_buffer, lif->token);
+    const char* out_text = get_token_value(gwps, liftoken, offset, buf, buf_size, &a);            
+    if (a == -1 && liftoken->type != SKIN_TOKEN_VOLUME)
         a = (out_text && *out_text) ? 1 : 0;
     switch (lif->operand.type)
     {
         case STRING:
+        {
+            char *cmp = SKINOFFSETTOPTR(skin_buffer, lif->operand.data.text);
             if (out_text == NULL)
                 return NULL;
-            a = strcmp(out_text, lif->operand.data.text);
+            a = strcmp(out_text, cmp);
             b = 0;
             break;
+        }
         case INTEGER:
         case DECIMAL:
             b = lif->operand.data.number;
@@ -752,11 +755,12 @@ static const char* NOINLINE get_lif_token_value(struct gui_wps *gwps,
         {
             char temp_buf[MAX_PATH];
             const char *outb;
-            struct wps_token *token = lif->operand.data.code->data;
+            struct skin_element *element = SKINOFFSETTOPTR(skin_buffer, lif->operand.data.code);
+            struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, element->data);
             b = lif->num_options;
             outb = get_token_value(gwps, token, offset, temp_buf,
                                    sizeof(temp_buf), &b);            
-            if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
+            if (b == -1 && liftoken->type != SKIN_TOKEN_VOLUME)
             {
                 if (!out_text || !outb)
                     return (lif->op == IF_EQUALS) ? NULL : "neq";
@@ -865,14 +869,15 @@ const char *get_token_value(struct gui_wps *gwps,
     {
         case SKIN_TOKEN_LOGICAL_IF:
         {
-            struct logical_if *lif = token->value.data;
+            struct logical_if *lif = SKINOFFSETTOPTR(skin_buffer, token->value.data);
             return get_lif_token_value(gwps, lif, offset, buf, buf_size);
         }
         break;
         case SKIN_TOKEN_SUBSTRING:
         {
-            struct substring *ss = token->value.data;
-            const char *token_val = get_token_value(gwps, ss->token, offset,
+            struct substring *ss = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            const char *token_val = get_token_value(gwps, 
+                            SKINOFFSETTOPTR(skin_buffer, ss->token), offset,
                                                     buf, buf_size, intval);
             if (token_val)
             {
@@ -909,7 +914,7 @@ const char *get_token_value(struct gui_wps *gwps,
             return &(token->value.c);
 
         case SKIN_TOKEN_STRING:
-            return (char*)token->value.data;
+            return (char*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
             
         case SKIN_TOKEN_TRANSLATEDSTRING:
             return (char*)P2STR(ID2P(token->value.i));
@@ -929,7 +934,7 @@ const char *get_token_value(struct gui_wps *gwps,
             return buf;
         case SKIN_TOKEN_LIST_ITEM_TEXT:
         {
-            struct listitem *li = (struct listitem *)token->value.data;
+            struct listitem *li = (struct listitem *)SKINOFFSETTOPTR(skin_buffer, token->value.data);
             return skinlist_get_item_text(li->offset, li->wrap, buf, buf_size);
         }
         case SKIN_TOKEN_LIST_ITEM_NUMBER:
@@ -941,7 +946,7 @@ const char *get_token_value(struct gui_wps *gwps,
             return skinlist_is_selected_item()?"s":"";
         case SKIN_TOKEN_LIST_ITEM_ICON:
         {
-            struct listitem *li = (struct listitem *)token->value.data;
+            struct listitem *li = (struct listitem *)SKINOFFSETTOPTR(skin_buffer, token->value.data);
             int icon = skinlist_get_item_icon(li->offset, li->wrap);
             if (intval)
                 *intval = icon;
@@ -997,14 +1002,15 @@ const char *get_token_value(struct gui_wps *gwps,
             return buf;
 #ifdef HAVE_ALBUMART
         case SKIN_TOKEN_ALBUMART_FOUND:
-            if (data->albumart)
+            if (SKINOFFSETTOPTR(skin_buffer, data->albumart))
             {
                 int handle = -1;
                 handle = playback_current_aa_hid(data->playback_aa_slot);
 #if CONFIG_TUNER
                 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
                 {
-                    struct dim dim = {data->albumart->width, data->albumart->height};
+                    struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart);
+                    struct dim dim = {aa->width, aa->height};
                     handle = radio_get_art_hid(&dim);
                 }
 #endif
@@ -1473,9 +1479,10 @@ const char *get_token_value(struct gui_wps *gwps,
             {
 #ifdef HAVE_TOUCHSCREEN
             unsigned int last_touch = touchscreen_last_touch();
-            struct touchregion_lastpress *data = token->value.data;
-            if (data->region)
-                last_touch = data->region->last_press;
+            struct touchregion_lastpress *data = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            struct touchregion *region = SKINOFFSETTOPTR(skin_buffer, data->region);
+            if (region)
+                last_touch = region->last_press;
 
             if (last_touch != 0xffff &&
                 TIME_BEFORE(current_tick, data->timeout + last_touch))
@@ -1805,7 +1812,7 @@ const char *get_token_value(struct gui_wps *gwps,
 #ifdef HAVE_SKIN_VARIABLES
         case SKIN_TOKEN_VAR_GETVAL:
         {
-            struct skin_var* var = token->value.data;
+            struct skin_var* var = SKINOFFSETTOPTR(skin_buffer, token->value.data);
             if (intval)
                 *intval = var->value;
             snprintf(buf, buf_size, "%d", var->value);
@@ -1814,8 +1821,9 @@ const char *get_token_value(struct gui_wps *gwps,
         break;
         case SKIN_TOKEN_VAR_TIMEOUT:
             {
-            struct skin_var_lastchange *data = token->value.data;
-            unsigned int last_change = data->var->last_changed;
+            struct skin_var_lastchange *data = SKINOFFSETTOPTR(skin_buffer, token->value.data);
+            struct skin_var* var = SKINOFFSETTOPTR(skin_buffer, data->var);
+            unsigned int last_change = var->last_changed;
 
             if (last_change != 0xffff &&
                 TIME_BEFORE(current_tick, data->timeout + last_change))
diff --git a/apps/gui/skin_engine/skin_tokens.h b/apps/gui/skin_engine/skin_tokens.h
deleted file mode 100644
index bfca7b7..0000000
--- a/apps/gui/skin_engine/skin_tokens.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- *             __________               __   ___.
- *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
- *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
- *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
- *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
- *                     \/            \/     \/    \/            \/
- * $Id$
- *
- * Copyright (C) 2007 Nicolas Pennequin
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
- 
-#ifndef _SKIN_TOKENS_H_
-#define _SKIN_TOKENS_H_
-
-#include <stdbool.h>
-#include "tag_table.h"
-
-struct wps_token {
-    union {
-        char c;
-        unsigned short i;
-        long l;
-        void* data;
-    } value;
-
-    enum skin_token_type type; /* enough to store the token type */
-    /* Whether the tag (e.g. track name or the album) refers the
-       current or the next song (false=current, true=next) */
-    bool next;
-};
-
-struct skin_token_list {
-    struct wps_token *token;
-    struct skin_token_list *next;
-};
-
-char* get_dir(char* buf, int buf_size, const char* path, int level);
-
-#endif
diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c
index 64c7979..3714f8c 100644
--- a/apps/gui/skin_engine/skin_touchsupport.c
+++ b/apps/gui/skin_engine/skin_touchsupport.c
@@ -37,11 +37,12 @@
 /** Disarms all touchregions. */
 void skin_disarm_touchregions(struct wps_data *data)
 {
-    struct skin_token_list *regions = data->touchregions;
+    struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions);
     while (regions)
     {
-        ((struct touchregion *)regions->token->value.data)->armed = false;
-        regions = regions->next;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token);
+        ((struct touchregion *)token->value.data)->armed = false;
+        regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
     }
 }
 
@@ -56,35 +57,38 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
     short x,y;
     short vx, vy;
     int type = action_get_touchscreen_press(&x, &y);
+    struct skin_viewport *wvp;
     struct touchregion *r, *temp = NULL;
     bool repeated = (type == BUTTON_REPEAT);
     bool released = (type == BUTTON_REL);
     bool pressed = (type == BUTTON_TOUCHSCREEN);
-    struct skin_token_list *regions = data->touchregions;
+    struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions);
     bool needs_repeat;
 
     while (regions)
     {
-        r = (struct touchregion *)regions->token->value.data;
+        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token);
+        r = (struct touchregion *)token->value.data;
+        wvp = SKINOFFSETTOPTR(skin_buffer, r->wvp);
         /* make sure this region's viewport is visible */
-        if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
+        if (wvp->hidden_flags&VP_DRAW_HIDDEN)
         {
-            regions = regions->next;
+            regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
             continue;
         }
         if (data->touchscreen_locked && 
             (r->action != ACTION_TOUCH_SOFTLOCK && !r->allow_while_locked))
         {
-            regions = regions->next;
+            regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
             continue;
         }
         needs_repeat = r->press_length != PRESS;
         /* check if it's inside this viewport */
-        if (viewport_point_within_vp(&(r->wvp->vp), x, y))
+        if (viewport_point_within_vp(&(wvp->vp), x, y))
         {   /* reposition the touch inside the viewport since touchregions
              * are relative to a preceding viewport */
-            vx = x - r->wvp->vp.x;
-            vy = y - r->wvp->vp.y;
+            vx = x - wvp->vp.x;
+            vy = y - wvp->vp.y;
             /* now see if the point is inside this region */
             if (vx >= r->x && vx < r->x+r->width &&
                 vy >= r->y && vy < r->y+r->height)
@@ -127,7 +131,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
                 }
             }
         }
-        regions = regions->next;
+        regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
     }
 
     /* On release, all regions are disarmed. */
@@ -214,7 +218,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
                 {
                     case F_T_CUSTOM:
                         s->custom_setting
-                            ->load_from_cfg(s->setting, data->value.text);
+                            ->load_from_cfg(s->setting, SKINOFFSETTOPTR(skin_buffer, data->value.text));
                         break;                          
                     case F_T_INT:
                     case F_T_UINT:
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index ed09ad0..5c9474a 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -25,6 +25,10 @@
 #ifndef _WPS_ENGINE_INTERNALS_
 #define _WPS_ENGINE_INTERNALS_
 
+#include "tag_table.h"
+#include "skin_parser.h"
+
+extern char skin_buffer[];
 
 /* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds
    (possibly with a decimal fraction) but stored as integer values.
@@ -33,9 +37,6 @@
 #define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */
 #define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */
 
-#include "skin_tokens.h"
-#include "tag_table.h"
-#include "skin_parser.h"
 
 
 /* TODO: sort this mess out */
@@ -44,41 +45,43 @@
 #include "statusbar.h"
 #include "metadata.h"
 
-/* alignments */
-#define WPS_ALIGN_RIGHT 32
-#define WPS_ALIGN_CENTER 64
-#define WPS_ALIGN_LEFT 128
-
 
 #define TOKEN_VALUE_ONLY 0x0DEADC0D
 
-#ifdef HAVE_ALBUMART
 
-/* albumart definitions */
-#define WPS_ALBUMART_NONE           0      /* WPS does not contain AA tag */
-#define WPS_ALBUMART_CHECK          1      /* WPS contains AA conditional tag */
-#define WPS_ALBUMART_LOAD           2      /* WPS contains AA tag */
+/* wps_data*/
+struct wps_token {
+    union {
+        char c;
+        unsigned short i;
+        long l;
+        OFFSETTYPE(void*) data;
+    } value;
+
+    enum skin_token_type type; /* enough to store the token type */
+    /* Whether the tag (e.g. track name or the album) refers the
+       current or the next song (false=current, true=next) */
+    bool next;
+};
 
-#define WPS_ALBUMART_ALIGN_RIGHT    1    /* x align:   right */
-#define WPS_ALBUMART_ALIGN_CENTER   2    /* x/y align: center */
-#define WPS_ALBUMART_ALIGN_LEFT     4    /* x align:   left */
-#define WPS_ALBUMART_ALIGN_TOP      1    /* y align:   top */
-#define WPS_ALBUMART_ALIGN_BOTTOM   4    /* y align:   bottom */
+char* get_dir(char* buf, int buf_size, const char* path, int level);
 
-#endif /* HAVE_ALBUMART */
 
-/* wps_data*/
+struct skin_token_list {
+    OFFSETTYPE(struct wps_token *) token;
+    OFFSETTYPE(struct skin_token_list *) next;
+};
 
 #ifdef HAVE_LCD_BITMAP
 struct gui_img {
-    struct viewport* vp;    /* The viewport to display this image in */
+    OFFSETTYPE(struct viewport*) vp;    /* The viewport to display this image in */
     short int x;                  /* x-pos */
     short int y;                  /* y-pos */
     short int num_subimages;      /* number of sub-images */
     short int subimage_height;    /* height of each sub-image */
     struct bitmap bm;
     int buflib_handle;
-    const char *label;
+    OFFSETTYPE(char*) label;
     bool loaded;            /* load state */
     bool always_display;    /* not using the preload/display mechanism */
     int display;
@@ -86,15 +89,15 @@ struct gui_img {
 };
 
 struct image_display {
-    const char *label;
+    OFFSETTYPE(char*) label;
     int subimage;
-    struct wps_token *token; /* the token to get the subimage number from */
+    OFFSETTYPE(struct wps_token*) token; /* the token to get the subimage number from */
     int offset; /* offset into the bitmap strip to start */
 };
 
 struct progressbar {
     enum skin_token_type type;
-    struct viewport *vp;
+    OFFSETTYPE(struct viewport *) vp;
     /* regular pb */
     short x;
     /* >=0: explicitly set in the tag -> y-coord within the viewport
@@ -105,14 +108,14 @@ struct progressbar {
     short height;
     bool  follow_lang_direction;
     
-    struct gui_img *image;
+    OFFSETTYPE(struct gui_img *) image;
     
     bool invert_fill_direction;
     bool nofill;
     bool nobar;
-    struct gui_img *slider;
+    OFFSETTYPE(struct gui_img *) slider;
     bool horizontal;
-    struct gui_img *backdrop;
+    OFFSETTYPE(struct gui_img *) backdrop;
 };
 #endif
 
@@ -125,35 +128,11 @@ struct align_pos {
 };
 
 #ifdef HAVE_LCD_BITMAP
-
-#define MAX_IMAGES (26*2) /* a-z and A-Z */
-#define MAX_PROGRESSBARS 3
-
-/* The image buffer is big enough to store one full-screen native bitmap,
-   plus two full-screen mono bitmaps. */
-
-#define WPS_MAX_VIEWPORTS   24
-#define WPS_MAX_LINES       ((LCD_HEIGHT/5+1) * 2)
-#define WPS_MAX_SUBLINES    (WPS_MAX_LINES*3)
 #define WPS_MAX_TOKENS      1150
-#define WPS_MAX_STRINGS     128
-#define STRING_BUFFER_SIZE  1024
-#define WPS_MAX_COND_LEVEL  10
-
 #else
-
-#define WPS_MAX_VIEWPORTS   2
-#define WPS_MAX_LINES       2
-#define WPS_MAX_SUBLINES    12
 #define WPS_MAX_TOKENS      64
-#define WPS_MAX_STRINGS     32
-#define STRING_BUFFER_SIZE  64
-#define WPS_MAX_COND_LEVEL  5
-
 #endif
 
-#define SUBLINE_RESET -1
-
 enum wps_parse_error {
     PARSE_OK,
     PARSE_FAIL_UNCLOSED_COND,
@@ -176,12 +155,13 @@ struct gradient_config {
 #define VP_DRAW_WASHIDDEN   0x4
 /* these are never drawn, nor cleared, i.e. just ignored */
 #define VP_NEVER_VISIBLE    0x8
-#define VP_DEFAULT_LABEL    "|"
+#define VP_DEFAULT_LABEL    -200
+#define VP_DEFAULT_LABEL_STRING "|"
 struct skin_viewport {
     struct viewport vp;   /* The LCD viewport struct */
     char hidden_flags;
     bool is_infovp;
-    char* label;
+    OFFSETTYPE(char*) label;
     int   parsed_fontid;
 #if LCD_DEPTH > 1
     unsigned start_fgcolour;
@@ -192,14 +172,14 @@ struct skin_viewport {
 #endif
 };
 struct viewport_colour {
-    struct viewport *vp;
+    OFFSETTYPE(struct viewport *) vp;
     unsigned colour;
 };
 
 #ifdef HAVE_TOUCHSCREEN
 struct touchregion {
-    char* label;            /* label to identify this region */
-    struct skin_viewport* wvp;/* The viewport this region is in */
+    OFFSETTYPE(char*) label;            /* label to identify this region */
+    OFFSETTYPE(struct skin_viewport*) wvp;/* The viewport this region is in */
     short int x;             /* x-pos */
     short int y;             /* y-pos */
     short int width;         /* width */
@@ -219,7 +199,7 @@ struct touchregion {
             const struct settings_list *setting; /* setting being controlled */
             union {         /* Value to set the setting to for ACTION_SETTING_SET */
                 int number;
-                char* text;
+                OFFSETTYPE(char*) text;
             } value;
         } setting_data;
         int   value;
@@ -230,20 +210,32 @@ struct touchregion {
 
 
 struct touchregion_lastpress {
-    struct touchregion *region;
+    OFFSETTYPE(struct touchregion *) region;
     long timeout;
 };
 #endif
 
 struct playlistviewer {
-    struct viewport *vp;
+    OFFSETTYPE(struct viewport *) vp;
     bool show_icons;
     int start_offset;
-    struct skin_element *line;
+    OFFSETTYPE(struct skin_element *) line;
 };
 
 
 #ifdef HAVE_ALBUMART
+
+/* albumart definitions */
+#define WPS_ALBUMART_NONE           0      /* WPS does not contain AA tag */
+#define WPS_ALBUMART_CHECK          1      /* WPS contains AA conditional tag */
+#define WPS_ALBUMART_LOAD           2      /* WPS contains AA tag */
+
+#define WPS_ALBUMART_ALIGN_RIGHT    1    /* x align:   right */
+#define WPS_ALBUMART_ALIGN_CENTER   2    /* x/y align: center */
+#define WPS_ALBUMART_ALIGN_LEFT     4    /* x align:   left */
+#define WPS_ALBUMART_ALIGN_TOP      1    /* y align:   top */
+#define WPS_ALBUMART_ALIGN_BOTTOM   4    /* y align:   bottom */
+
 struct skin_albumart {
     /* Album art support */
     int x;
@@ -255,7 +247,7 @@ struct skin_albumart {
     unsigned char yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */
     unsigned char state; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */
     
-    struct viewport *vp;
+    OFFSETTYPE(struct viewport *) vp;
     int draw_handle;
 };
 #endif
@@ -272,11 +264,11 @@ struct line_alternator {
 
 struct conditional {
     int last_value;
-    struct wps_token *token;
+    OFFSETTYPE(struct wps_token *) token;
 };
 
 struct logical_if {
-    struct wps_token *token;
+    OFFSETTYPE(struct wps_token *) token;
     enum {
         IF_EQUALS, /* == */
         IF_NOTEQUALS, /* != */
@@ -292,7 +284,7 @@ struct logical_if {
 struct substring {
     int start;
     int length;
-    struct wps_token *token;
+    OFFSETTYPE(struct wps_token *) token;
 };
 
 struct listitem {
@@ -302,16 +294,16 @@ struct listitem {
 
 #ifdef HAVE_SKIN_VARIABLES
 struct skin_var {
-    const char *label;
+    OFFSETTYPE(const char *) label;
     int value;
     long last_changed;
 };
 struct skin_var_lastchange {
-    struct skin_var *var;
+    OFFSETTYPE(struct skin_var *) var;
     long timeout;
 };
 struct skin_var_changer {
-    struct skin_var *var;
+    OFFSETTYPE(struct skin_var *) var;
     int newval;
     bool direct; /* true to make val=newval, false for val += newval */
     int max;
@@ -323,30 +315,27 @@ struct skin_var_changer {
    viewable content of a wps */
 struct wps_data
 {
-    struct skin_element *tree;
+    OFFSETTYPE(struct skin_element *) tree;
 #ifdef HAVE_LCD_BITMAP
-    struct skin_token_list *images;
-    int *font_ids;
+    OFFSETTYPE(struct skin_token_list *) images;
+    OFFSETTYPE(int *) font_ids;
     int font_count;
 #endif
 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
-    struct {
-        char *backdrop;
-        int backdrop_id;
-    };
+    int backdrop_id;
 #endif
 
 #ifdef HAVE_TOUCHSCREEN
-    struct skin_token_list *touchregions;
+    OFFSETTYPE(struct skin_token_list *) touchregions;
     bool touchscreen_locked;
 #endif
 #ifdef HAVE_ALBUMART
-    struct skin_albumart *albumart;
+    OFFSETTYPE(struct skin_albumart *) albumart;
     int    playback_aa_slot;
 #endif
 
 #ifdef HAVE_SKIN_VARIABLES
-    struct skin_token_list *skinvars;
+    OFFSETTYPE(struct skin_token_list *) skinvars;
 #endif
 
 #ifdef HAVE_LCD_BITMAP
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index f79672c..bec2484 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -87,8 +87,9 @@ int sb_postproccess(enum screen_type screen, struct wps_data *data)
         /* hide the sb's default viewport because it has nasty effect with stuff
         * not part of the statusbar,
         * hence .sbs's without any other vps are unsupported*/
-        struct skin_viewport *vp = skin_find_item(VP_DEFAULT_LABEL, SKIN_FIND_VP, data);
-        struct skin_element *next_vp = data->tree->next;
+        struct skin_viewport *vp = skin_find_item(VP_DEFAULT_LABEL_STRING, SKIN_FIND_VP, data);
+        struct skin_element *tree = SKINOFFSETTOPTR(skin_buffer, data->tree);
+        struct skin_element *next_vp = SKINOFFSETTOPTR(skin_buffer, tree->next);
         
         if (vp)
         {
@@ -99,7 +100,7 @@ int sb_postproccess(enum screen_type screen, struct wps_data *data)
             /* hide this viewport, forever */
             vp->hidden_flags = VP_NEVER_VISIBLE;
         }
-        sb_set_info_vp(screen, VP_DEFAULT_LABEL);
+        sb_set_info_vp(screen, VP_DEFAULT_LABEL_STRING);
     }
     viewportmanager_theme_undo(screen, false);
     return 1;
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 6486e42..97c945d 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -667,7 +667,7 @@ static void gwps_enter_wps(void)
 #if LCD_DEPTH > 1
         if (display->depth > 1)
         {
-            struct skin_viewport *svp = skin_find_item(VP_DEFAULT_LABEL, 
+            struct skin_viewport *svp = skin_find_item(VP_DEFAULT_LABEL_STRING, 
                                                        SKIN_FIND_VP, gwps->data);
             if (svp)
             {
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c
index 43f18cd..af1aac9 100644
--- a/apps/recorder/albumart.c
+++ b/apps/recorder/albumart.c
@@ -305,7 +305,7 @@ void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear)
         return;
 
     struct wps_data *data = gwps->data;
-    struct skin_albumart *aa = data->albumart;
+    struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart);
 
     if (!aa)
         return;
diff --git a/lib/skin_parser/skin_buffer.c b/lib/skin_parser/skin_buffer.c
index 5a9d446..b3c4e0f 100644
--- a/lib/skin_parser/skin_buffer.c
+++ b/lib/skin_parser/skin_buffer.c
@@ -60,6 +60,16 @@
 static size_t buf_size;
 static unsigned char *buffer_start = NULL;
 static unsigned char *buffer_front = NULL;
+
+long skin_buffer_to_offset(void *pointer)
+{
+    return pointer == NULL ? -1 : (void*)pointer - (void*)buffer_start;
+}
+
+void* skin_buffer_from_offset(long offset)
+{
+    return offset < 0 ? NULL : buffer_start + offset;
+}
 #endif
 
 #ifdef USE_HOST_MALLOC
diff --git a/lib/skin_parser/skin_buffer.h b/lib/skin_parser/skin_buffer.h
index b2ed34e..e42516e 100644
--- a/lib/skin_parser/skin_buffer.h
+++ b/lib/skin_parser/skin_buffer.h
@@ -28,6 +28,9 @@
 void skin_buffer_init(char* buffer, size_t size);
 /* Allocate size bytes from the buffer */
 
+long skin_buffer_to_offset(void *pointer);
+void* skin_buffer_from_offset(long offset);
+
 /* #define DEBUG_SKIN_ALLOCATIONS */
 
 #ifdef DEBUG_SKIN_ALLOCATIONS 
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c
index 2612cc8..b17f634 100644
--- a/lib/skin_parser/skin_parser.c
+++ b/lib/skin_parser/skin_parser.c
@@ -37,8 +37,6 @@ int skin_line = 0;
 char* skin_start = 0;
 int viewport_line = 0;
 
-static int tag_recursion_level = 0;
-
 #ifdef ROCKBOX
 static skin_callback callback = NULL;
 static void* callback_data;
@@ -81,8 +79,6 @@ struct skin_element* skin_parse(const char* document)
     struct skin_element* root = NULL;
     struct skin_element* last = NULL;
 
-    struct skin_element** to_write = 0;
-
     const char* cursor = document; /*Keeps track of location in the document*/
     
     skin_line = 1;
@@ -93,14 +89,18 @@ struct skin_element* skin_parse(const char* document)
 
     while(*cursor != '\0')
     {
+        struct skin_element* tree = skin_parse_viewport(&cursor);
         if(!root)
-            to_write = &root;
+        {
+            root = tree;
+            last = root;
+        }
         else
-            to_write = &(last->next);
-
+        {
+            last->next = skin_buffer_to_offset(tree);
+            last = tree;
+        }
 
-        *to_write = skin_parse_viewport(&cursor);
-        last = *to_write;
         if(!last)
         {
             skin_free_tree(root); /* Clearing any memory already used */
@@ -108,8 +108,8 @@ struct skin_element* skin_parse(const char* document)
         }
 
         /* Making sure last is at the end */
-        while(last->next)
-            last = last->next;
+        while(last->next >= 0)
+            last = skin_buffer_from_offset(last->next);
 
     }
     return root;
@@ -121,8 +121,6 @@ static struct skin_element* skin_parse_viewport(const char** document)
     struct skin_element* root = NULL;
     struct skin_element* last = NULL;
     struct skin_element* retval = NULL;
-    
-    tag_recursion_level = 0;
 
     retval = skin_alloc_element();
     if (!retval)
@@ -132,7 +130,7 @@ static struct skin_element* skin_parse_viewport(const char** document)
     retval->line = skin_line;
     viewport_line = skin_line;
 
-    struct skin_element** to_write = 0;
+    struct skin_element** children;
 
     const char* cursor = *document; /* Keeps track of location in the document */
     const char* bookmark; /* Used when we need to look ahead */
@@ -165,8 +163,8 @@ static struct skin_element* skin_parse_viewport(const char** document)
         return retval;
     }
     retval->children_count = 1;
-    retval->children = skin_alloc_children(1);
-    if (!retval->children)
+    children = skin_alloc_children(1);
+    if (!children)
         return NULL;
     do
     {
@@ -212,15 +210,19 @@ static struct skin_element* skin_parse_viewport(const char** document)
         }
         cursor = bookmark;
 
-        if(!root)
-            to_write = &root;
-        else
-            to_write = &(last->next);
-
         if(sublines)
         {
-            *to_write = skin_parse_sublines(&cursor);
-            last = *to_write;
+            struct skin_element* out = skin_parse_sublines(&cursor);
+            if (!root)
+            {
+                root = out;
+                last = root;
+            }
+            else
+            {
+                last->next = skin_buffer_to_offset(out);
+                last = out;
+            }
             if(!last)
                 return NULL;
         }
@@ -237,15 +239,25 @@ static struct skin_element* skin_parse_viewport(const char** document)
             if (check_viewport(cursor))
                 break;
 #endif
-            *to_write = skin_parse_line(&cursor);
-            last = *to_write;
+
+            struct skin_element* out = skin_parse_line(&cursor);
+            if (!root)
+            {
+                root = out;
+                last = root;
+            }
+            else
+            {
+                last->next = skin_buffer_to_offset(out);
+                last = out;
+            }
             if(!last)
                 return NULL;
 
         }
         /* Making sure last is at the end */
-        while(last->next)
-            last = last->next;
+        while(last->next >= 0)
+            last = skin_buffer_from_offset(last->next);
 
         if(*cursor == '\n')
         {
@@ -269,7 +281,8 @@ static struct skin_element* skin_parse_viewport(const char** document)
 
     *document = cursor;
 
-    retval->children[0] = root;
+    children[0] = root;
+    retval->children = skin_buffer_to_offset(children);
     return retval;
 }
 
@@ -293,6 +306,7 @@ static struct skin_element* skin_parse_line_optional(const char** document,
     struct skin_element* root = NULL;
     struct skin_element* current = NULL;
     struct skin_element* retval = NULL;
+    struct skin_element** children = NULL;
 
     /* A wrapper for the line */
     retval = skin_alloc_element();
@@ -315,8 +329,8 @@ static struct skin_element* skin_parse_line_optional(const char** document,
 
     if(retval->children_count > 0)
     {
-        retval->children = skin_alloc_children(1);
-        if (!retval->children)
+        children = skin_alloc_children(1);
+        if (!children)
             return NULL;
     }
 
@@ -344,10 +358,11 @@ static struct skin_element* skin_parse_line_optional(const char** document,
         /* Allocating memory if necessary */
         if(root)
         {
-            current->next = skin_alloc_element();
-            if (!current->next)
+            struct skin_element *next = skin_alloc_element();
+            if (!next)
                 return NULL;
-            current = current->next;
+            current->next = skin_buffer_to_offset(next);
+            current = next;
         }
         else
         {
@@ -384,7 +399,10 @@ static struct skin_element* skin_parse_line_optional(const char** document,
     *document = cursor;
     
     if(root)
-        retval->children[0] = root;
+    {
+        children[0] = root;
+        retval->children = skin_buffer_to_offset(children);
+    }
     return retval;
 }
 
@@ -397,6 +415,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
                                                   int conditional)
 {
     struct skin_element* retval;
+    struct skin_element** children;
     const char* cursor = *document;
     int sublines = 1;
     int i;
@@ -405,7 +424,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
     if (!retval)
         return NULL;
     retval->type = LINE_ALTERNATOR;
-    retval->next = NULL;
+    retval->next = skin_buffer_to_offset(NULL);
     retval->line = skin_line;
 
     /* First we count the sublines */
@@ -449,14 +468,14 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
 
     /* ...and then we parse them */
     retval->children_count = sublines;
-    retval->children = skin_alloc_children(sublines);
-    if (!retval->children)
+    children = skin_alloc_children(sublines);
+    if (!children)
         return NULL;
 
     cursor = *document;
     for(i = 0; i < sublines; i++)
     {
-        retval->children[i] = skin_parse_line_optional(&cursor, conditional);
+        children[i] = skin_parse_line_optional(&cursor, conditional);
         skip_whitespace(&cursor);
 
         if(*cursor != MULTILINESYM && i != sublines - 1)
@@ -478,6 +497,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
     }
 #endif
     *document = cursor;
+    retval->children = skin_buffer_to_offset(children);
 
     return retval;
 }
@@ -490,13 +510,13 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
     char tag_name[3];
     char* tag_args;
     const struct tag_info *tag;
+    struct skin_tag_parameter* params = NULL;
 
     int num_args = 1;
     int i;
     int star = 0; /* Flag for the all-or-none option */
 
     int optional = 0;
-    tag_recursion_level++;
 
     /* Checking the tag name */
     tag_name[0] = cursor[0];
@@ -597,8 +617,8 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
 
     cursor = bookmark; /* Restoring the cursor */
     element->params_count = num_args;
-    element->params = skin_alloc_params(num_args, tag_recursion_level<=1);
-    if (!element->params)
+    params = skin_alloc_params(num_args);
+    if (!params)
         return 0;
 
     /* Now we have to actually parse each argument */
@@ -686,14 +706,14 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
         else
             type_code = *tag_args;
         /* Storing the type code */
-        element->params[i].type_code = type_code;
+        params[i].type_code = type_code;
 
         /* Checking a nullable argument for null. */
         if(*cursor == DEFAULTSYM && !isdigit(cursor[1]))
         {
             if(islower(type_code))
             {
-                element->params[i].type = DEFAULT;
+                params[i].type = DEFAULT;
                 cursor++;
             }
             else
@@ -711,8 +731,8 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
                 return 0;
             }
 
-            element->params[i].type = INTEGER;
-            element->params[i].data.number = scan_int(&cursor);
+            params[i].type = INTEGER;
+            params[i].data.number = scan_int(&cursor);
         }
         else if(tolower(type_code) == 'd')
         {
@@ -738,23 +758,23 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
             }
             if (have_tenth == false)
                 val *= 10;
-            element->params[i].type = DECIMAL;
-            element->params[i].data.number = val;
+            params[i].type = DECIMAL;
+            params[i].data.number = val;
         }
         else if(tolower(type_code) == 'n' ||
                 tolower(type_code) == 's' || tolower(type_code) == 'f')
         {
             /* Scanning a string argument */
-            element->params[i].type = STRING;
-            element->params[i].data.text = scan_string(&cursor);
+            params[i].type = STRING;
+            params[i].data.text = skin_buffer_to_offset(scan_string(&cursor));
 
         }
         else if(tolower(type_code) == 'c')
         {
             /* Recursively parsing a code argument */
-            element->params[i].type = CODE;
-            element->params[i].data.code = skin_parse_code_as_arg(&cursor);
-            if(!element->params[i].data.code)
+            params[i].type = CODE;
+            params[i].data.code = skin_buffer_to_offset(skin_parse_code_as_arg(&cursor));
+            if(params[i].data.code < 0)
                 return 0;
         }
         else if (tolower(type_code) == 't')
@@ -763,9 +783,9 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
             child->type = TAG;
             if (!skin_parse_tag(child, &cursor))
                 return 0;
-            child->next = NULL;
-            element->params[i].type = CODE;
-            element->params[i].data.code = child;
+            child->next = skin_buffer_to_offset(NULL);
+            params[i].type = CODE;
+            params[i].data.code = skin_buffer_to_offset(child);
         }
             
 
@@ -796,6 +816,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
             tag_args++;
         }
     }
+    element->params = skin_buffer_to_offset(params);
 
     /* Checking for a premature end */
     if(*tag_args != '\0' && !optional)
@@ -811,7 +832,6 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
     }
 #endif
     *document = cursor;
-    tag_recursion_level--;
 
     return 1;
 }
@@ -855,9 +875,10 @@ static int skin_parse_text(struct skin_element* element, const char** document,
     /* Copying the text into the element struct */
     element->type = TEXT;
     element->line = skin_line;
-    element->next = NULL;
-    element->data = text = skin_alloc_string(length);
-    if (!element->data)
+    element->next = skin_buffer_to_offset(NULL);
+    text = skin_alloc_string(length);
+    element->data = skin_buffer_to_offset(text);
+    if (element->data < 0)
         return 0;
     
     for(dest = 0; dest < length; dest++)
@@ -896,6 +917,7 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
     const char *false_branch = NULL;
     const char *conditional_end = NULL;
 #endif
+    struct skin_element **children_array = NULL;
 
     /* Some conditional tags allow for target feature checking,
      * so to handle that call the callback as usual with type == TAG
@@ -994,23 +1016,23 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
     {
         const char* emptyline= "";
         children = 1;
-        element->children = skin_alloc_children(children);
-        if (!element->children)
+        children_array = skin_alloc_children(children);
+        if (!children_array)
             return 0;
         element->children_count = children;
-        element->children[0] = skin_parse_code_as_arg(&emptyline);
+        children_array[0] = skin_parse_code_as_arg(&emptyline);
     }
     else
     {    
-        element->children = skin_alloc_children(children);
-        if (!element->children)
+        children_array = skin_alloc_children(children);
+        if (!children_array)
             return 0;
         element->children_count = children;
 
         for(i = 0; i < children; i++)
         {
-            element->children[i] = skin_parse_code_as_arg(&cursor);
-            if (element->children[i] == NULL)
+            children_array[i] = skin_parse_code_as_arg(&cursor);
+            if (children_array[i] == NULL)
                 return 0;
             skip_whitespace(&cursor);
 #ifdef ROCKBOX
@@ -1035,6 +1057,7 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
         }
     }
     *document = cursor;
+    element->children = skin_buffer_to_offset(children_array);
 
     return 1;
 }
@@ -1056,7 +1079,7 @@ static int skin_parse_comment(struct skin_element* element, const char** documen
     element->type = COMMENT;
     element->line = skin_line;
 #ifdef ROCKBOX 
-    element->data = NULL;
+    element->data = -1;
 #else    
     element->data = text = skin_alloc_string(length);
     if (!element->data)
@@ -1131,7 +1154,8 @@ struct skin_element* skin_alloc_element()
     if (!retval)
         return NULL;
     retval->type = UNKNOWN;
-    retval->next = NULL;
+    retval->next = skin_buffer_to_offset(NULL);
+    retval->params = skin_buffer_to_offset(NULL);
     retval->tag = NULL;
     retval->params_count = 0;
     retval->children_count = 0;
@@ -1144,16 +1168,8 @@ struct skin_element* skin_alloc_element()
  * enough for any tag. params should be used straight away by the callback
  * so this is safe.
  */
-struct skin_tag_parameter* skin_alloc_params(int count, bool use_shared_params)
+struct skin_tag_parameter* skin_alloc_params(int count)
 {
-#ifdef ROCKBOX
-    static struct skin_tag_parameter params[MAX_TAG_PARAMS];
-    if (use_shared_params && count <= MAX_TAG_PARAMS)
-    {
-        memset(params, 0, sizeof(params));
-        return params;
-    }
-#endif
     size_t size = sizeof(struct skin_tag_parameter) * count;
     return (struct skin_tag_parameter*)skin_buffer_alloc(size);
 
diff --git a/lib/skin_parser/skin_parser.h b/lib/skin_parser/skin_parser.h
index 3e06349..c4df9a2 100644
--- a/lib/skin_parser/skin_parser.h
+++ b/lib/skin_parser/skin_parser.h
@@ -29,6 +29,20 @@ extern "C"
 #include <stdlib.h>
 #include <stdbool.h>
 
+
+/* Use this type and macro to convert a pointer from the
+ * skin buffer to a useable pointer */
+typedef long skinoffset;
+#define SKINOFFSETTOPTR(base, offset) ((offset) < 0 ? NULL : ((void*)&base[offset]))
+#define PTRTOSKINOFFSET(base, pointer) ((pointer) ? ((void*)pointer-(void*)base) : -1)
+/* Use this macro when declaring a variable to self-document the code.
+ * type is the actual type being pointed to (i.e OFFSETTYPE(char*) foo )
+ * 
+ * WARNING: Don't use the PTRTOSKINOFFSET() around a function call as it wont
+ * do what you expect.
+ */
+#define OFFSETTYPE(type) skinoffset
+
 /********************************************************************
  ****** Data Structures *********************************************
  *******************************************************************/
@@ -78,8 +92,8 @@ struct skin_tag_parameter
     union
     {
         int number;
-        char* text;
-        struct skin_element* code;
+        OFFSETTYPE(char*) text;
+        OFFSETTYPE(struct skin_element*) code;
     } data;
 
     char type_code;
@@ -92,20 +106,20 @@ struct skin_tag_parameter
 struct skin_element
 {
     /* Link to the next element */
-    struct skin_element* next;
+    OFFSETTYPE(struct skin_element*) next;
     /* Pointer to an array of children */
-    struct skin_element** children;
+    OFFSETTYPE(struct skin_element**) children;
     /* Placeholder for element data
      * TEXT and COMMENT uses it for the text string
      * TAG, VIEWPORT, LINE, etc may use it for post parse extra storage
      */
-    void* data;
+    OFFSETTYPE(void*) data;
 
     /* The tag or conditional name */
     const struct tag_info *tag;
 
     /* Pointer to an array of parameters */
-    struct skin_tag_parameter* params;
+    OFFSETTYPE(struct skin_tag_parameter*) params;
 
     /* Number of elements in the children array */
     short children_count;
@@ -141,7 +155,7 @@ struct skin_element* skin_parse(const char* document);
 /* Memory management functions */
 struct skin_element* skin_alloc_element(void);
 struct skin_element** skin_alloc_children(int count);
-struct skin_tag_parameter* skin_alloc_params(int count, bool use_shared_params);
+struct skin_tag_parameter* skin_alloc_params(int count);
 char* skin_alloc_string(int length);
 
 void skin_free_tree(struct skin_element* root);
