1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h
index 704a785..5fa094a 100644
--- a/apps/gui/skin_engine/skin_engine.h
+++ b/apps/gui/skin_engine/skin_engine.h
@@ -44,7 +44,7 @@ bool skin_update(struct gui_wps *gwps, unsigned int update_type);
  */
 bool skin_data_load(struct wps_data *wps_data,
                     const char *buf,
-                    bool isfile);
+                    unsigned flags);


 /* initial setup of wps_data */
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 434e7c9..86c579d 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -86,6 +86,13 @@ static struct skin_viewport *curr_vp;
 /* the current line, linked to the above viewport */
 static struct skin_line *curr_line;

+#define RETURN_IF_CURR_VP_HIDDEN do { \
+                if ((curr_vp->hidden_flags & VP_NEVER_VISIBLE) && !(token->used_conditionally)) \
+                { \
+                    return WPS_ERROR_INVALID_PARAM; \
+                }\
+                } while (0)
+
 #ifdef HAVE_LCD_BITMAP

 #if LCD_DEPTH > 1
@@ -542,6 +549,7 @@ static int parse_image_display(const char *wps_bufptr,
 	struct gui_img *img;;

     /* sanity check */
+    RETURN_IF_CURR_VP_HIDDEN;
     img = find_image(label, wps_data);
     if (!img)
     {
@@ -776,6 +784,7 @@ static int parse_setting_and_lang(const char *wps_bufptr,
     int i = 0;
     char temp[64];

+    RETURN_IF_CURR_VP_HIDDEN;
     /* Find the setting's cfg_name */
     if (*ptr != '|')
         return WPS_ERROR_INVALID_PARAM;
@@ -898,6 +907,7 @@ static int parse_progressbar(const char *wps_bufptr,
     struct progressbar *pb = skin_buffer_alloc(sizeof(struct progressbar));
     struct skin_token_list *item = new_skin_token_list_item(token, pb);

+    RETURN_IF_CURR_VP_HIDDEN;
 	if (!pb || !item)
 	    return WPS_ERROR_INVALID_PARAM;

@@ -1157,13 +1167,13 @@ static int parse_albumart_display(const char *wps_bufptr,
                                       struct wps_data *wps_data)
 {
     (void)wps_bufptr;
-    struct wps_token *prev = token-1;
-    if ((wps_data->num_tokens >= 1) && (prev->type == WPS_TOKEN_CONDITIONAL))
+    if ((wps_data->num_tokens >= 1) && token->used_conditionally)
     {
         token->type = WPS_TOKEN_ALBUMART_FOUND;
     }
     else if (wps_data->albumart)
     {
+        RETURN_IF_CURR_VP_HIDDEN;
         wps_data->albumart->vp = &curr_vp->vp;
     }
 #if 0
@@ -1287,11 +1297,15 @@ static int parse_touchregion(const char *wps_bufptr,
 /* Parse a generic token from the given string. Return the length read */
 static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
 {
+    static int prev_was_cond = 0;
     int skip = 0, taglen = 0, ret;
     struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
     const struct wps_tag *tag;
     memset(token, 0, sizeof(*token));

+    if (prev_was_cond)
+        token->used_conditionally = true;
+
     switch(*wps_bufptr)
     {

@@ -1311,6 +1325,7 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
         case '?':
             /* conditional tag */
             token->type = WPS_TOKEN_CONDITIONAL;
+            prev_was_cond = 1;
             level++;
             condindex[level] = wps_data->num_tokens;
             numoptions[level] = 1;
@@ -1322,6 +1337,8 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)

         default:
             /* find what tag we have */
+            prev_was_cond = 0;
+            RETURN_IF_CURR_VP_HIDDEN;
             for (tag = all_tags;
                  strncmp(wps_bufptr, tag->name, strlen(tag->name)) != 0;
                  tag++) ;
@@ -1740,11 +1757,12 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
    from a (wps-)file (isfile = true)*/
 bool skin_data_load(struct wps_data *wps_data,
                    const char *buf,
-                   bool isfile)
+                   unsigned flags)
 {

     if (!wps_data || !buf)
         return false;
+    int isfile = flags & SKIN_IS_FILE;
 #ifdef HAVE_ALBUMART
     int status;
     struct mp3entry *curtrack;
@@ -1775,6 +1793,10 @@ bool skin_data_load(struct wps_data *wps_data,
     curr_vp->pb            = NULL;
     curr_vp->hidden_flags  = 0;
     curr_vp->lines         = NULL;
+    if (flags & SKIN_HIDE_DEFAULT_VP)
+    {
+        curr_vp->hidden_flags |= VP_NEVER_VISIBLE;
+    }

     curr_line = NULL;
     if (!skin_start_new_line(curr_vp, 0))
diff --git a/apps/gui/skin_engine/skin_tokens.h b/apps/gui/skin_engine/skin_tokens.h
index 6d78355..0a8eb50 100644
--- a/apps/gui/skin_engine/skin_tokens.h
+++ b/apps/gui/skin_engine/skin_tokens.h
@@ -201,6 +201,7 @@ struct wps_token {
     /* Whether the tag (e.g. track name or the album) refers the
        current or the next song (false=current, true=next) */
     bool next;
+    bool used_conditionally;

     union {
         char c;
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index 1fd6864..3048adf 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -73,6 +73,10 @@

 #endif /* HAVE_ALBUMART */

+/* flags for setting up a skin */
+#define SKIN_IS_FILE            (1<<0)
+#define SKIN_HIDE_DEFAULT_VP    (1<<1)
+
 /* wps_data*/

 #ifdef HAVE_LCD_BITMAP
@@ -147,6 +151,7 @@ enum wps_parse_error {
     PARSE_OK,
     PARSE_FAIL_UNCLOSED_COND,
     PARSE_FAIL_INVALID_CHAR,
+    PARSE_FAIL_INVALID_VIEWPORT,
     PARSE_FAIL_COND_SYNTAX_ERROR,
     PARSE_FAIL_COND_INVALID_PARAM,
     PARSE_FAIL_LIMITS_EXCEEDED,
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index 9756401..fcf7dac 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -49,9 +49,10 @@ static int update_delay = DEFAULT_UPDATE_DELAY;
 void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile)
 {
     struct wps_data *data = sb_skin[screen].data;
-
+    unsigned flags = isfile ? SKIN_IS_FILE:0;
     int success;
-    success = buf && skin_data_load(data, buf, isfile);
+    
+    success = buf && skin_data_load(data, buf, flags|SKIN_HIDE_DEFAULT_VP);

     if (success)
     {  /* hide the sb's default viewport because it has nasty effect with stuff
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 8d1a0b9..9b849e7 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -104,6 +104,7 @@ static void statusbar_toggle_handler(void *data);
 void wps_data_load(enum screen_type screen, const char *buf, bool isfile)
 {
     bool loaded_ok;
+    unsigned flags = isfile ? SKIN_IS_FILE : 0;

     screens[screen].backdrop_unload(BACKDROP_SKIN_WPS);

@@ -127,7 +128,7 @@ void wps_data_load(enum screen_type screen, const char *buf, bool isfile)

 #endif /* __PCTOOL__ */

-    loaded_ok = buf && skin_data_load(gui_wps[screen].data, buf, isfile);
+    loaded_ok = buf && skin_data_load(gui_wps[screen].data, buf, flags);

     if (!loaded_ok) /* load the hardcoded default */
     {