Index: apps/gui/gwps-common.c
===================================================================
--- apps/gui/gwps-common.c	(révision 13058)
+++ apps/gui/gwps-common.c	(copie de travail)
@@ -81,12 +81,10 @@
 {
     bool draw = global_settings.statusbar;
 
-    if(wps->data->wps_sb_tag 
-        && wps->data->show_sb_on_wps)
-        draw = true;
-    else if(wps->data->wps_sb_tag)
-        draw = false;
-    if(draw)
+    if (wps->data->wps_sb_tag)
+        draw = wps->data->show_sb_on_wps;
+
+    if (draw)
         gui_statusbar_draw(wps->statusbar, force);
 }
 #else
@@ -1012,15 +1010,13 @@
             }
         }
 #endif
-
         case WPS_TOKEN_BATTERY_SLEEPTIME:
         {
             if (get_sleep_timer() == 0)
                 return NULL;
             else
             {
-                format_time(buf, buf_size, \
-                            get_sleep_timer() * 1000);
+                format_time(buf, buf_size, get_sleep_timer() * 1000);
                 return buf;
             }
         }
@@ -1377,6 +1373,7 @@
     char temp_buf[128];
     char *buf = linebuf;  /* will always point to the writing position */
     char *linebuf_end = linebuf + linebuf_size - 1;
+    int i, last_token_idx;
     bool update = false;
 
     /* alignment-related variables */
@@ -1384,16 +1381,14 @@
     char* cur_align_start;
     cur_align_start = buf;
     cur_align = WPS_ALIGN_LEFT;
-    align->left = 0;
-    align->center = 0;
-    align->right = 0;
+    align->left = NULL;
+    align->center = NULL;
+    align->right = NULL;
 
-    /* start at the beginning of the current (sub)line */
-    int i = data->format_lines[line][subline];
-
-    while (data->tokens[i].type != WPS_TOKEN_EOL
-           && data->tokens[i].type != WPS_TOKEN_SUBLINE_SEPARATOR
-           && i < data->num_tokens)
+    /* Process all tokens of the desired subline */
+    last_token_idx = wps_last_token_index(data, line, subline);
+    for (i = wps_first_token_index(data, line, subline);
+         i <= last_token_idx; i++)
     {
         switch(data->tokens[i].type)
         {
@@ -1460,8 +1455,7 @@
             default:
             {
                 /* get the value of the tag and copy it to the buffer */
-                char *value = get_tag(gwps, i, temp_buf,
-                                      sizeof(temp_buf), NULL);
+                char *value = get_tag(gwps,i,temp_buf,sizeof(temp_buf),NULL);
                 if (value)
                 {
                     update = true;
@@ -1471,7 +1465,6 @@
                 break;
             }
         }
-        i++;
     }
 
     /* close the current alignment */
@@ -1496,13 +1489,14 @@
 static void get_subline_timeout(struct gui_wps *gwps, int line, int subline)
 {
     struct wps_data *data = gwps->data;
-    int i = data->format_lines[line][subline];
+    int i;
+    int subline_idx = wps_subline_index(data, line, subline);
+    int last_token_idx = wps_last_token_index(data, line, subline);
 
-    data->time_mult[line][subline] = DEFAULT_SUBLINE_TIME_MULTIPLIER;
+    data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
 
-    while (data->tokens[i].type != WPS_TOKEN_EOL
-           && data->tokens[i].type != WPS_TOKEN_SUBLINE_SEPARATOR
-           && i < data->num_tokens)
+    for (i = wps_first_token_index(data, line, subline);
+         i <= last_token_idx; i++)
     {
         switch(data->tokens[i].type)
         {
@@ -1518,32 +1512,33 @@
                 break;
 
             case WPS_TOKEN_SUBLINE_TIMEOUT:
-                data->time_mult[line][subline] = data->tokens[i].value.i;
+                data->sublines[subline_idx].time_mult = data->tokens[i].value.i;
                 break;
 
             default:
                 break;
         }
-        i++;
     }
 }
 
-/* Calculate which subline should be displayed for each line */
-static bool get_curr_subline(struct gui_wps *gwps, int line)
+/* Calculates which subline should be displayed for the specified line
+   Returns true iff the subline must be refreshed */
+static bool update_curr_subline(struct gui_wps *gwps, int line)
 {
     struct wps_data *data = gwps->data;
 
-    int search, search_start;
+    int search, search_start, num_sublines;
     bool reset_subline;
     bool new_subline_refresh;
     bool only_one_subline;
 
-    reset_subline = (data->curr_subline[line] == SUBLINE_RESET);
+    num_sublines = data->lines[line].num_sublines;
+    reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET);
     new_subline_refresh = false;
     only_one_subline = false;
 
     /* if time to advance to next sub-line  */
-    if (TIME_AFTER(current_tick, data->subline_expire_time[line] - 1) ||
+    if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) ||
         reset_subline)
     {
         /* search all sublines until the next subline with time > 0
@@ -1551,43 +1546,44 @@
         if (reset_subline)
             search_start = 0;
         else
-            search_start = data->curr_subline[line];
+            search_start = data->lines[line].curr_subline;
 
-        for (search = 0; search < WPS_MAX_SUBLINES; search++)
+        for (search = 0; search < num_sublines; search++)
         {
-            data->curr_subline[line]++;
+            data->lines[line].curr_subline++;
 
             /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */
-            if ((!data->format_lines[line][data->curr_subline[line]]) ||
-                (data->curr_subline[line] == WPS_MAX_SUBLINES))
+            if (data->lines[line].curr_subline == num_sublines)
             {
-                if (data->curr_subline[line] == 1)
+                if (data->lines[line].curr_subline == 1)
                     only_one_subline = true;
-                data->curr_subline[line] = 0;
+                data->lines[line].curr_subline = 0;
             }
 
             /* if back where we started after search or
                 only one subline is defined on the line */
-            if (((search > 0) && (data->curr_subline[line] == search_start)) ||
+            if (((search > 0) && (data->lines[line].curr_subline == search_start)) ||
                 only_one_subline)
             {
                 /* no other subline with a time > 0 exists */
-                data->subline_expire_time[line] = (reset_subline?
-                    current_tick : data->subline_expire_time[line]) + 100 * HZ;
+                data->lines[line].subline_expire_time = (reset_subline ?
+                    current_tick : data->lines[line].subline_expire_time) + 100 * HZ;
                 break;
             }
             else
             {
                 /* get initial time multiplier for this subline */
-                get_subline_timeout(gwps, line, data->curr_subline[line]);
+                get_subline_timeout(gwps, line, data->lines[line].curr_subline);
 
+                int subline_idx = wps_subline_index(data, line, search);
+
                 /* only use this subline if subline time > 0 */
-                if (data->time_mult[line][data->curr_subline[line]] > 0)
+                if (data->sublines[subline_idx].time_mult > 0)
                 {
                     new_subline_refresh = true;
-                    data->subline_expire_time[line] = (reset_subline ?
-                        current_tick : data->subline_expire_time[line]) +
-                        BASE_SUBLINE_TIME * data->time_mult[line][data->curr_subline[line]];
+                    data->lines[line].subline_expire_time = (reset_subline ?
+                        current_tick : data->lines[line].subline_expire_time) +
+                        BASE_SUBLINE_TIME * data->sublines[subline_idx].time_mult;
                     break;
                 }
             }
@@ -1779,7 +1775,7 @@
     if(!gwps || !data || !state || !display)
         return false;
 
-    int line, i;
+    int line, i, subline_idx;
     unsigned char flags;
     char linebuf[MAX_PATH];
 
@@ -1814,7 +1810,7 @@
     {
         for (i = 0; i < data->num_lines; i++)
         {
-            data->curr_subline[i] = SUBLINE_RESET;
+            data->lines[i].curr_subline = SUBLINE_RESET;
         }
     }
 
@@ -1840,15 +1836,16 @@
         update_line = false;
 
         /* get current subline for the line */
-        new_subline_refresh = get_curr_subline(gwps, line);
+        new_subline_refresh = update_curr_subline(gwps, line);
 
-        flags = data->line_type[line][data->curr_subline[line]];
+        subline_idx = wps_subline_index(data, line, data->lines[line].curr_subline);
+        flags = data->sublines[subline_idx].line_type;
 
-        if (refresh_mode == WPS_REFRESH_ALL || flags & refresh_mode
+        if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode)
             || new_subline_refresh)
         {
             /* get_line tells us if we need to update the line */
-            update_line = get_line(gwps, line, data->curr_subline[line],
+            update_line = get_line(gwps, line, data->lines[line].curr_subline,
                                    &align, linebuf, sizeof(linebuf));
         }
 
@@ -1947,3 +1944,24 @@
 
     return true;
 }
+
+int wps_subline_index(struct wps_data *data, int line, int subline) {
+    return data->lines[line].first_subline_idx + subline;
+}
+
+int wps_first_token_index(struct wps_data *data, int line, int subline) {
+    int first_subline_idx = data->lines[line].first_subline_idx;
+    return data->sublines[first_subline_idx + subline].first_token_idx;
+}
+
+int wps_last_token_index(struct wps_data *data, int line, int subline) {
+    int first_subline_idx = data->lines[line].first_subline_idx;
+    int idx = first_subline_idx + subline;
+    if (idx < data->num_sublines - 1) {
+        /* This subline ends where the next begins */
+        return data->sublines[idx+1].first_token_idx - 1;
+    } else {
+        /* The last subline goes to the end */
+        return data->num_tokens - 1;
+    }
+}
Index: apps/gui/wps_debug.c
===================================================================
--- apps/gui/wps_debug.c	(révision 13058)
+++ apps/gui/wps_debug.c	(copie de travail)
@@ -24,107 +24,122 @@
 #include "gwps.h"
 #include "debug.h"
 
+static char *next_str(bool next) {
+    return next ? "next" : "";
+}
+
 void dump_wps_tokens(struct wps_data *data)
 {
+    struct wps_token *token;
     int i, j;
     int indent = 0;
     char buf[64];
     bool next;
 
+    if (data->num_tokens > WPS_MAX_TOKENS) {
+        DEBUGF("Number of tokens is too high (%d)!!!\n", data->num_tokens);
+        return;
+    }
+
     /* Dump parsed WPS */
-    for(i = 0; i < data->num_tokens && i < WPS_MAX_TOKENS; i++) {
+    for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++) {
+        next = token->next;
 
-        next = data->tokens[i].next;
-
-        switch(data->tokens[i].type) {
+        switch(token->type) {
             case WPS_TOKEN_UNKNOWN:
                 snprintf(buf, sizeof(buf), "Unknown token");
                 break;
             case WPS_TOKEN_CHARACTER:
                 snprintf(buf, sizeof(buf), "Character '%c'",
-                         data->tokens[i].value.c);
+                         token->value.c);
                 break;
 
             case WPS_TOKEN_STRING:
                 snprintf(buf, sizeof(buf), "String '%s'",
-                         data->strings[data->tokens[i].value.i]);
+                         data->strings[token->value.i]);
                 break;
 
-            case WPS_TOKEN_EOL:
-                snprintf(buf, sizeof(buf), "%s", "EOL");
-                break;
-
 #ifdef HAVE_LCD_BITMAP
             case WPS_TOKEN_ALIGN_LEFT:
-                snprintf(buf, sizeof(buf), "%s", "align left");
+                snprintf(buf, sizeof(buf), "align left");
                 break;
 
             case WPS_TOKEN_ALIGN_CENTER:
-                snprintf(buf, sizeof(buf), "%s", "align center");
+                snprintf(buf, sizeof(buf), "align center");
                 break;
 
             case WPS_TOKEN_ALIGN_RIGHT:
-                snprintf(buf, sizeof(buf), "%s", "align right");
+                snprintf(buf, sizeof(buf), "align right");
                 break;
 #endif
 
+            case WPS_TOKEN_SUBLINE_TIMEOUT:
+                snprintf(buf, sizeof(buf), "subline timeout value: %d",
+                         token->value.i);
+                break;
+
             case WPS_TOKEN_CONDITIONAL:
-            snprintf(buf, sizeof(buf), "%s, %d options", "conditional",
-                     data->tokens[i].value.i);
+                snprintf(buf, sizeof(buf), "conditional, %d options",
+                        token->value.i);
                 break;
 
             case WPS_TOKEN_CONDITIONAL_START:
-                snprintf(buf, sizeof(buf), "%s, next cond: %d",
-                         "conditional start", data->tokens[i].value.i);
+                snprintf(buf, sizeof(buf), "conditional start, next cond: %d",
+                         token->value.i);
                 indent++;
                 break;
 
             case WPS_TOKEN_CONDITIONAL_OPTION:
-                snprintf(buf, sizeof(buf), "%s, next cond: %d",
-                         "conditional option", data->tokens[i].value.i);
+                snprintf(buf, sizeof(buf), "conditional option, next cond: %d",
+                         token->value.i);
                 break;
 
             case WPS_TOKEN_CONDITIONAL_END:
-                snprintf(buf, sizeof(buf), "%s", "conditional end");
+                snprintf(buf, sizeof(buf), "conditional end");
                 indent--;
                 break;
 
 #ifdef HAVE_LCD_BITMAP
             case WPS_TOKEN_IMAGE_PRELOAD:
-                snprintf(buf, sizeof(buf), "%s", "preload image");
+                snprintf(buf, sizeof(buf), "preload image");
                 break;
 
             case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY:
-                snprintf(buf, sizeof(buf), "%s %d", "display preloaded image",
-                         data->tokens[i].value.i);
+                snprintf(buf, sizeof(buf), "display preloaded image %d",
+                         token->value.i);
                 break;
 
             case WPS_TOKEN_IMAGE_DISPLAY:
-                snprintf(buf, sizeof(buf), "%s", "display image");
+                snprintf(buf, sizeof(buf), "display image");
                 break;
 #endif
 
 #ifdef HAS_BUTTON_HOLD
             case WPS_TOKEN_MAIN_HOLD:
-                snprintf(buf, sizeof(buf), "%s", "mode hold");
+                snprintf(buf, sizeof(buf), "mode hold");
                 break;
 #endif
 
 #ifdef HAS_REMOTE_BUTTON_HOLD
             case WPS_TOKEN_REMOTE_HOLD:
-                snprintf(buf, sizeof(buf), "%s", "mode remote hold");
+                snprintf(buf, sizeof(buf), "mode remote hold");
                 break;
 #endif
 
             case WPS_TOKEN_REPEAT_MODE:
-                snprintf(buf, sizeof(buf), "%s", "mode repeat");
+                snprintf(buf, sizeof(buf), "mode repeat");
                 break;
 
             case WPS_TOKEN_PLAYBACK_STATUS:
-                snprintf(buf, sizeof(buf), "%s", "mode playback");
+                snprintf(buf, sizeof(buf), "mode playback");
                 break;
 
 #if CONFIG_RTC
+            case WPS_TOKEN_RTC:
+                snprintf(buf, sizeof(buf), "real-time clock",
+                        token->value.c);
+                break;
+
             case WPS_TOKEN_RTC_DAY_OF_MONTH:
             case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
             case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
@@ -142,199 +157,159 @@
             case WPS_TOKEN_RTC_MONTH_NAME:
             case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
             case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
-            case WPS_TOKEN_RTC:
-            snprintf(buf, sizeof(buf), "%s %c", "real-time clock tag:",
-                     data->tokens[i].value.c);
+                snprintf(buf, sizeof(buf), "real-time clock tag: %c",
+                        token->value.c);
                 break;
 #endif
 
 #ifdef HAVE_LCD_BITMAP
             case WPS_TOKEN_IMAGE_BACKDROP:
-                snprintf(buf, sizeof(buf), "%s", "backdrop image");
+                snprintf(buf, sizeof(buf), "backdrop image");
                 break;
 
             case WPS_TOKEN_IMAGE_PROGRESS_BAR:
-                snprintf(buf, sizeof(buf), "%s", "progressbar bitmap");
+                snprintf(buf, sizeof(buf), "progressbar bitmap");
                 break;
 
-
-            case WPS_TOKEN_STATUSBAR_ENABLED:
-                snprintf(buf, sizeof(buf), "%s", "statusbar enable");
-                break;
-
-            case WPS_TOKEN_STATUSBAR_DISABLED:
-                snprintf(buf, sizeof(buf), "%s", "statusbar disable");
-                break;
-
             case WPS_TOKEN_PEAKMETER:
-                snprintf(buf, sizeof(buf), "%s", "peakmeter");
+                snprintf(buf, sizeof(buf), "peakmeter");
                 break;
 #endif
 
             case WPS_TOKEN_PROGRESSBAR:
-                snprintf(buf, sizeof(buf), "%s", "progressbar");
+                snprintf(buf, sizeof(buf), "progressbar");
                 break;
 
 #ifdef HAVE_LCD_CHARCELLS
             case WPS_TOKEN_PLAYER_PROGRESSBAR:
-                snprintf(buf, sizeof(buf), "%s", "full line progressbar");
+                snprintf(buf, sizeof(buf), "full line progressbar");
                 break;
 #endif
 
             case WPS_TOKEN_TRACK_TIME_ELAPSED:
-                snprintf(buf, sizeof(buf), "%s", "time elapsed in track");
+                snprintf(buf, sizeof(buf), "time elapsed in track");
                 break;
 
             case WPS_TOKEN_PLAYLIST_ENTRIES:
-                snprintf(buf, sizeof(buf), "%s", "number of entries in playlist");
+                snprintf(buf, sizeof(buf), "number of entries in playlist");
                 break;
 
             case WPS_TOKEN_PLAYLIST_NAME:
-                snprintf(buf, sizeof(buf), "%s", "playlist name");
+                snprintf(buf, sizeof(buf), "playlist name");
                 break;
 
             case WPS_TOKEN_PLAYLIST_POSITION:
-                snprintf(buf, sizeof(buf), "%s", "position in playlist");
+                snprintf(buf, sizeof(buf), "position in playlist");
                 break;
 
             case WPS_TOKEN_TRACK_TIME_REMAINING:
-                snprintf(buf, sizeof(buf), "%s", "time remaining in track");
+                snprintf(buf, sizeof(buf), "time remaining in track");
                 break;
 
             case WPS_TOKEN_PLAYLIST_SHUFFLE:
-                snprintf(buf, sizeof(buf), "%s", "playlist shuffle mode");
+                snprintf(buf, sizeof(buf), "playlist shuffle mode");
                 break;
 
             case WPS_TOKEN_TRACK_LENGTH:
-                snprintf(buf, sizeof(buf), "%s", "track length");
+                snprintf(buf, sizeof(buf), "track length");
                 break;
 
             case WPS_TOKEN_VOLUME:
-                snprintf(buf, sizeof(buf), "%s", "volume");
+                snprintf(buf, sizeof(buf), "volume");
                 break;
 
             case WPS_TOKEN_METADATA_ARTIST:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track artist");
+                snprintf(buf, sizeof(buf), "%strack artist", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_COMPOSER:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track composer");
+                snprintf(buf, sizeof(buf), "%strack composer", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_ALBUM:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track album");
+                snprintf(buf, sizeof(buf), "%strack album", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_GENRE:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track genre");
+                snprintf(buf, sizeof(buf), "%strack genre", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_TRACK_NUMBER:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track number");
+                snprintf(buf, sizeof(buf), "%strack number", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_TRACK_TITLE:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track title");
+                snprintf(buf, sizeof(buf), "%strack title", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_VERSION:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track ID3 version");
+                snprintf(buf, sizeof(buf), "%strack ID3 version", next_str(next));
                 break;
 
             case WPS_TOKEN_METADATA_YEAR:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "track year");
+                snprintf(buf, sizeof(buf), "%strack year", next_str(next));
                 break;
 
             case WPS_TOKEN_BATTERY_PERCENT:
-                snprintf(buf, sizeof(buf), "%s", "battery percentage");
+                snprintf(buf, sizeof(buf), "battery percentage");
                 break;
 
             case WPS_TOKEN_BATTERY_VOLTS:
-                snprintf(buf, sizeof(buf), "%s", "battery voltage");
+                snprintf(buf, sizeof(buf), "battery voltage");
                 break;
 
             case WPS_TOKEN_BATTERY_TIME:
-                snprintf(buf, sizeof(buf), "%s", "battery time left");
+                snprintf(buf, sizeof(buf), "battery time left");
                 break;
 
             case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
-                snprintf(buf, sizeof(buf), "%s", "battery charger connected");
+                snprintf(buf, sizeof(buf), "battery charger connected");
                 break;
 
             case WPS_TOKEN_BATTERY_CHARGING:
-                snprintf(buf, sizeof(buf), "%s", "battery charging");
+                snprintf(buf, sizeof(buf), "battery charging");
                 break;
 
             case WPS_TOKEN_FILE_BITRATE:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file bitrate");
+                snprintf(buf, sizeof(buf), "%sfile bitrate", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_CODEC:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file codec");
+                snprintf(buf, sizeof(buf), "%sfile codec", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_FREQUENCY:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file audio frequency");
+                snprintf(buf, sizeof(buf), "%sfile audio frequency", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_NAME:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file name");
+                snprintf(buf, sizeof(buf), "%sfile name", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file name with extension");
+                snprintf(buf, sizeof(buf), "%sfile name with extension", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_PATH:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file path");
+                snprintf(buf, sizeof(buf), "%sfile path", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_SIZE:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file size");
+                snprintf(buf, sizeof(buf), "%sfile size", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_VBR:
-                snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "",
-                         "file is vbr");
+                snprintf(buf, sizeof(buf), "%sfile is vbr", next_str(next));
                 break;
 
             case WPS_TOKEN_FILE_DIRECTORY:
-                snprintf(buf, sizeof(buf), "%s%s: %d", next ? "next " : "",
-                         "file directory, level",
-                         data->tokens[i].value.i);
+                snprintf(buf, sizeof(buf), "%sfile directory, level: %d", next_str(next),
+                         token->value.i);
                 break;
 
-            case WPS_TOKEN_SCROLL:
-                snprintf(buf, sizeof(buf), "%s", "scrolling line");
-                break;
-
-            case WPS_TOKEN_SUBLINE_TIMEOUT:
-                snprintf(buf, sizeof(buf), "%s: %d", "subline timeout value",
-                         data->tokens[i].value.i);
-                break;
-
-            case WPS_TOKEN_SUBLINE_SEPARATOR:
-                snprintf(buf, sizeof(buf), "%s", "subline separator");
-                break;
-
             default:
-                snprintf(buf, sizeof(buf), "%s (code: %d)", "FIXME",
-                         data->tokens[i].type);
+                snprintf(buf, sizeof(buf), "FIXME (code: %d)",
+                         token->type);
                 break;
         }
 
@@ -342,24 +317,43 @@
             DEBUGF("\t");
         }
 
-        DEBUGF("[%03d] = %s\n", i, buf);
+        DEBUGF("[%3d] = (%2d) %s\n", i, token->type, buf);
     }
     DEBUGF("\n");
 }
 
 void print_line_info(struct wps_data *data)
 {
-    int line, subline;
+    int i, j;
+    struct wps_line *line;
+    struct wps_subline *subline;
 
-    DEBUGF("line/subline start indexes :\n");
-    for (line = 0; line < data->num_lines; line++)
+    DEBUGF("Number of lines   : %d\n", data->num_lines);
+    DEBUGF("Number of sublines: %d\n", data->num_sublines);
+    DEBUGF("Number of tokens  : %d\n", data->num_tokens);
+    DEBUGF("\n");
+
+    for (i = 0, line = data->lines; i < data->num_lines; i++,line++)
     {
-        DEBUGF("%2d. ", line);
-        for (subline = 0; subline < data->num_sublines[line]; subline++)
+        DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n",
+                i, line->num_sublines, line->first_subline_idx);
+
+        for (j = 0, subline = data->sublines + line->first_subline_idx;
+             j < line->num_sublines; j++, subline++)
         {
-            DEBUGF("%3d ", data->format_lines[line][subline]);
+            DEBUGF("    Subline %d: first_token=%3d, last_token=%3d",
+                    j, subline->first_token_idx,
+                    wps_last_token_index(data, i, j));
+
+            if (subline->line_type & WPS_REFRESH_SCROLL)
+                DEBUGF(", scrolled");
+            else if (subline->line_type & WPS_REFRESH_PLAYER_PROGRESS)
+                DEBUGF(", progressbar");
+            else if (subline->line_type & WPS_REFRESH_PEAK_METER)
+                DEBUGF(", peakmeter");
+
+            DEBUGF("\n");
         }
-        DEBUGF("\n");
     }
 
     DEBUGF("\n");
@@ -367,21 +361,21 @@
 
 void print_wps_strings(struct wps_data *data)
 {
-    DEBUGF("strings :\n");
+    DEBUGF("Strings:\n");
     int i, len = 0;
     for (i=0; i < data->num_strings; i++)
     {
         len += strlen(data->strings[i]);
         DEBUGF("%2d: '%s'\n", i, data->strings[i]);
     }
-    DEBUGF("total length : %d\n", len);
+    DEBUGF("Total length: %d\n", len);
     DEBUGF("\n");
 }
 
 #ifdef HAVE_LCD_BITMAP
 void print_img_cond_indexes(struct wps_data *data)
 {
-    DEBUGF("image conditional indexes :\n");
+    DEBUGF("Image conditional indexes:\n");
     int i;
     for (i=0; i < MAX_IMAGES; i++)
     {
Index: apps/gui/gwps.h
===================================================================
--- apps/gui/gwps.h	(révision 13058)
+++ apps/gui/gwps.h	(copie de travail)
@@ -71,23 +71,25 @@
 #define MAX_IMAGES (26*2) /* a-z and A-Z */
 #define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
                    + (2*LCD_HEIGHT*LCD_WIDTH/8))
-#define WPS_MAX_LINES (LCD_HEIGHT/5+1)
-#define WPS_MAX_TOKENS 1024
-#define WPS_MAX_STRINGS 128
-#define STRING_BUFFER_SIZE 512
-#define WPS_MAX_COND_LEVEL 10
 
+#define WPS_MAX_LINES       (LCD_HEIGHT/5+1)
+#define WPS_MAX_SUBLINES    (WPS_MAX_LINES*3)
+#define WPS_MAX_TOKENS      1024
+#define WPS_MAX_STRINGS     128
+#define STRING_BUFFER_SIZE  512
+#define WPS_MAX_COND_LEVEL  10
+
 #else
 
-#define WPS_MAX_LINES 2
-#define WPS_MAX_TOKENS 64
-#define WPS_MAX_STRINGS 32
-#define STRING_BUFFER_SIZE 64
-#define WPS_MAX_COND_LEVEL 5
+#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 WPS_MAX_SUBLINES 12
 #define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */
 #define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to
                                 (1/HZ sec, or 100ths of sec) */
@@ -100,18 +102,13 @@
     /* Markers */
     WPS_TOKEN_CHARACTER,
     WPS_TOKEN_STRING,
-    WPS_TOKEN_EOL,
 
     /* Alignment */
     WPS_TOKEN_ALIGN_LEFT,
     WPS_TOKEN_ALIGN_CENTER,
     WPS_TOKEN_ALIGN_RIGHT,
 
-    /* Scrolling */
-    WPS_TOKEN_SCROLL,
-
-    /* Alternating sublines */
-    WPS_TOKEN_SUBLINE_SEPARATOR,
+    /* Sublines */
     WPS_TOKEN_SUBLINE_TIMEOUT,
 
     /* Battery */
@@ -228,12 +225,6 @@
     WPS_TOKEN_PLAYLIST_POSITION,
     WPS_TOKEN_PLAYLIST_SHUFFLE,
 
-#ifdef HAVE_LCD_BITMAP
-    /* Statusbar */
-    WPS_TOKEN_STATUSBAR_ENABLED,
-    WPS_TOKEN_STATUSBAR_DISABLED,
-#endif
-
 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
     /* Virtual LED */
     WPS_TOKEN_VLED_HDD
@@ -242,14 +233,53 @@
 
 struct wps_token {
     enum wps_token_type type;
+
+    /* Whether the tag (e.g. track name or the album) refers the
+       current or the next song (false=current, true=next) */
     bool next;
+
     union {
         char c;
         unsigned short i;
     } value;
 };
 
+/* Description of a subline on the WPS */
+struct wps_subline {
 
+    /* Bit or'ed WPS_REFRESH_xxx */
+    unsigned char line_type;
+
+    /* Index of the first token for this subline in the token array.
+       Tokens of this subline end where tokens for the next subline
+       begin. */
+    int first_token_idx;
+
+    /* How long the subline should be displayed, in 10ths of sec */
+    int time_mult;
+};
+
+/* Description of a line on the WPS. A line is a set of sublines.
+   A subline is displayed for a certain amount of time. After that,
+   the next subline of the line is displayed. And so on. */
+struct wps_line {
+
+    /* Number of sublines in this line */
+    int num_sublines;
+
+    /* Index of the first subline of this line in the subline array.
+       Sublines for this line end where sublines for the next line begin. */
+    int first_subline_idx;
+
+    /* Number (0-based) of the subline within this line currently being displayed */
+    int curr_subline;
+
+    /* When the next subline of this line should be displayed
+       (absolute time value in ticks) */
+    long subline_expire_time;
+};
+
+
 /* wps_data
    this struct holds all necessary data which describes the
    viewable content of a wps */
@@ -273,20 +303,24 @@
     unsigned short wps_progress_pat[8];
     bool full_line_progressbar;
 #endif
-    unsigned short format_lines[WPS_MAX_LINES][WPS_MAX_SUBLINES];
-    unsigned char num_lines;
-    unsigned char line_type[WPS_MAX_LINES][WPS_MAX_SUBLINES];
-    unsigned short time_mult[WPS_MAX_LINES][WPS_MAX_SUBLINES];
-    long subline_expire_time[WPS_MAX_LINES];
-    short curr_subline[WPS_MAX_LINES];
-    unsigned char num_sublines[WPS_MAX_LINES];
+    /* Number of lines in the WPS. During WPS parsing, this is
+       the index of the line being parsed. */
+    int num_lines;
+    struct wps_line lines[WPS_MAX_LINES];
 
+    /* Total number of sublines in the WPS. During WPS parsing, this is
+       the index of the subline where the parsed tokens are added to. */
+    int num_sublines;
+    struct wps_subline sublines[WPS_MAX_SUBLINES];
+
+    /* Total number of tokens in the WPS. During WPS parsing, this is
+       the index of the token being parsed. */
+    int num_tokens;
     struct wps_token tokens[WPS_MAX_TOKENS];
-    unsigned short num_tokens;
 
     char string_buffer[STRING_BUFFER_SIZE];
     char *strings[WPS_MAX_STRINGS];
-    unsigned char num_strings;
+    int num_strings;
 
     bool wps_loaded;
 };
@@ -300,6 +334,24 @@
                    const char *buf,
                    bool isfile);
 
+/* Returns the index of the subline in the subline array
+   line - 0-based line number
+   subline - 0-based subline number within the line
+ */
+int wps_subline_index(struct wps_data *wps_data, int line, int subline);
+
+/* Returns the index of the first subline's token in the token array
+   line - 0-based line number
+   subline - 0-based subline number within the line
+ */
+int wps_first_token_index(struct wps_data *data, int line, int subline);
+
+/* Returns the index of the last subline's token in the token array.
+   line - 0-based line number
+   subline - 0-based subline number within the line
+ */
+int wps_last_token_index(struct wps_data *data, int line, int subline);
+
 /* wps_data end */
 
 /* wps_state
@@ -329,11 +381,11 @@
 /* wps_state end*/
 
 /* gui_wps
-   defines a wps with it's data, state,
+   defines a wps with its data, state,
    and the screen on which the wps-content should be drawn */
 struct gui_wps
 {
-    struct screen * display;
+    struct screen *display;
     struct wps_data *data;
     struct wps_state *state;
     struct gui_statusbar *statusbar;
Index: apps/gui/wps_parser.c
===================================================================
--- apps/gui/wps_parser.c	(révision 13058)
+++ apps/gui/wps_parser.c	(copie de travail)
@@ -69,11 +69,19 @@
 extern void print_wps_strings(struct wps_data *data);
 #endif
 
-/* special parsing function.
-   wps_bufptr points to the char following the tag.
-   The return value is the number of chars read. */
-typedef int (*wps_tag_parse_func)(const char *wps_bufptr, struct wps_data *wps_data);
+/* Function for parsing of details for a token. At the moment the
+   function is called, the token type has already been set. The
+   function must fill in the details and possibly add more tokens
+   to the token array. It should return the number of chars that
+   has been consumed.
 
+   wps_bufptr points to the char following the tag (i.e. where
+   details begin).
+   token is the pointer to the 'main' token being parsed
+   */
+typedef int (*wps_tag_parse_func)(const char *wps_bufptr,
+                struct wps_token *token, struct wps_data *wps_data);
+
 struct wps_tag {
     enum wps_token_type type;
     const char name[3];
@@ -82,17 +90,27 @@
 };
 
 /* prototypes of all special parse functions : */
-static int parse_subline_timeout(const char *wps_bufptr, struct wps_data *wps_data);
-static int parse_progressbar(const char *wps_bufptr, struct wps_data *wps_data);
-static int parse_dir_level(const char *wps_bufptr, struct wps_data *wps_data);
+static int parse_subline_timeout(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_progressbar(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_dir_level(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
 #ifdef HAVE_LCD_BITMAP
-static int parse_image_special(const char *wps_bufptr, struct wps_data *wps_data);
-static int parse_statusbar(const char *wps_bufptr, struct wps_data *wps_data);
-static int parse_image_display(const char *wps_bufptr, struct wps_data *wps_data);
-static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data);
+static int parse_image_special(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_statusbar_enable(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_statusbar_disable(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_image_display(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
+static int parse_image_load(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
 #endif /*HAVE_LCD_BITMAP */
 #if CONFIG_RTC
-static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data);
+static int parse_rtc_format(const char *wps_bufptr,
+        struct wps_token *token, struct wps_data *wps_data);
 
 /* RTC tokens array */
 static const struct wps_tag rtc_tags[] = {
@@ -113,8 +131,8 @@
     { WPS_TOKEN_RTC_MONTH_NAME,                "b", 0, NULL },
     { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON,     "u", 0, NULL },
     { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN,     "w", 0, NULL },
-    { WPS_TOKEN_CHARACTER,                     "\0",0, NULL }
-    /* the array MUST end with a "\0" token */
+    { WPS_TOKEN_CHARACTER,                     "",  0, NULL }
+    /* the array MUST end with an empty string (first char is \0) */
 };
 #endif
 
@@ -229,29 +247,30 @@
     { WPS_TOKEN_REPLAYGAIN,               "rg",  WPS_REFRESH_STATIC,  NULL },
 #endif
 
-    { WPS_TOKEN_SCROLL,                   "s",   WPS_REFRESH_SCROLL,  NULL },
+    { WPS_NO_TOKEN,                       "s",   WPS_REFRESH_SCROLL,  NULL },
     { WPS_TOKEN_SUBLINE_TIMEOUT,          "t",   0,  parse_subline_timeout },
 
 #ifdef HAVE_LCD_BITMAP
-    { WPS_TOKEN_STATUSBAR_ENABLED,        "we",  0,        parse_statusbar },
-    { WPS_TOKEN_STATUSBAR_DISABLED,       "wd",  0,        parse_statusbar },
+    { WPS_NO_TOKEN,                       "we",  0, parse_statusbar_enable },
+    { WPS_NO_TOKEN,                       "wd",  0, parse_statusbar_disable },
 
     { WPS_NO_TOKEN,                       "xl",  0,       parse_image_load },
 
     { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY,    "xd",  WPS_REFRESH_STATIC, parse_image_display },
 
-    {  WPS_TOKEN_IMAGE_DISPLAY,           "x",   0,       parse_image_load },
-    {  WPS_TOKEN_IMAGE_PROGRESS_BAR,      "P",   0,    parse_image_special },
+    { WPS_TOKEN_IMAGE_DISPLAY,            "x",   0,       parse_image_load },
+    { WPS_TOKEN_IMAGE_PROGRESS_BAR,       "P",   0,    parse_image_special },
 #if LCD_DEPTH > 1
-    {  WPS_TOKEN_IMAGE_BACKDROP,          "X",   0,    parse_image_special },
+    { WPS_TOKEN_IMAGE_BACKDROP,           "X",   0,    parse_image_special },
 #endif
 #endif
 
-    { WPS_TOKEN_UNKNOWN,                  "\0",  0, NULL }
-    /* the array MUST end with a "\0" token */
+    { WPS_TOKEN_UNKNOWN,                  "",    0, NULL }
+    /* the array MUST end with an empty string (first char is \0) */
 };
 
-
+/* Returns the number of chars that should be skipped to jump
+   immediately after the first eol, i.e. to the start of the next line */
 static int skip_end_of_line(const char *wps_bufptr)
 {
     int skip = 0;
@@ -260,10 +279,20 @@
     return ++skip;
 }
 
+/* Starts a new subline in the current line during parsing */
+static void wps_start_new_subline(struct wps_data *data) {
+    data->num_sublines++;
+    data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
+    data->lines[data->num_lines].num_sublines++;
+}
+
 #if CONFIG_RTC
-static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_rtc_format(const char *wps_bufptr,
+                            struct wps_token *token,
+                            struct wps_data *wps_data)
 {
     int skip = 0, i;
+    (void)token; /* kill the warning */
 
     /* RTC tag format ends with a c or a newline */
     while (wps_bufptr && *wps_bufptr != 'c' && *wps_bufptr != '\n')
@@ -276,7 +305,7 @@
         wps_data->num_tokens++;
         wps_data->tokens[wps_data->num_tokens].type = rtc_tags[i].type;
         wps_data->tokens[wps_data->num_tokens].value.c = *wps_bufptr;
-        skip ++;
+        skip++;
         wps_bufptr++;
     }
 
@@ -290,16 +319,23 @@
 
 #ifdef HAVE_LCD_BITMAP
 
-static int parse_statusbar(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_statusbar_enable(const char *wps_bufptr,
+                                  struct wps_token *token,
+                                  struct wps_data *wps_data)
 {
+    (void)token; /* Kill warnings */
     wps_data->wps_sb_tag = true;
+    wps_data->show_sb_on_wps = true;
+    return skip_end_of_line(wps_bufptr);
+}
 
-    if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_STATUSBAR_ENABLED)
-        wps_data->show_sb_on_wps = true;
-    else
-        wps_data->show_sb_on_wps = false;
-
-    /* Skip the rest of the line */
+static int parse_statusbar_disable(const char *wps_bufptr,
+                                   struct wps_token *token,
+                                   struct wps_data *wps_data)
+{
+    (void)token; /* Kill warnings */
+    wps_data->wps_sb_tag = true;
+    wps_data->show_sb_on_wps = false;
     return skip_end_of_line(wps_bufptr);
 }
 
@@ -357,10 +393,12 @@
     return buf;
 }
 
-static int parse_image_display(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_image_display(const char *wps_bufptr,
+                               struct wps_token *token,
+                               struct wps_data *wps_data)
 {
     int n = get_image_id(*wps_bufptr);
-    wps_data->tokens[wps_data->num_tokens].value.i = n;
+    token->value.i = n;
 
     /* if the image is in a conditional, remember it */
     if (level >= 0)
@@ -369,7 +407,9 @@
     return 1;
 }
 
-static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_image_load(const char *wps_bufptr,
+                            struct wps_token *token,
+                            struct wps_data *wps_data)
 {
     int n;
     const char *ptr = wps_bufptr;
@@ -421,7 +461,7 @@
             return skip_end_of_line(wps_bufptr);
         }
 
-        if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_DISPLAY)
+        if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
             wps_data->img[n].always_display = true;
     }
 
@@ -429,15 +469,17 @@
     return skip_end_of_line(wps_bufptr);
 }
 
-static int parse_image_special(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_image_special(const char *wps_bufptr,
+                               struct wps_token *token,
+                               struct wps_data *wps_data)
 {
-    if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_PROGRESS_BAR)
+    if (token->type == WPS_TOKEN_IMAGE_PROGRESS_BAR)
     {
         /* format: %P|filename.bmp| */
         pb_bmp_name = wps_bufptr + 1;
     }
 #if LCD_DEPTH > 1
-    else if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_BACKDROP)
+    else if (token->type == WPS_TOKEN_IMAGE_BACKDROP)
     {
         /* format: %X|filename.bmp| */
         backdrop_bmp_name = wps_bufptr + 1;
@@ -452,20 +494,27 @@
 
 #endif /* HAVE_LCD_BITMAP */
 
-static int parse_dir_level(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_dir_level(const char *wps_bufptr,
+                           struct wps_token *token,
+                           struct wps_data *wps_data)
 {
     char val[] = { *wps_bufptr, '\0' };
-    wps_data->tokens[wps_data->num_tokens].value.i = atoi(val);
+    token->value.i = atoi(val);
+    (void)wps_data; /* Kill warnings */
     return 1;
 }
 
-static int parse_subline_timeout(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_subline_timeout(const char *wps_bufptr,
+                                 struct wps_token *token,
+                                 struct wps_data *wps_data)
 {
     int skip = 0;
     int val = 0;
     bool have_point = false;
     bool have_tenth = false;
 
+    (void)wps_data; /* Kill the warning */
+
     while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
     {
         if (*wps_bufptr != '.')
@@ -490,13 +539,16 @@
     if (have_tenth == false)
         val *= 10;
 
-    wps_data->tokens[wps_data->num_tokens].value.i = val;
+    token->value.i = val;
 
     return skip;
 }
 
-static int parse_progressbar(const char *wps_bufptr, struct wps_data *wps_data)
+static int parse_progressbar(const char *wps_bufptr,
+                             struct wps_token *token,
+                             struct wps_data *wps_data)
 {
+    (void)token; /* Kill warnings */
 #ifdef HAVE_LCD_BITMAP
 
     short *vals[] = {
@@ -547,9 +599,8 @@
 static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
 {
     int skip = 0, taglen = 0;
-    int i = 0;
-    int line = wps_data->num_lines;
-    int subline = wps_data->num_sublines[line];
+    struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
+    const struct wps_tag *tag;
 
     switch(*wps_bufptr)
     {
@@ -560,47 +611,47 @@
         case '>':
         case ';':
             /* escaped characters */
-            wps_data->tokens[wps_data->num_tokens].type = WPS_TOKEN_CHARACTER;
-            wps_data->tokens[wps_data->num_tokens].value.c = *wps_bufptr;
+            token->type = WPS_TOKEN_CHARACTER;
+            token->value.c = *wps_bufptr;
             wps_data->num_tokens++;
             skip++;
             break;
 
         case '?':
             /* conditional tag */
-            wps_data->tokens[wps_data->num_tokens].type = WPS_TOKEN_CONDITIONAL;
+            token->type = WPS_TOKEN_CONDITIONAL;
             level++;
             condindex[level] = wps_data->num_tokens;
             numoptions[level] = 1;
             wps_data->num_tokens++;
+            token++;
             wps_bufptr++;
             skip++;
             /* no "break" because a '?' is followed by a regular tag */
 
         default:
             /* find what tag we have */
-            while (all_tags[i].name &&
-                   strncmp(wps_bufptr, all_tags[i].name, strlen(all_tags[i].name)))
-                i++;
+            for (tag = all_tags;
+                 strncmp(wps_bufptr, tag->name, strlen(tag->name)) != 0;
+                 tag++) ;
 
-            taglen  = strlen(all_tags[i].name);
+            taglen = strlen(tag->name);
             skip += taglen;
-            wps_data->tokens[wps_data->num_tokens].type = all_tags[i].type;
+            token->type = tag->type;
+            wps_data->sublines[wps_data->num_sublines].line_type |= tag->refresh_type;
 
             /* if the tag has a special parsing function, we call it */
-            if (all_tags[i].parse_func)
-                skip += all_tags[i].parse_func(wps_bufptr + taglen, wps_data);
+            if (tag->parse_func)
+                skip += tag->parse_func(wps_bufptr + taglen, token, wps_data);
 
             /* Some tags we don't want to save as tokens */
-            if (all_tags[i].type == WPS_NO_TOKEN)
+            if (tag->type == WPS_NO_TOKEN)
                 break;
 
             /* tags that start with 'F', 'I' or 'D' are for the next file */
-            if ( *(all_tags[i].name) == 'I' || *(all_tags[i].name) == 'F'
-                                            || *(all_tags[i].name) == 'D')
-                wps_data->tokens[wps_data->num_tokens].next = true;
+            if ( *(tag->name) == 'I' || *(tag->name) == 'F' || *(tag->name) == 'D')
+                token->next = true;
 
-            wps_data->line_type[line][subline] |= all_tags[i].refresh_type;
             wps_data->num_tokens++;
             break;
     }
@@ -608,17 +659,19 @@
     return skip;
 }
 
+/* Parses the WPS.
+   data is the pointer to the structure where the parsed WPS should be stored.
+        It is initialised.
+   wps_bufptr points to the string containing the WPS tags */
 static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
 {
     if (!data || !wps_bufptr || !*wps_bufptr)
         return false;
 
-    int subline;
-    data->num_tokens = 0;
     char *current_string = data->string_buffer;
 
-    while(wps_bufptr && *wps_bufptr && data->num_tokens < WPS_MAX_TOKENS
-          && data->num_lines < WPS_MAX_LINES)
+    while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1
+            && data->num_lines < WPS_MAX_LINES)
     {
         switch(*wps_bufptr++)
         {
@@ -630,12 +683,8 @@
 
             /* Alternating sublines separator */
             case ';':
-                if (data->num_sublines[data->num_lines]+1 < WPS_MAX_SUBLINES)
-                {
-                    data->tokens[data->num_tokens++].type = WPS_TOKEN_SUBLINE_SEPARATOR;
-                    subline = ++(data->num_sublines[data->num_lines]);
-                    data->format_lines[data->num_lines][subline] = data->num_tokens;
-                }
+                if (data->num_sublines+1 < WPS_MAX_SUBLINES)
+                    wps_start_new_subline(data);
                 else
                     wps_bufptr += skip_end_of_line(wps_bufptr);
 
@@ -694,13 +743,14 @@
                     goto condlistend;
                     break;
                 }
-                data->tokens[data->num_tokens++].type = WPS_TOKEN_EOL;
-                (data->num_sublines[data->num_lines])++;
-                data->num_lines++;
+                wps_start_new_subline(data);
+                data->num_lines++; /* Start a new line */
 
-                if (data->num_lines < WPS_MAX_LINES)
+                if ((data->num_lines < WPS_MAX_LINES) &&
+                    (data->num_sublines < WPS_MAX_SUBLINES))
                 {
-                    data->format_lines[data->num_lines][0] = data->num_tokens;
+                    data->lines[data->num_lines].first_subline_idx = data->num_sublines;
+                    data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
                 }
 
                 break;
@@ -777,8 +827,7 @@
     wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */
     wps_data->peak_meter_enabled = false;
 #else /* HAVE_LCD_CHARCELLS */
-    int i;
-    for(i = 0; i < 8; i++)
+    for (i = 0; i < 8; i++)
     {
         wps_data->wps_progress_pat[i] = 0;
     }
