summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-07-29 12:37:48 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-07-29 12:37:48 +0000
commit2d31d77a8ba231cb03ec35863c4c4ce2024f6509 (patch)
treeb85ca1bede3e83695619064ee9a323f0a8da1865 /lib
parente436483b66a931fef6436e9cd3e69eb2b3ff1f7b (diff)
downloadrockbox-2d31d77a8ba231cb03ec35863c4c4ce2024f6509.tar.gz
rockbox-2d31d77a8ba231cb03ec35863c4c4ce2024f6509.zip
FS#11470 - new skin code, finally svn uses the new parser from the theme editor. This means that a skin that passes the editor WILL pass svn and checkwps (unless the target runs out of skin buffer or something.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27613 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'lib')
-rw-r--r--lib/skin_parser/SOURCES2
-rw-r--r--lib/skin_parser/skin_buffer.c38
-rw-r--r--lib/skin_parser/skin_buffer.h6
-rw-r--r--lib/skin_parser/skin_debug.c40
-rw-r--r--lib/skin_parser/skin_debug.h9
-rw-r--r--lib/skin_parser/skin_parser.c169
-rw-r--r--lib/skin_parser/skin_parser.h15
-rw-r--r--lib/skin_parser/skin_scan.c8
-rw-r--r--lib/skin_parser/skin_scan.h1
-rw-r--r--lib/skin_parser/tag_table.c325
-rw-r--r--lib/skin_parser/tag_table.h21
11 files changed, 434 insertions, 200 deletions
diff --git a/lib/skin_parser/SOURCES b/lib/skin_parser/SOURCES
index 3024797255..37a6e9a03c 100644
--- a/lib/skin_parser/SOURCES
+++ b/lib/skin_parser/SOURCES
@@ -1,6 +1,6 @@
1skin_buffer.c 1skin_buffer.c
2skin_parser.c 2skin_parser.c
3#ifndef ROCKBOX 3#if !defined(ROCKBOX) || defined(__PCTOOL__)
4skin_debug.c 4skin_debug.c
5#endif 5#endif
6skin_scan.c 6skin_scan.c
diff --git a/lib/skin_parser/skin_buffer.c b/lib/skin_parser/skin_buffer.c
index 05cdc0ce03..69d9d273bd 100644
--- a/lib/skin_parser/skin_buffer.c
+++ b/lib/skin_parser/skin_buffer.c
@@ -24,21 +24,19 @@
24#include <string.h> 24#include <string.h>
25#include <stdlib.h> 25#include <stdlib.h>
26 26
27#include "skin_buffer.h"
28
27#ifdef ROCKBOX 29#ifdef ROCKBOX
28#define SKIN_BUFFER_SIZE (400*1024) /* Excessivly large for now */ 30static size_t buf_size;
29static unsigned char buffer[SKIN_BUFFER_SIZE]; 31static unsigned char *buffer_start = NULL;
30static unsigned char *buffer_front = NULL; /* start of the free space, 32static unsigned char *buffer_front = NULL;
31 increases with allocation*/
32#endif 33#endif
33 34
34void skin_buffer_init(void) 35void skin_buffer_init(char* buffer, size_t size)
35{ 36{
36#if defined(ROCKBOX) 37#if defined(ROCKBOX)
37 { 38 buffer_start = buffer_front = buffer;
38 /* reset the buffer.... */ 39 buf_size = size;
39 buffer_front = buffer;
40 //TODO: buf_size = size;
41 }
42#endif 40#endif
43} 41}
44 42
@@ -46,7 +44,9 @@ void skin_buffer_init(void)
46void* skin_buffer_alloc(size_t size) 44void* skin_buffer_alloc(size_t size)
47{ 45{
48 void *retval = NULL; 46 void *retval = NULL;
49#ifdef ROCKBOX 47#ifdef ROCKBOX
48 if (size > skin_buffer_freespace())
49 return NULL;
50 retval = buffer_front; 50 retval = buffer_front;
51 buffer_front += size; 51 buffer_front += size;
52 /* 32-bit aligned */ 52 /* 32-bit aligned */
@@ -62,10 +62,22 @@ void* skin_buffer_alloc(size_t size)
62/* get the number of bytes currently being used */ 62/* get the number of bytes currently being used */
63size_t skin_buffer_usage(void) 63size_t skin_buffer_usage(void)
64{ 64{
65 return buffer_front - buffer; 65 return buffer_front - buffer_start;
66} 66}
67size_t skin_buffer_freespace(void) 67size_t skin_buffer_freespace(void)
68{ 68{
69 return SKIN_BUFFER_SIZE - skin_buffer_usage(); 69 return buf_size - skin_buffer_usage();
70}
71
72static unsigned char *saved_buffer_pos = NULL;
73void skin_buffer_save_position(void)
74{
75 saved_buffer_pos = buffer_front;
76}
77
78void skin_buffer_restore_position(void)
79{
80 if (saved_buffer_pos)
81 buffer_front = saved_buffer_pos;
70} 82}
71#endif 83#endif
diff --git a/lib/skin_parser/skin_buffer.h b/lib/skin_parser/skin_buffer.h
index ff477da539..1698b8afb2 100644
--- a/lib/skin_parser/skin_buffer.h
+++ b/lib/skin_parser/skin_buffer.h
@@ -25,11 +25,15 @@
25#include <stdlib.h> 25#include <stdlib.h>
26#ifndef _SKIN_BUFFFER_H_ 26#ifndef _SKIN_BUFFFER_H_
27#define _SKIN_BUFFFER_H_ 27#define _SKIN_BUFFFER_H_
28void skin_buffer_init(size_t size); 28void skin_buffer_init(char* buffer, size_t size);
29/* Allocate size bytes from the buffer */ 29/* Allocate size bytes from the buffer */
30void* skin_buffer_alloc(size_t size); 30void* skin_buffer_alloc(size_t size);
31 31
32/* get the number of bytes currently being used */ 32/* get the number of bytes currently being used */
33size_t skin_buffer_usage(void); 33size_t skin_buffer_usage(void);
34size_t skin_buffer_freespace(void); 34size_t skin_buffer_freespace(void);
35
36/* save and restore a buffer position incase a skin fails to load */
37void skin_buffer_save_position(void);
38void skin_buffer_restore_position(void);
35#endif 39#endif
diff --git a/lib/skin_parser/skin_debug.c b/lib/skin_parser/skin_debug.c
index c03b32e910..88ad209cce 100644
--- a/lib/skin_parser/skin_debug.c
+++ b/lib/skin_parser/skin_debug.c
@@ -35,6 +35,7 @@ extern char* skin_start;
35/* Global error variables */ 35/* Global error variables */
36int error_line; 36int error_line;
37int error_col; 37int error_col;
38char *error_line_start;
38char* error_message; 39char* error_message;
39 40
40/* Debugging functions */ 41/* Debugging functions */
@@ -48,6 +49,7 @@ void skin_error(enum skin_errorcode error, char* cursor)
48 cursor--; 49 cursor--;
49 error_col++; 50 error_col++;
50 } 51 }
52 error_line_start = cursor+1;
51 53
52 error_line = skin_line; 54 error_line = skin_line;
53 55
@@ -285,4 +287,42 @@ void skin_debug_indent()
285 for(i = 0; i < debug_indent_level; i++) 287 for(i = 0; i < debug_indent_level; i++)
286 printf(" "); 288 printf(" ");
287} 289}
290
288#endif 291#endif
292
293#define MIN(a,b) ((a<b)?(a):(b))
294void skin_error_format_message()
295{
296 int i;
297 char text[128];
298 char* line_end = strchr(error_line_start, '\n');
299 int len = MIN(line_end - error_line_start, 80);
300 if (!line_end)
301 len = strlen(error_line_start);
302 printf("Error on line %d.\n", error_line);
303 error_col--;
304 if (error_col <= 10)
305 {
306 strncpy(text, error_line_start, len);
307 text[len] = '\0';
308 }
309 else
310 {
311 int j;
312 /* make it fit nicely.. "<start few chars>...<10 chars><error>" */
313 strncpy(text, error_line_start, 6);
314 i = 5;
315 text[i++] = '.';
316 text[i++] = '.';
317 text[i++] = '.';
318 for (j=error_col-10; error_line_start[j] && error_line_start[j] != '\n'; j++)
319 text[i++] = error_line_start[j];
320 text[i] = '\0';
321 error_col = 18;
322 }
323 printf("%s\n", text);
324 for (i=0; i<error_col; i++)
325 text[i] = ' ';
326 snprintf(&text[i],64, "^ \'%s\' Here", error_message);
327 printf("%s\n", text);
328}
diff --git a/lib/skin_parser/skin_debug.h b/lib/skin_parser/skin_debug.h
index fbff5cbb4c..c3538083d2 100644
--- a/lib/skin_parser/skin_debug.h
+++ b/lib/skin_parser/skin_debug.h
@@ -28,8 +28,12 @@ extern "C"
28{ 28{
29#endif 29#endif
30 30
31#if !defined(ROCKBOX) || defined(__PCTOOL__)
32#define SKINPARSER_DEBUG
33#endif
34
31#include "skin_parser.h" 35#include "skin_parser.h"
32#ifndef ROCKBOX 36#ifdef SKINPARSER_DEBUG
33/* Debugging functions */ 37/* Debugging functions */
34void skin_error(enum skin_errorcode error, char* cursor); 38void skin_error(enum skin_errorcode error, char* cursor);
35int skin_error_line(void); 39int skin_error_line(void);
@@ -37,6 +41,7 @@ int skin_error_col(void);
37char* skin_error_message(void); 41char* skin_error_message(void);
38void skin_clear_errors(void); 42void skin_clear_errors(void);
39void skin_debug_tree(struct skin_element* root); 43void skin_debug_tree(struct skin_element* root);
44void skin_error_format_message();
40 45
41/* Auxiliary debug functions */ 46/* Auxiliary debug functions */
42void skin_debug_params(int count, struct skin_tag_parameter params[]); 47void skin_debug_params(int count, struct skin_tag_parameter params[]);
@@ -46,7 +51,7 @@ void skin_debug_indent(void);
46#define skin_error(...) 51#define skin_error(...)
47#define skin_clear_errors() 52#define skin_clear_errors()
48 53
49#endif /* !ROCKBOX */ 54#endif /* SKINPARSER_DEBUG */
50 55
51 56
52#ifdef __cplusplus 57#ifdef __cplusplus
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c
index 3e23067258..13c7b55e5e 100644
--- a/lib/skin_parser/skin_parser.c
+++ b/lib/skin_parser/skin_parser.c
@@ -21,6 +21,7 @@
21 21
22#include <stdlib.h> 22#include <stdlib.h>
23#include <stdio.h> 23#include <stdio.h>
24#include <stdbool.h>
24#include <string.h> 25#include <string.h>
25#include <ctype.h> 26#include <ctype.h>
26#include <stdbool.h> 27#include <stdbool.h>
@@ -37,6 +38,11 @@ int skin_line = 0;
37char* skin_start = 0; 38char* skin_start = 0;
38int viewport_line = 0; 39int viewport_line = 0;
39 40
41#ifdef ROCKBOX
42static skin_callback callback = NULL;
43static void* callback_data;
44#endif
45
40/* Auxiliary parsing functions (not visible at global scope) */ 46/* Auxiliary parsing functions (not visible at global scope) */
41static struct skin_element* skin_parse_viewport(char** document); 47static struct skin_element* skin_parse_viewport(char** document);
42static struct skin_element* skin_parse_line(char** document); 48static struct skin_element* skin_parse_line(char** document);
@@ -55,10 +61,23 @@ static int skin_parse_comment(struct skin_element* element, char** document);
55static struct skin_element* skin_parse_code_as_arg(char** document); 61static struct skin_element* skin_parse_code_as_arg(char** document);
56 62
57 63
64static void skip_whitespace(char** document)
65{
66 while(**document == ' ' || **document == '\t')
67 (*document)++;
68}
58 69
70#ifdef ROCKBOX
71struct skin_element* skin_parse(const char* document,
72 skin_callback cb, void* cb_data)
73
74{
75 callback = cb;
76 callback_data = cb_data;
77#else
59struct skin_element* skin_parse(const char* document) 78struct skin_element* skin_parse(const char* document)
60{ 79{
61 80#endif
62 struct skin_element* root = NULL; 81 struct skin_element* root = NULL;
63 struct skin_element* last = NULL; 82 struct skin_element* last = NULL;
64 83
@@ -94,7 +113,6 @@ struct skin_element* skin_parse(const char* document)
94 last = last->next; 113 last = last->next;
95 114
96 } 115 }
97
98 return root; 116 return root;
99 117
100} 118}
@@ -107,6 +125,8 @@ static struct skin_element* skin_parse_viewport(char** document)
107 struct skin_element* retval = NULL; 125 struct skin_element* retval = NULL;
108 126
109 retval = skin_alloc_element(); 127 retval = skin_alloc_element();
128 if (!retval)
129 return NULL;
110 retval->type = VIEWPORT; 130 retval->type = VIEWPORT;
111 retval->children_count = 1; 131 retval->children_count = 1;
112 retval->line = skin_line; 132 retval->line = skin_line;
@@ -129,11 +149,18 @@ static struct skin_element* skin_parse_viewport(char** document)
129 skin_line++; 149 skin_line++;
130 } 150 }
131 } 151 }
152#ifdef ROCKBOX
153 else if (callback)
154 {
155 if (callback(retval, callback_data) == CALLBACK_ERROR)
156 return NULL;
157 }
158#endif
132 159
133 retval->children_count = 1; 160 retval->children_count = 1;
134 retval->children = skin_alloc_children(1); 161 retval->children = skin_alloc_children(1);
135 162 if (!retval->children)
136 163 return NULL;
137 do 164 do
138 { 165 {
139 166
@@ -199,7 +226,6 @@ static struct skin_element* skin_parse_viewport(char** document)
199 return NULL; 226 return NULL;
200 227
201 } 228 }
202
203 /* Making sure last is at the end */ 229 /* Making sure last is at the end */
204 while(last->next) 230 while(last->next)
205 last = last->next; 231 last = last->next;
@@ -245,6 +271,8 @@ static struct skin_element* skin_parse_line_optional(char** document,
245 271
246 /* A wrapper for the line */ 272 /* A wrapper for the line */
247 retval = skin_alloc_element(); 273 retval = skin_alloc_element();
274 if (!retval)
275 return NULL;
248 retval->type = LINE; 276 retval->type = LINE;
249 retval->line = skin_line; 277 retval->line = skin_line;
250 if(*cursor != '\0' && *cursor != '\n' && *cursor != MULTILINESYM 278 if(*cursor != '\0' && *cursor != '\n' && *cursor != MULTILINESYM
@@ -261,7 +289,24 @@ static struct skin_element* skin_parse_line_optional(char** document,
261 } 289 }
262 290
263 if(retval->children_count > 0) 291 if(retval->children_count > 0)
292 {
264 retval->children = skin_alloc_children(1); 293 retval->children = skin_alloc_children(1);
294 if (!retval->children)
295 return NULL;
296 }
297
298#ifdef ROCKBOX
299 if (callback)
300 {
301 switch (callback(retval, callback_data))
302 {
303 case CALLBACK_ERROR:
304 return NULL;
305 default:
306 break;
307 }
308 }
309#endif
265 310
266 while(*cursor != '\n' && *cursor != '\0' && *cursor != MULTILINESYM 311 while(*cursor != '\n' && *cursor != '\0' && *cursor != MULTILINESYM
267 && !((*cursor == ARGLISTSEPERATESYM 312 && !((*cursor == ARGLISTSEPERATESYM
@@ -275,11 +320,15 @@ static struct skin_element* skin_parse_line_optional(char** document,
275 if(root) 320 if(root)
276 { 321 {
277 current->next = skin_alloc_element(); 322 current->next = skin_alloc_element();
323 if (!current->next)
324 return NULL;
278 current = current->next; 325 current = current->next;
279 } 326 }
280 else 327 else
281 { 328 {
282 current = skin_alloc_element(); 329 current = skin_alloc_element();
330 if (!current)
331 return NULL;
283 root = current; 332 root = current;
284 } 333 }
285 334
@@ -306,9 +355,10 @@ static struct skin_element* skin_parse_line_optional(char** document,
306 } 355 }
307 } 356 }
308 357
358
309 /* Moving up the calling function's pointer */ 359 /* Moving up the calling function's pointer */
310 *document = cursor; 360 *document = cursor;
311 361
312 if(root) 362 if(root)
313 retval->children[0] = root; 363 retval->children[0] = root;
314 return retval; 364 return retval;
@@ -328,6 +378,8 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
328 int i; 378 int i;
329 379
330 retval = skin_alloc_element(); 380 retval = skin_alloc_element();
381 if (!retval)
382 return NULL;
331 retval->type = LINE_ALTERNATOR; 383 retval->type = LINE_ALTERNATOR;
332 retval->next = NULL; 384 retval->next = NULL;
333 retval->line = skin_line; 385 retval->line = skin_line;
@@ -374,6 +426,8 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
374 /* ...and then we parse them */ 426 /* ...and then we parse them */
375 retval->children_count = sublines; 427 retval->children_count = sublines;
376 retval->children = skin_alloc_children(sublines); 428 retval->children = skin_alloc_children(sublines);
429 if (!retval->children)
430 return NULL;
377 431
378 cursor = *document; 432 cursor = *document;
379 for(i = 0; i < sublines; i++) 433 for(i = 0; i < sublines; i++)
@@ -392,6 +446,13 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
392 } 446 }
393 } 447 }
394 448
449#ifdef ROCKBOX
450 if (callback)
451 {
452 if (callback(retval, callback_data) == CALLBACK_ERROR)
453 return NULL;
454 }
455#endif
395 *document = cursor; 456 *document = cursor;
396 457
397 return retval; 458 return retval;
@@ -458,6 +519,14 @@ static int skin_parse_tag(struct skin_element* element, char** document)
458 || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) 519 || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM)
459 || (star && *cursor != ARGLISTOPENSYM)) 520 || (star && *cursor != ARGLISTOPENSYM))
460 { 521 {
522
523#ifdef ROCKBOX
524 if (callback)
525 {
526 if (callback(element, callback_data) == CALLBACK_ERROR)
527 return 0;
528 }
529#endif
461 *document = cursor; 530 *document = cursor;
462 return 1; 531 return 1;
463 } 532 }
@@ -507,6 +576,8 @@ static int skin_parse_tag(struct skin_element* element, char** document)
507 cursor = bookmark; /* Restoring the cursor */ 576 cursor = bookmark; /* Restoring the cursor */
508 element->params_count = num_args; 577 element->params_count = num_args;
509 element->params = skin_alloc_params(num_args); 578 element->params = skin_alloc_params(num_args);
579 if (!element->params)
580 return 0;
510 581
511 /* Now we have to actually parse each argument */ 582 /* Now we have to actually parse each argument */
512 for(i = 0; i < num_args; i++) 583 for(i = 0; i < num_args; i++)
@@ -587,7 +658,6 @@ static int skin_parse_tag(struct skin_element* element, char** document)
587 } 658 }
588 if (have_tenth == false) 659 if (have_tenth == false)
589 val *= 10; 660 val *= 10;
590
591 element->params[i].type = DECIMAL; 661 element->params[i].type = DECIMAL;
592 element->params[i].data.number = val; 662 element->params[i].data.number = val;
593 } 663 }
@@ -644,7 +714,13 @@ static int skin_parse_tag(struct skin_element* element, char** document)
644 skin_error(INSUFFICIENT_ARGS, cursor); 714 skin_error(INSUFFICIENT_ARGS, cursor);
645 return 0; 715 return 0;
646 } 716 }
647 717#ifdef ROCKBOX
718 if (callback)
719 {
720 if (callback(element, callback_data) == CALLBACK_ERROR)
721 return 0;
722 }
723#endif
648 *document = cursor; 724 *document = cursor;
649 725
650 return 1; 726 return 1;
@@ -691,6 +767,8 @@ static int skin_parse_text(struct skin_element* element, char** document,
691 element->line = skin_line; 767 element->line = skin_line;
692 element->next = NULL; 768 element->next = NULL;
693 element->data = text = skin_alloc_string(length); 769 element->data = text = skin_alloc_string(length);
770 if (!element->data)
771 return 0;
694 772
695 for(dest = 0; dest < length; dest++) 773 for(dest = 0; dest < length; dest++)
696 { 774 {
@@ -702,6 +780,14 @@ static int skin_parse_text(struct skin_element* element, char** document,
702 cursor++; 780 cursor++;
703 } 781 }
704 text[length] = '\0'; 782 text[length] = '\0';
783
784#ifdef ROCKBOX
785 if (callback)
786 {
787 if (callback(element, callback_data) == CALLBACK_ERROR)
788 return 0;
789 }
790#endif
705 791
706 *document = cursor; 792 *document = cursor;
707 793
@@ -715,14 +801,40 @@ static int skin_parse_conditional(struct skin_element* element, char** document)
715 char* bookmark; 801 char* bookmark;
716 int children = 1; 802 int children = 1;
717 int i; 803 int i;
804
805#ifdef ROCKBOX
806 bool feature_available = true;
807 char *false_branch = NULL;
808#endif
718 809
719 element->type = CONDITIONAL; 810 /* Some conditional tags allow for target feature checking,
811 * so to handle that call the callback as usual with type == TAG
812 * then call it a second time with type == CONDITIONAL and check the return
813 * value */
814 element->type = TAG;
720 element->line = skin_line; 815 element->line = skin_line;
721 816
722 /* Parsing the tag first */ 817 /* Parsing the tag first */
723 if(!skin_parse_tag(element, &cursor)) 818 if(!skin_parse_tag(element, &cursor))
724 return 0; 819 return 0;
725 820
821 element->type = CONDITIONAL;
822#ifdef ROCKBOX
823 if (callback)
824 {
825 switch (callback(element, callback_data))
826 {
827 case FEATURE_NOT_AVAILABLE:
828 feature_available = false;
829 break;
830 case CALLBACK_ERROR:
831 return 0;
832 default:
833 break;
834 }
835 }
836#endif
837
726 /* Counting the children */ 838 /* Counting the children */
727 if(*(cursor++) != ENUMLISTOPENSYM) 839 if(*(cursor++) != ENUMLISTOPENSYM)
728 { 840 {
@@ -751,16 +863,35 @@ static int skin_parse_conditional(struct skin_element* element, char** document)
751 { 863 {
752 children++; 864 children++;
753 cursor++; 865 cursor++;
866#ifdef ROCKBOX
867 if (false_branch == NULL && !feature_available)
868 {
869 false_branch = cursor;
870 children--;
871 }
872#endif
754 } 873 }
755 else 874 else
756 { 875 {
757 cursor++; 876 cursor++;
758 } 877 }
759 } 878 }
879#ifdef ROCKBOX
880 if (*cursor == ENUMLISTCLOSESYM &&
881 false_branch == NULL && !feature_available)
882 {
883 false_branch = cursor+1;
884 children--;
885 }
886 /* if we are skipping the true branch fix that up */
887 cursor = false_branch ? false_branch : bookmark;
888#else
760 cursor = bookmark; 889 cursor = bookmark;
761 890#endif
762 /* Parsing the children */ 891 /* Parsing the children */
763 element->children = skin_alloc_children(children); 892 element->children = skin_alloc_children(children);
893 if (!element->children)
894 return 0;
764 element->children_count = children; 895 element->children_count = children;
765 896
766 for(i = 0; i < children; i++) 897 for(i = 0; i < children; i++)
@@ -809,6 +940,8 @@ static int skin_parse_comment(struct skin_element* element, char** document)
809 element->data = NULL; 940 element->data = NULL;
810#else 941#else
811 element->data = text = skin_alloc_string(length); 942 element->data = text = skin_alloc_string(length);
943 if (!element->data)
944 return 0;
812 /* We copy from one char past cursor to leave out the # */ 945 /* We copy from one char past cursor to leave out the # */
813 memcpy((void*)text, (void*)(cursor + 1), 946 memcpy((void*)text, (void*)(cursor + 1),
814 sizeof(char) * (length-1)); 947 sizeof(char) * (length-1));
@@ -877,6 +1010,8 @@ struct skin_element* skin_alloc_element()
877{ 1010{
878 struct skin_element* retval = (struct skin_element*) 1011 struct skin_element* retval = (struct skin_element*)
879 skin_buffer_alloc(sizeof(struct skin_element)); 1012 skin_buffer_alloc(sizeof(struct skin_element));
1013 if (!retval)
1014 return NULL;
880 retval->type = UNKNOWN; 1015 retval->type = UNKNOWN;
881 retval->next = NULL; 1016 retval->next = NULL;
882 retval->tag = NULL; 1017 retval->tag = NULL;
@@ -886,9 +1021,21 @@ struct skin_element* skin_alloc_element()
886 return retval; 1021 return retval;
887 1022
888} 1023}
889 1024/* On a ROCKBOX build we try to save space as much as possible
1025 * so if we can, use a shared param pool which should be more then large
1026 * enough for any tag. params should be used straight away by the callback
1027 * so this is safe.
1028 */
890struct skin_tag_parameter* skin_alloc_params(int count) 1029struct skin_tag_parameter* skin_alloc_params(int count)
891{ 1030{
1031#ifdef ROCKBOX
1032 static struct skin_tag_parameter params[MAX_TAG_PARAMS];
1033 if (count <= MAX_TAG_PARAMS)
1034 {
1035 memset(params, 0, sizeof(params));
1036 return params;
1037 }
1038#endif
892 size_t size = sizeof(struct skin_tag_parameter) * count; 1039 size_t size = sizeof(struct skin_tag_parameter) * count;
893 return (struct skin_tag_parameter*)skin_buffer_alloc(size); 1040 return (struct skin_tag_parameter*)skin_buffer_alloc(size);
894 1041
diff --git a/lib/skin_parser/skin_parser.h b/lib/skin_parser/skin_parser.h
index ad10f90125..8514dfdd0e 100644
--- a/lib/skin_parser/skin_parser.h
+++ b/lib/skin_parser/skin_parser.h
@@ -115,14 +115,27 @@ struct skin_element
115 struct skin_element* next; 115 struct skin_element* next;
116}; 116};
117 117
118enum skin_cb_returnvalue
119{
120 CALLBACK_ERROR = -666,
121 FEATURE_NOT_AVAILABLE,
122 CALLBACK_OK = 0,
123 /* > 0 reserved for future use */
124};
125typedef int (*skin_callback)(struct skin_element* element, void* data);
126
118/*********************************************************************** 127/***********************************************************************
119 ***** Functions ******************************************************* 128 ***** Functions *******************************************************
120 **********************************************************************/ 129 **********************************************************************/
121 130
122/* Parses a WPS document and returns a list of skin_element 131/* Parses a WPS document and returns a list of skin_element
123 structures. */ 132 structures. */
133#ifdef ROCKBOX
134struct skin_element* skin_parse(const char* document,
135 skin_callback callback, void* callback_data);
136#else
124struct skin_element* skin_parse(const char* document); 137struct skin_element* skin_parse(const char* document);
125 138#endif
126/* Memory management functions */ 139/* Memory management functions */
127struct skin_element* skin_alloc_element(void); 140struct skin_element* skin_alloc_element(void);
128struct skin_element** skin_alloc_children(int count); 141struct skin_element** skin_alloc_children(int count);
diff --git a/lib/skin_parser/skin_scan.c b/lib/skin_parser/skin_scan.c
index 6b5c189b9f..d18f2224b3 100644
--- a/lib/skin_parser/skin_scan.c
+++ b/lib/skin_parser/skin_scan.c
@@ -40,12 +40,6 @@ void skip_comment(char** document)
40 (*document)++; 40 (*document)++;
41} 41}
42 42
43void skip_whitespace(char** document)
44{
45 while(**document == ' ' || **document == '\t')
46 (*document)++;
47}
48
49void skip_arglist(char** document) 43void skip_arglist(char** document)
50{ 44{
51 if(**document == ARGLISTOPENSYM) 45 if(**document == ARGLISTOPENSYM)
@@ -132,6 +126,8 @@ char* scan_string(char** document)
132 /* Copying the string */ 126 /* Copying the string */
133 cursor = *document; 127 cursor = *document;
134 buffer = skin_alloc_string(length); 128 buffer = skin_alloc_string(length);
129 if (!buffer)
130 return NULL;
135 buffer[length] = '\0'; 131 buffer[length] = '\0';
136 for(i = 0; i < length; i++) 132 for(i = 0; i < length; i++)
137 { 133 {
diff --git a/lib/skin_parser/skin_scan.h b/lib/skin_parser/skin_scan.h
index b1d04a6e34..72d4475767 100644
--- a/lib/skin_parser/skin_scan.h
+++ b/lib/skin_parser/skin_scan.h
@@ -30,7 +30,6 @@ extern "C"
30 30
31/* Scanning functions */ 31/* Scanning functions */
32void skip_comment(char** document); 32void skip_comment(char** document);
33void skip_whitespace(char** document);
34void skip_arglist(char** document); 33void skip_arglist(char** document);
35void skip_enumlist(char** document); 34void skip_enumlist(char** document);
36char* scan_string(char** document); 35char* scan_string(char** document);
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
index dd8df63997..a7e3378d24 100644
--- a/lib/skin_parser/tag_table.c
+++ b/lib/skin_parser/tag_table.c
@@ -33,182 +33,181 @@ struct tag_info legal_tags[] =
33 { SKIN_TOKEN_ALIGN_RIGHT_RTL, "aR", "", 0 }, 33 { SKIN_TOKEN_ALIGN_RIGHT_RTL, "aR", "", 0 },
34 { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, 34 { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 },
35 35
36 { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, 0 }, 36 { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC },
37 { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", 0 }, 37 { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC },
38 { SKIN_TOKEN_BATTERY_TIME, "bt", "", 0 }, 38 { SKIN_TOKEN_BATTERY_TIME, "bt", "", SKIN_REFRESH_DYNAMIC },
39 { SKIN_TOKEN_BATTERY_SLEEPTIME, "bs", "", 0 }, 39 { SKIN_TOKEN_BATTERY_SLEEPTIME, "bs", "", SKIN_REFRESH_DYNAMIC },
40 { SKIN_TOKEN_BATTERY_CHARGING, "bc", "", 0 }, 40 { SKIN_TOKEN_BATTERY_CHARGING, "bc", "", SKIN_REFRESH_DYNAMIC },
41 { SKIN_TOKEN_BATTERY_CHARGER_CONNECTED, "bp", "", 0 }, 41 { SKIN_TOKEN_BATTERY_CHARGER_CONNECTED, "bp", "", SKIN_REFRESH_DYNAMIC },
42 { SKIN_TOKEN_USB_POWERED, "bu", "", 0 }, 42 { SKIN_TOKEN_USB_POWERED, "bu", "", SKIN_REFRESH_DYNAMIC },
43 43
44 44
45 { SKIN_TOKEN_RTC_PRESENT, "cc", "", 0 }, 45 { SKIN_TOKEN_RTC_PRESENT, "cc", "", SKIN_REFRESH_STATIC },
46 { SKIN_TOKEN_RTC_DAY_OF_MONTH, "cd", "", 0 }, 46 { SKIN_TOKEN_RTC_DAY_OF_MONTH, "cd", "", SKIN_RTC_REFRESH },
47 { SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, "ce", "", 0 }, 47 { SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, "ce", "", SKIN_RTC_REFRESH },
48 { SKIN_TOKEN_RTC_12HOUR_CFG, "cf", "", 0 }, 48 { SKIN_TOKEN_RTC_12HOUR_CFG, "cf", "", SKIN_RTC_REFRESH },
49 { SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", "", 0 }, 49 { SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", "", SKIN_RTC_REFRESH },
50 { SKIN_TOKEN_RTC_HOUR_24, "ck", "", 0 }, 50 { SKIN_TOKEN_RTC_HOUR_24, "ck", "", SKIN_RTC_REFRESH },
51 { SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", "", 0 }, 51 { SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", "", SKIN_RTC_REFRESH },
52 { SKIN_TOKEN_RTC_HOUR_12, "cl", "", 0 }, 52 { SKIN_TOKEN_RTC_HOUR_12, "cl", "", SKIN_RTC_REFRESH },
53 { SKIN_TOKEN_RTC_MONTH, "cm", "", 0 }, 53 { SKIN_TOKEN_RTC_MONTH, "cm", "", SKIN_RTC_REFRESH },
54 { SKIN_TOKEN_RTC_MINUTE, "cM", "", 0 }, 54 { SKIN_TOKEN_RTC_MINUTE, "cM", "", SKIN_RTC_REFRESH },
55 { SKIN_TOKEN_RTC_SECOND, "cS", "", 0 }, 55 { SKIN_TOKEN_RTC_SECOND, "cS", "", SKIN_RTC_REFRESH },
56 { SKIN_TOKEN_RTC_YEAR_2_DIGITS, "cy", "", 0 }, 56 { SKIN_TOKEN_RTC_YEAR_2_DIGITS, "cy", "", SKIN_RTC_REFRESH },
57 { SKIN_TOKEN_RTC_YEAR_4_DIGITS, "cY", "", 0 }, 57 { SKIN_TOKEN_RTC_YEAR_4_DIGITS, "cY", "", SKIN_RTC_REFRESH },
58 { SKIN_TOKEN_RTC_AM_PM_UPPER, "cP", "", 0 }, 58 { SKIN_TOKEN_RTC_AM_PM_UPPER, "cP", "", SKIN_RTC_REFRESH },
59 { SKIN_TOKEN_RTC_AM_PM_LOWER, "cp", "", 0 }, 59 { SKIN_TOKEN_RTC_AM_PM_LOWER, "cp", "", SKIN_RTC_REFRESH },
60 { SKIN_TOKEN_RTC_WEEKDAY_NAME, "ca", "", 0 }, 60 { SKIN_TOKEN_RTC_WEEKDAY_NAME, "ca", "", SKIN_RTC_REFRESH },
61 { SKIN_TOKEN_RTC_MONTH_NAME, "cb", "", 0 }, 61 { SKIN_TOKEN_RTC_MONTH_NAME, "cb", "", SKIN_RTC_REFRESH },
62 { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", "", 0 }, 62 { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", "", SKIN_RTC_REFRESH },
63 { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", "", 0 }, 63 { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", "", SKIN_RTC_REFRESH },
64 64
65 { SKIN_TOKEN_FILE_BITRATE, "fb", "", 0 }, 65 { SKIN_TOKEN_FILE_BITRATE, "fb", "", SKIN_REFRESH_STATIC },
66 { SKIN_TOKEN_FILE_CODEC, "fc", "", 0 }, 66 { SKIN_TOKEN_FILE_CODEC, "fc", "", SKIN_REFRESH_STATIC },
67 { SKIN_TOKEN_FILE_FREQUENCY, "ff", "", 0 }, 67 { SKIN_TOKEN_FILE_FREQUENCY, "ff", "", SKIN_REFRESH_STATIC },
68 { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "fk", "", 0 }, 68 { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "fk", "", SKIN_REFRESH_STATIC },
69 { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", "", 0 }, 69 { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", "", SKIN_REFRESH_STATIC },
70 { SKIN_TOKEN_FILE_NAME, "fn", "", 0 }, 70 { SKIN_TOKEN_FILE_NAME, "fn", "", SKIN_REFRESH_STATIC },
71 { SKIN_TOKEN_FILE_PATH, "fp", "", 0 }, 71 { SKIN_TOKEN_FILE_PATH, "fp", "", SKIN_REFRESH_STATIC },
72 { SKIN_TOKEN_FILE_SIZE, "fs", "", 0 }, 72 { SKIN_TOKEN_FILE_SIZE, "fs", "", SKIN_REFRESH_STATIC },
73 { SKIN_TOKEN_FILE_VBR, "fv", "", 0 }, 73 { SKIN_TOKEN_FILE_VBR, "fv", "", SKIN_REFRESH_STATIC },
74 { SKIN_TOKEN_FILE_DIRECTORY, "d" , "I", 0 }, 74 { SKIN_TOKEN_FILE_DIRECTORY, "d" , "I", SKIN_REFRESH_STATIC },
75 75
76 { SKIN_TOKEN_FILE_BITRATE, "Fb", "", 0 }, 76 { SKIN_TOKEN_FILE_BITRATE, "Fb", "", SKIN_REFRESH_STATIC },
77 { SKIN_TOKEN_FILE_CODEC, "Fc", "", 0 }, 77 { SKIN_TOKEN_FILE_CODEC, "Fc", "", SKIN_REFRESH_STATIC },
78 { SKIN_TOKEN_FILE_FREQUENCY, "Ff", "", 0 }, 78 { SKIN_TOKEN_FILE_FREQUENCY, "Ff", "", SKIN_REFRESH_STATIC },
79 { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "Fk", "", 0 }, 79 { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "Fk", "", SKIN_REFRESH_STATIC },
80 { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", "", 0 }, 80 { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", "", SKIN_REFRESH_STATIC },
81 { SKIN_TOKEN_FILE_NAME, "Fn", "", 0 }, 81 { SKIN_TOKEN_FILE_NAME, "Fn", "", SKIN_REFRESH_STATIC },
82 { SKIN_TOKEN_FILE_PATH, "Fp", "", 0 }, 82 { SKIN_TOKEN_FILE_PATH, "Fp", "", SKIN_REFRESH_STATIC },
83 { SKIN_TOKEN_FILE_SIZE, "Fs", "", 0 }, 83 { SKIN_TOKEN_FILE_SIZE, "Fs", "", SKIN_REFRESH_STATIC },
84 { SKIN_TOKEN_FILE_VBR, "Fv", "", 0 }, 84 { SKIN_TOKEN_FILE_VBR, "Fv", "", SKIN_REFRESH_STATIC },
85 { SKIN_TOKEN_FILE_DIRECTORY, "D" , "I", 0 }, 85 { SKIN_TOKEN_FILE_DIRECTORY, "D" , "I", SKIN_REFRESH_STATIC },
86 86
87 87
88 { SKIN_TOKEN_METADATA_ARTIST, "ia", "", 0 }, 88 { SKIN_TOKEN_METADATA_ARTIST, "ia", "", SKIN_REFRESH_STATIC },
89 { SKIN_TOKEN_METADATA_COMPOSER, "ic", "", 0 }, 89 { SKIN_TOKEN_METADATA_COMPOSER, "ic", "", SKIN_REFRESH_STATIC },
90 { SKIN_TOKEN_METADATA_ALBUM, "id", "", 0 }, 90 { SKIN_TOKEN_METADATA_ALBUM, "id", "", SKIN_REFRESH_STATIC },
91 { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "iA", "", 0 }, 91 { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "iA", "", SKIN_REFRESH_STATIC },
92 { SKIN_TOKEN_METADATA_GROUPING, "iG", "", 0 }, 92 { SKIN_TOKEN_METADATA_GROUPING, "iG", "", SKIN_REFRESH_STATIC },
93 { SKIN_TOKEN_METADATA_GENRE, "ig", "", 0 }, 93 { SKIN_TOKEN_METADATA_GENRE, "ig", "", SKIN_REFRESH_STATIC },
94 { SKIN_TOKEN_METADATA_DISC_NUMBER, "ik", "", 0 }, 94 { SKIN_TOKEN_METADATA_DISC_NUMBER, "ik", "", SKIN_REFRESH_STATIC },
95 { SKIN_TOKEN_METADATA_TRACK_NUMBER, "in", "", 0 }, 95 { SKIN_TOKEN_METADATA_TRACK_NUMBER, "in", "", SKIN_REFRESH_STATIC },
96 { SKIN_TOKEN_METADATA_TRACK_TITLE, "it", "", 0 }, 96 { SKIN_TOKEN_METADATA_TRACK_TITLE, "it", "", SKIN_REFRESH_STATIC },
97 { SKIN_TOKEN_METADATA_VERSION, "iv", "", 0 }, 97 { SKIN_TOKEN_METADATA_VERSION, "iv", "", SKIN_REFRESH_STATIC },
98 { SKIN_TOKEN_METADATA_YEAR, "iy", "", 0 }, 98 { SKIN_TOKEN_METADATA_YEAR, "iy", "", SKIN_REFRESH_STATIC },
99 { SKIN_TOKEN_METADATA_COMMENT, "iC", "", 0 }, 99 { SKIN_TOKEN_METADATA_COMMENT, "iC", "", SKIN_REFRESH_STATIC },
100 100
101 { SKIN_TOKEN_METADATA_ARTIST, "Ia", "", 0 }, 101 { SKIN_TOKEN_METADATA_ARTIST, "Ia", "", SKIN_REFRESH_STATIC },
102 { SKIN_TOKEN_METADATA_COMPOSER, "Ic", "", 0 }, 102 { SKIN_TOKEN_METADATA_COMPOSER, "Ic", "", SKIN_REFRESH_STATIC },
103 { SKIN_TOKEN_METADATA_ALBUM, "Id", "", 0 }, 103 { SKIN_TOKEN_METADATA_ALBUM, "Id", "", SKIN_REFRESH_STATIC },
104 { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "IA", "", 0 }, 104 { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "IA", "", SKIN_REFRESH_STATIC },
105 { SKIN_TOKEN_METADATA_GROUPING, "IG", "", 0 }, 105 { SKIN_TOKEN_METADATA_GROUPING, "IG", "", SKIN_REFRESH_STATIC },
106 { SKIN_TOKEN_METADATA_GENRE, "Ig", "", 0 }, 106 { SKIN_TOKEN_METADATA_GENRE, "Ig", "", SKIN_REFRESH_STATIC },
107 { SKIN_TOKEN_METADATA_DISC_NUMBER, "Ik", "", 0 }, 107 { SKIN_TOKEN_METADATA_DISC_NUMBER, "Ik", "", SKIN_REFRESH_STATIC },
108 { SKIN_TOKEN_METADATA_TRACK_NUMBER, "In", "", 0 }, 108 { SKIN_TOKEN_METADATA_TRACK_NUMBER, "In", "", SKIN_REFRESH_STATIC },
109 { SKIN_TOKEN_METADATA_TRACK_TITLE, "It", "", 0 }, 109 { SKIN_TOKEN_METADATA_TRACK_TITLE, "It", "", SKIN_REFRESH_STATIC },
110 { SKIN_TOKEN_METADATA_VERSION, "Iv", "", 0 }, 110 { SKIN_TOKEN_METADATA_VERSION, "Iv", "", SKIN_REFRESH_STATIC },
111 { SKIN_TOKEN_METADATA_YEAR, "Iy", "", 0 }, 111 { SKIN_TOKEN_METADATA_YEAR, "Iy", "", SKIN_REFRESH_STATIC },
112 { SKIN_TOKEN_METADATA_COMMENT, "IC", "", 0 }, 112 { SKIN_TOKEN_METADATA_COMMENT, "IC", "", SKIN_REFRESH_STATIC },
113 113
114 { SKIN_TOKEN_SOUND_PITCH, "Sp", "", 0 }, 114 { SKIN_TOKEN_SOUND_PITCH, "Sp", "", SKIN_REFRESH_DYNAMIC },
115 { SKIN_TOKEN_SOUND_SPEED, "Ss", "", 0 }, 115 { SKIN_TOKEN_SOUND_SPEED, "Ss", "", SKIN_REFRESH_DYNAMIC },
116 116
117 { SKIN_TOKEN_VLED_HDD, "lh", "", 0 }, 117 { SKIN_TOKEN_VLED_HDD, "lh", "", SKIN_REFRESH_DYNAMIC },
118 118
119 { SKIN_TOKEN_MAIN_HOLD, "mh", "", 0 }, 119 { SKIN_TOKEN_MAIN_HOLD, "mh", "", SKIN_REFRESH_DYNAMIC },
120 { SKIN_TOKEN_REMOTE_HOLD, "mr", "", 0 }, 120 { SKIN_TOKEN_REMOTE_HOLD, "mr", "", SKIN_REFRESH_DYNAMIC },
121 { SKIN_TOKEN_REPEAT_MODE, "mm", "", 0 }, 121 { SKIN_TOKEN_REPEAT_MODE, "mm", "", SKIN_REFRESH_DYNAMIC },
122 { SKIN_TOKEN_PLAYBACK_STATUS, "mp", "", 0 }, 122 { SKIN_TOKEN_PLAYBACK_STATUS, "mp", "", SKIN_REFRESH_DYNAMIC },
123 { SKIN_TOKEN_BUTTON_VOLUME, "mv", "|D", 0 }, 123 { SKIN_TOKEN_BUTTON_VOLUME, "mv", "|D", SKIN_REFRESH_DYNAMIC },
124 124
125 { SKIN_TOKEN_PEAKMETER, "pm", "", 0 }, 125 { SKIN_TOKEN_PEAKMETER, "pm", "", SKIN_REFRESH_PEAK_METER },
126 { SKIN_TOKEN_PLAYER_PROGRESSBAR, "pf", "", 0 }, 126 { SKIN_TOKEN_PLAYER_PROGRESSBAR, "pf", "", SKIN_REFRESH_DYNAMIC|SKIN_REFRESH_PLAYER_PROGRESS },
127 { SKIN_TOKEN_PROGRESSBAR, "pb" , BAR_PARAMS, 0 }, 127 { SKIN_TOKEN_PROGRESSBAR, "pb" , BAR_PARAMS, SKIN_REFRESH_PLAYER_PROGRESS },
128 { SKIN_TOKEN_VOLUME, "pv" , BAR_PARAMS, 0 }, 128 { SKIN_TOKEN_VOLUME, "pv" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC },
129 129 { SKIN_TOKEN_TRACK_ELAPSED_PERCENT, "px", "", SKIN_REFRESH_DYNAMIC },
130 { SKIN_TOKEN_TRACK_ELAPSED_PERCENT, "px", "", 0 }, 130 { SKIN_TOKEN_TRACK_TIME_ELAPSED, "pc", "", SKIN_REFRESH_DYNAMIC },
131 { SKIN_TOKEN_TRACK_TIME_ELAPSED, "pc", "", 0 }, 131 { SKIN_TOKEN_TRACK_TIME_REMAINING, "pr", "", SKIN_REFRESH_DYNAMIC },
132 { SKIN_TOKEN_TRACK_TIME_REMAINING, "pr", "", 0 }, 132 { SKIN_TOKEN_TRACK_LENGTH, "pt", "", SKIN_REFRESH_STATIC },
133 { SKIN_TOKEN_TRACK_LENGTH, "pt", "", 0 }, 133 { SKIN_TOKEN_TRACK_STARTING, "pS" , "|D", SKIN_REFRESH_DYNAMIC },
134 { SKIN_TOKEN_TRACK_STARTING, "pS" , "|D", 0 }, 134 { SKIN_TOKEN_TRACK_ENDING, "pE" , "|D", SKIN_REFRESH_DYNAMIC },
135 { SKIN_TOKEN_TRACK_ENDING, "pE" , "|D", 0 }, 135 { SKIN_TOKEN_PLAYLIST_POSITION, "pp", "", SKIN_REFRESH_STATIC },
136 { SKIN_TOKEN_PLAYLIST_POSITION, "pp", "", 0 }, 136 { SKIN_TOKEN_PLAYLIST_ENTRIES, "pe", "", SKIN_REFRESH_STATIC },
137 { SKIN_TOKEN_PLAYLIST_ENTRIES, "pe", "", 0 }, 137 { SKIN_TOKEN_PLAYLIST_NAME, "pn", "", SKIN_REFRESH_STATIC },
138 { SKIN_TOKEN_PLAYLIST_NAME, "pn", "", 0 }, 138 { SKIN_TOKEN_PLAYLIST_SHUFFLE, "ps", "", SKIN_REFRESH_DYNAMIC },
139 { SKIN_TOKEN_PLAYLIST_SHUFFLE, "ps", "", 0 }, 139
140 140 { SKIN_TOKEN_DATABASE_PLAYCOUNT, "rp", "", SKIN_REFRESH_DYNAMIC },
141 { SKIN_TOKEN_DATABASE_PLAYCOUNT, "rp", "", 0 }, 141 { SKIN_TOKEN_DATABASE_RATING, "rr", "", SKIN_REFRESH_DYNAMIC },
142 { SKIN_TOKEN_DATABASE_RATING, "rr", "", 0 }, 142 { SKIN_TOKEN_DATABASE_AUTOSCORE, "ra", "", SKIN_REFRESH_DYNAMIC },
143 { SKIN_TOKEN_DATABASE_AUTOSCORE, "ra", "", 0 }, 143
144 144 { SKIN_TOKEN_REPLAYGAIN, "rg", "", SKIN_REFRESH_STATIC },
145 { SKIN_TOKEN_REPLAYGAIN, "rg", "", 0 }, 145 { SKIN_TOKEN_CROSSFADE, "xf", "", SKIN_REFRESH_DYNAMIC },
146 { SKIN_TOKEN_CROSSFADE, "xf", "", 0 }, 146
147 147 { SKIN_TOKEN_HAVE_TUNER, "tp", "", SKIN_REFRESH_STATIC },
148 { SKIN_TOKEN_HAVE_TUNER, "tp", "", 0 }, 148 { SKIN_TOKEN_TUNER_TUNED, "tt", "", SKIN_REFRESH_DYNAMIC },
149 { SKIN_TOKEN_TUNER_TUNED, "tt", "", 0 }, 149 { SKIN_TOKEN_TUNER_SCANMODE, "tm", "", SKIN_REFRESH_DYNAMIC },
150 { SKIN_TOKEN_TUNER_SCANMODE, "tm", "", 0 }, 150 { SKIN_TOKEN_TUNER_STEREO, "ts", "", SKIN_REFRESH_DYNAMIC },
151 { SKIN_TOKEN_TUNER_STEREO, "ts", "", 0 }, 151 { SKIN_TOKEN_TUNER_MINFREQ, "ta", "", SKIN_REFRESH_STATIC },
152 { SKIN_TOKEN_TUNER_MINFREQ, "ta", "", 0 }, 152 { SKIN_TOKEN_TUNER_MAXFREQ, "tb", "", SKIN_REFRESH_STATIC },
153 { SKIN_TOKEN_TUNER_MAXFREQ, "tb", "", 0 }, 153 { SKIN_TOKEN_TUNER_CURFREQ, "tf", "", SKIN_REFRESH_DYNAMIC },
154 { SKIN_TOKEN_TUNER_CURFREQ, "tf", "", 0 }, 154 { SKIN_TOKEN_PRESET_ID, "Ti", "", SKIN_REFRESH_STATIC },
155 { SKIN_TOKEN_PRESET_ID, "Ti", "", 0 }, 155 { SKIN_TOKEN_PRESET_NAME, "Tn", "", SKIN_REFRESH_STATIC },
156 { SKIN_TOKEN_PRESET_NAME, "Tn", "", 0 }, 156 { SKIN_TOKEN_PRESET_FREQ, "Tf", "", SKIN_REFRESH_STATIC },
157 { SKIN_TOKEN_PRESET_FREQ, "Tf", "", 0 }, 157 { SKIN_TOKEN_PRESET_COUNT, "Tc", "", SKIN_REFRESH_STATIC },
158 { SKIN_TOKEN_PRESET_COUNT, "Tc", "", 0 }, 158 { SKIN_TOKEN_HAVE_RDS, "tx", "", SKIN_REFRESH_STATIC },
159 { SKIN_TOKEN_HAVE_RDS, "tx", "", 0 }, 159 { SKIN_TOKEN_RDS_NAME, "ty", "", SKIN_REFRESH_DYNAMIC },
160 { SKIN_TOKEN_RDS_NAME, "ty", "", 0 }, 160 { SKIN_TOKEN_RDS_TEXT, "tz", "", SKIN_REFRESH_DYNAMIC },
161 { SKIN_TOKEN_RDS_TEXT, "tz", "", 0 }, 161
162 162 { SKIN_TOKEN_SUBLINE_SCROLL, "s", "", SKIN_REFRESH_SCROLL },
163 { SKIN_TOKEN_SUBLINE_SCROLL, "s", "", 0 },
164 { SKIN_TOKEN_SUBLINE_TIMEOUT, "t" , "D", 0 }, 163 { SKIN_TOKEN_SUBLINE_TIMEOUT, "t" , "D", 0 },
164
165 { SKIN_TOKEN_ENABLE_THEME, "we", "", 0|NOBREAK },
166 { SKIN_TOKEN_DISABLE_THEME, "wd", "", 0|NOBREAK },
167 { SKIN_TOKEN_DRAW_INBUILTBAR, "wi", "", SKIN_REFRESH_STATIC|NOBREAK },
165 168
166 { SKIN_TOKEN_ENABLE_THEME, "we", "", NOBREAK }, 169 { SKIN_TOKEN_IMAGE_PRELOAD, "xl", "SFII|I", 0|NOBREAK },
167 { SKIN_TOKEN_DISABLE_THEME, "wd", "", NOBREAK },
168 { SKIN_TOKEN_DRAW_INBUILTBAR, "wi", "", NOBREAK },
169
170 { SKIN_TOKEN_IMAGE_PRELOAD, "xl", "SFII|I", NOBREAK },
171 { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S", 0 }, 170 { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S", 0 },
172 { SKIN_TOKEN_IMAGE_PRELOAD, "x", "SFII", NOBREAK }, 171 { SKIN_TOKEN_IMAGE_DISPLAY, "x", "SFII", 0|NOBREAK },
173 172
174 { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF", NOBREAK }, 173 { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF", 0|NOBREAK },
175 { SKIN_TOKEN_ALBUMART_LOAD, "Cl" , "IIII|ss", NOBREAK }, 174 { SKIN_TOKEN_ALBUMART_LOAD, "Cl" , "IIII|ss", 0|NOBREAK },
176 { SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", 0 }, 175 { SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", SKIN_REFRESH_STATIC },
177 { SKIN_TOKEN_ALBUMART_FOUND, "C" , "", 0 }, 176 { SKIN_TOKEN_ALBUMART_FOUND, "C" , "", SKIN_REFRESH_STATIC },
178 177
179 { SKIN_TOKEN_VIEWPORT_ENABLE, "Vd" , "S", 0 }, 178 { SKIN_TOKEN_VIEWPORT_ENABLE, "Vd" , "S", SKIN_REFRESH_STATIC },
180 { SKIN_TOKEN_UIVIEWPORT_ENABLE, "VI" , "S", 0 }, 179 { SKIN_TOKEN_UIVIEWPORT_ENABLE, "VI" , "S", SKIN_REFRESH_STATIC },
181 180
182 { SKIN_TOKEN_VIEWPORT_CUSTOMLIST, "Vp" , "ICC", NOBREAK }, 181 { SKIN_TOKEN_VIEWPORT_CUSTOMLIST, "Vp" , "ICC", SKIN_REFRESH_DYNAMIC|NOBREAK },
183 { SKIN_TOKEN_LIST_TITLE_TEXT, "Lt" , "", 0 }, 182 { SKIN_TOKEN_LIST_TITLE_TEXT, "Lt" , "", SKIN_REFRESH_DYNAMIC },
184 { SKIN_TOKEN_LIST_TITLE_ICON, "Li" , "", 0 }, 183 { SKIN_TOKEN_LIST_TITLE_ICON, "Li" , "", SKIN_REFRESH_DYNAMIC },
185 184
186 { SKIN_TOKEN_VIEWPORT_FGCOLOUR, "Vf" , "S", NOBREAK }, 185 { SKIN_TOKEN_VIEWPORT_FGCOLOUR, "Vf" , "s", SKIN_REFRESH_STATIC|NOBREAK },
187 { SKIN_TOKEN_VIEWPORT_BGCOLOUR, "Vb" , "S", NOBREAK }, 186 { SKIN_TOKEN_VIEWPORT_BGCOLOUR, "Vb" , "s", SKIN_REFRESH_STATIC|NOBREAK },
188 187
189 { SKIN_TOKEN_VIEWPORT_CONDITIONAL, "Vl" , "SIIiii", 0 }, 188 { SKIN_TOKEN_VIEWPORT_CONDITIONAL, "Vl" , "SIIiii", 0 },
190 { SKIN_TOKEN_UIVIEWPORT_LOAD, "Vi" , "sIIiii", 0 }, 189 { SKIN_TOKEN_UIVIEWPORT_LOAD, "Vi" , "sIIiii", 0 },
191 { SKIN_TOKEN_VIEWPORT_LOAD, "V" , "IIiii", 0 }, 190 { SKIN_TOKEN_VIEWPORT_LOAD, "V" , "IIiii", 0 },
192 191
193 { SKIN_TOKEN_IMAGE_BACKDROP, "X" , "f", NOBREAK }, 192 { SKIN_TOKEN_IMAGE_BACKDROP, "X" , "f", SKIN_REFRESH_STATIC|NOBREAK },
194 193
195 { SKIN_TOKEN_SETTING, "St" , "S", 0 }, 194 { SKIN_TOKEN_SETTING, "St" , "S", SKIN_REFRESH_DYNAMIC },
196 { SKIN_TOKEN_TRANSLATEDSTRING, "Sx" , "S", 0 }, 195 { SKIN_TOKEN_TRANSLATEDSTRING, "Sx" , "S", SKIN_REFRESH_STATIC },
197 { SKIN_TOKEN_LANG_IS_RTL, "Sr" , "", 0 }, 196 { SKIN_TOKEN_LANG_IS_RTL, "Sr" , "", SKIN_REFRESH_STATIC },
198 197
199 { SKIN_TOKEN_LASTTOUCH, "Tl" , "|D", 0 }, 198 { SKIN_TOKEN_LASTTOUCH, "Tl" , "|D", SKIN_REFRESH_DYNAMIC },
200 { SKIN_TOKEN_CURRENT_SCREEN, "cs", "", 0 }, 199 { SKIN_TOKEN_CURRENT_SCREEN, "cs", "", SKIN_REFRESH_DYNAMIC },
201 { SKIN_TOKEN_TOUCHREGION, "T" , "IIiiS", NOBREAK }, 200 { SKIN_TOKEN_TOUCHREGION, "T" , "IIiiS", 0|NOBREAK },
202 201
203 { SKIN_TOKEN_HAVE_RECORDING, "Rp" , "", 0 }, 202 { SKIN_TOKEN_HAVE_RECORDING, "Rp" , "", SKIN_REFRESH_STATIC },
204 { SKIN_TOKEN_IS_RECORDING, "Rr" , "", 0 }, 203 { SKIN_TOKEN_IS_RECORDING, "Rr" , "", SKIN_REFRESH_DYNAMIC },
205 { SKIN_TOKEN_REC_FREQ, "Rf" , "", 0 }, 204 { SKIN_TOKEN_REC_FREQ, "Rf" , "", SKIN_REFRESH_DYNAMIC },
206 { SKIN_TOKEN_REC_ENCODER, "Re" , "", 0 }, 205 { SKIN_TOKEN_REC_ENCODER, "Re" , "", SKIN_REFRESH_DYNAMIC },
207 { SKIN_TOKEN_REC_BITRATE, "Rb" , "", 0 }, 206 { SKIN_TOKEN_REC_BITRATE, "Rb" , "", SKIN_REFRESH_DYNAMIC },
208 { SKIN_TOKEN_REC_MONO, "Rm" , "", 0 }, 207 { SKIN_TOKEN_REC_MONO, "Rm" , "", SKIN_REFRESH_DYNAMIC },
209 { SKIN_TOKEN_REC_SECONDS, "Rs" , "", 0 }, 208 { SKIN_TOKEN_REC_SECONDS, "Rs" , "", SKIN_REFRESH_DYNAMIC },
210 { SKIN_TOKEN_REC_MINUTES, "Rn" , "", 0 }, 209 { SKIN_TOKEN_REC_MINUTES, "Rn" , "", SKIN_REFRESH_DYNAMIC },
211 { SKIN_TOKEN_REC_HOURS, "Rh" , "", 0 }, 210 { SKIN_TOKEN_REC_HOURS, "Rh" , "", SKIN_REFRESH_DYNAMIC },
212 211
213 { SKIN_TOKEN_UNKNOWN, "" , "", 0 } 212 { SKIN_TOKEN_UNKNOWN, "" , "", 0 }
214 /* Keep this here to mark the end of the table */ 213 /* Keep this here to mark the end of the table */
diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h
index f84d4ac762..dde1487d13 100644
--- a/lib/skin_parser/tag_table.h
+++ b/lib/skin_parser/tag_table.h
@@ -27,12 +27,31 @@ extern "C"
27{ 27{
28#endif 28#endif
29 29
30#define MAX_TAG_PARAMS 12
31
32
30 /* Flag to tell the renderer not to insert a line break */ 33 /* Flag to tell the renderer not to insert a line break */
31#define NOBREAK 0x1 34#define NOBREAK 0x1
32 35
36/* constants used in line_type and as refresh_mode for wps_refresh */
37#define SKIN_REFRESH_SHIFT 16
38#define SKIN_REFRESH_STATIC (1u<<SKIN_REFRESH_SHIFT) /* line doesn't change over time */
39#define SKIN_REFRESH_DYNAMIC (1u<<(SKIN_REFRESH_SHIFT+1)) /* line may change (e.g. time flag) */
40#define SKIN_REFRESH_SCROLL (1u<<(SKIN_REFRESH_SHIFT+2)) /* line scrolls */
41#define SKIN_REFRESH_PLAYER_PROGRESS (1u<<(SKIN_REFRESH_SHIFT+3)) /* line contains a progress bar */
42#define SKIN_REFRESH_PEAK_METER (1u<<(SKIN_REFRESH_SHIFT+4)) /* line contains a peak meter */
43#define SKIN_REFRESH_STATUSBAR (1u<<(SKIN_REFRESH_SHIFT+5)) /* refresh statusbar */
44#define SKIN_RTC_REFRESH (1u<<(SKIN_REFRESH_SHIFT+6)) /* refresh rtc, convert at parse time */
45#define SKIN_REFRESH_ALL (0xffffu<<SKIN_REFRESH_SHIFT) /* to refresh all line types */
46
47/* to refresh only those lines that change over time */
48#define SKIN_REFRESH_NON_STATIC (SKIN_REFRESH_DYNAMIC| \
49 SKIN_REFRESH_PLAYER_PROGRESS| \
50 SKIN_REFRESH_PEAK_METER)
33 51
34enum skin_token_type { 52enum skin_token_type {
35 53
54 SKIN_TOKEN_NO_TOKEN,
36 SKIN_TOKEN_UNKNOWN, 55 SKIN_TOKEN_UNKNOWN,
37 56
38 /* Markers */ 57 /* Markers */
@@ -91,7 +110,7 @@ enum skin_token_type {
91 /* The begin/end values allow us to know if a token is an RTC one. 110 /* The begin/end values allow us to know if a token is an RTC one.
92 New RTC tokens should be added between the markers. */ 111 New RTC tokens should be added between the markers. */
93 112
94 SKIN_TOKENs_RTC_BEGIN, /* just the start marker, not an actual token */ 113 SKIN_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */
95 114
96 SKIN_TOKEN_RTC_DAY_OF_MONTH, 115 SKIN_TOKEN_RTC_DAY_OF_MONTH,
97 SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, 116 SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,