summaryrefslogtreecommitdiff
path: root/apps/gui/skin_engine
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-06-07 03:44:11 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-06-07 03:44:11 +0000
commit5b0521c9aadee11886e2c92df7d768d5e76063a6 (patch)
treea6fc72ca29627bb53276c05a5606a559f78bae83 /apps/gui/skin_engine
parent53b619c6e80c9efc6993c23ff7b1035e8e101834 (diff)
downloadrockbox-5b0521c9aadee11886e2c92df7d768d5e76063a6.tar.gz
rockbox-5b0521c9aadee11886e2c92df7d768d5e76063a6.zip
Changeover to the new skin format. SkinBreakingChange in the wiki has the runown of the changes.
Major changes are paramerterised tags now use %tag(param,param), colours are removed from the %V() tag, %Vi gets a required (but can be -) label as its first param). utils/skinupdater/ has a program to update individual skins, and a perl script to update a whole zip. Themesite will be unusable for the time being (you should be able to upload new themes once it updates checkwps though). I obviously havnt tested every updated wps in this change so let me know if one doesnt load git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26641 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/gui/skin_engine')
-rw-r--r--apps/gui/skin_engine/skin_display.c23
-rw-r--r--apps/gui/skin_engine/skin_parser.c190
-rw-r--r--apps/gui/skin_engine/skin_tokens.h2
-rw-r--r--apps/gui/skin_engine/wps_internals.h7
4 files changed, 144 insertions, 78 deletions
diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c
index 848a09eced..6759521473 100644
--- a/apps/gui/skin_engine/skin_display.c
+++ b/apps/gui/skin_engine/skin_display.c
@@ -755,7 +755,20 @@ static bool get_line(struct gui_wps *gwps,
755 skip to the end of the conditional structure */ 755 skip to the end of the conditional structure */
756 i = find_conditional_end(data, i); 756 i = find_conditional_end(data, i);
757 break; 757 break;
758 758#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
759 case WPS_TOKEN_VIEWPORT_FGCOLOUR:
760 {
761 struct viewport_colour *col = data->tokens[i].value.data;
762 col->vp->fg_pattern = col->colour;
763 }
764 break;
765 case WPS_TOKEN_VIEWPORT_BGCOLOUR:
766 {
767 struct viewport_colour *col = data->tokens[i].value.data;
768 col->vp->bg_pattern = col->colour;
769 }
770 break;
771#endif
759#ifdef HAVE_LCD_BITMAP 772#ifdef HAVE_LCD_BITMAP
760 case WPS_TOKEN_PEAKMETER: 773 case WPS_TOKEN_PEAKMETER:
761 data->peak_meter_enabled = true; 774 data->peak_meter_enabled = true;
@@ -1208,14 +1221,16 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode)
1208 } 1221 }
1209 } 1222 }
1210 } 1223 }
1211 int viewport_count = 0;
1212 for (viewport_list = data->viewports; 1224 for (viewport_list = data->viewports;
1213 viewport_list; viewport_list = viewport_list->next, viewport_count++) 1225 viewport_list; viewport_list = viewport_list->next)
1214 { 1226 {
1215 struct skin_viewport *skin_viewport = 1227 struct skin_viewport *skin_viewport =
1216 (struct skin_viewport *)viewport_list->token->value.data; 1228 (struct skin_viewport *)viewport_list->token->value.data;
1217 unsigned vp_refresh_mode = refresh_mode; 1229 unsigned vp_refresh_mode = refresh_mode;
1218 1230#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
1231 skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour;
1232 skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour;
1233#endif
1219 display->set_viewport(&skin_viewport->vp); 1234 display->set_viewport(&skin_viewport->vp);
1220 1235
1221 int hidden_vp = 0; 1236 int hidden_vp = 0;
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 158f2eb7b7..2f79c99144 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -168,6 +168,8 @@ static int parse_font_load(const char *wps_bufptr,
168 struct wps_token *token, struct wps_data *wps_data); 168 struct wps_token *token, struct wps_data *wps_data);
169#endif /*HAVE_LCD_BITMAP */ 169#endif /*HAVE_LCD_BITMAP */
170#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 170#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
171static int parse_viewportcolour(const char *wps_bufptr,
172 struct wps_token *token, struct wps_data *wps_data);
171static int parse_image_special(const char *wps_bufptr, 173static int parse_image_special(const char *wps_bufptr,
172 struct wps_token *token, struct wps_data *wps_data); 174 struct wps_token *token, struct wps_data *wps_data);
173#endif 175#endif
@@ -400,6 +402,10 @@ static const struct wps_tag all_tags[] = {
400 { WPS_TOKEN_LIST_TITLE_TEXT, "Lt", WPS_REFRESH_DYNAMIC, NULL }, 402 { WPS_TOKEN_LIST_TITLE_TEXT, "Lt", WPS_REFRESH_DYNAMIC, NULL },
401 { WPS_TOKEN_LIST_TITLE_ICON, "Li", WPS_REFRESH_DYNAMIC, NULL }, 403 { WPS_TOKEN_LIST_TITLE_ICON, "Li", WPS_REFRESH_DYNAMIC, NULL },
402#endif 404#endif
405#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
406 { WPS_TOKEN_VIEWPORT_FGCOLOUR, "Vf", WPS_REFRESH_STATIC, parse_viewportcolour },
407 { WPS_TOKEN_VIEWPORT_BGCOLOUR, "Vb", WPS_REFRESH_STATIC, parse_viewportcolour },
408#endif
403 { WPS_NO_TOKEN, "V", 0, parse_viewport }, 409 { WPS_NO_TOKEN, "V", 0, parse_viewport },
404 410
405#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 411#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
@@ -618,9 +624,11 @@ static int get_image_id(int c)
618char *get_image_filename(const char *start, const char* bmpdir, 624char *get_image_filename(const char *start, const char* bmpdir,
619 char *buf, int buf_size) 625 char *buf, int buf_size)
620{ 626{
621 const char *end = strchr(start, '|'); 627 const char *end = start;
622 int bmpdirlen = strlen(bmpdir); 628 int bmpdirlen = strlen(bmpdir);
623 629
630 while (*end && *end != ',' && *end != ')')
631 end++;
624 if ( !end || (end - start) >= (buf_size - bmpdirlen - 2) ) 632 if ( !end || (end - start) >= (buf_size - bmpdirlen - 2) )
625 { 633 {
626 buf[0] = '\0'; 634 buf[0] = '\0';
@@ -639,7 +647,7 @@ static int parse_image_display(const char *wps_bufptr,
639 struct wps_token *token, 647 struct wps_token *token,
640 struct wps_data *wps_data) 648 struct wps_data *wps_data)
641{ 649{
642 char label = wps_bufptr[0]; 650 char label = wps_bufptr[1];
643 int subimage; 651 int subimage;
644 struct gui_img *img;; 652 struct gui_img *img;;
645 653
@@ -651,17 +659,17 @@ static int parse_image_display(const char *wps_bufptr,
651 return WPS_ERROR_INVALID_PARAM; 659 return WPS_ERROR_INVALID_PARAM;
652 } 660 }
653 661
654 if ((subimage = get_image_id(wps_bufptr[1])) != -1) 662 if ((subimage = get_image_id(wps_bufptr[2])) != -1)
655 { 663 {
656 if (subimage >= img->num_subimages) 664 if (subimage >= img->num_subimages)
657 return WPS_ERROR_INVALID_PARAM; 665 return WPS_ERROR_INVALID_PARAM;
658 666
659 /* Store sub-image number to display in high bits */ 667 /* Store sub-image number to display in high bits */
660 token->value.i = label | (subimage << 8); 668 token->value.i = label | (subimage << 8);
661 return 2; /* We have consumed 2 bytes */ 669 return 4; /* We have consumed 2 bytes */
662 } else { 670 } else {
663 token->value.i = label; 671 token->value.i = label;
664 return 1; /* We have consumed 1 byte */ 672 return 3; /* We have consumed 1 byte */
665 } 673 }
666} 674}
667 675
@@ -670,10 +678,8 @@ static int parse_image_load(const char *wps_bufptr,
670 struct wps_data *wps_data) 678 struct wps_data *wps_data)
671{ 679{
672 const char *ptr = wps_bufptr; 680 const char *ptr = wps_bufptr;
673 const char *pos;
674 const char* filename; 681 const char* filename;
675 const char* id; 682 const char* id;
676 const char *newline;
677 int x,y; 683 int x,y;
678 struct gui_img *img; 684 struct gui_img *img;
679 685
@@ -682,16 +688,16 @@ static int parse_image_load(const char *wps_bufptr,
682 or %xl|n|filename.bmp|x|y|num_subimages| 688 or %xl|n|filename.bmp|x|y|num_subimages|
683 */ 689 */
684 690
685 if (*ptr != '|') 691 if (*ptr != '(')
686 return WPS_ERROR_INVALID_PARAM; 692 return WPS_ERROR_INVALID_PARAM;
687 693
688 ptr++; 694 ptr++;
689 695
690 if (!(ptr = parse_list("ssdd", NULL, '|', ptr, &id, &filename, &x, &y))) 696 if (!(ptr = parse_list("ssdd", NULL, ',', ptr, &id, &filename, &x, &y)))
691 return WPS_ERROR_INVALID_PARAM; 697 return WPS_ERROR_INVALID_PARAM;
692 698
693 /* Check there is a terminating | */ 699 /* Check there is a terminating ) */
694 if (*ptr != '|') 700 if (*ptr != ')' && *ptr != ',')
695 return WPS_ERROR_INVALID_PARAM; 701 return WPS_ERROR_INVALID_PARAM;
696 702
697 /* check the image number and load state */ 703 /* check the image number and load state */
@@ -718,15 +724,11 @@ static int parse_image_load(const char *wps_bufptr,
718 { 724 {
719 img->always_display = true; 725 img->always_display = true;
720 } 726 }
721 else 727 else if (*ptr == ',')
722 { 728 {
723 /* Parse the (optional) number of sub-images */ 729 /* Parse the (optional) number of sub-images */
724 ptr++; 730 ptr++;
725 newline = strchr(ptr, '\n'); 731 img->num_subimages = atoi(ptr);
726 pos = strchr(ptr, '|');
727 if (pos && pos < newline)
728 img->num_subimages = atoi(ptr);
729
730 if (img->num_subimages <= 0) 732 if (img->num_subimages <= 0)
731 return WPS_ERROR_INVALID_PARAM; 733 return WPS_ERROR_INVALID_PARAM;
732 } 734 }
@@ -751,16 +753,16 @@ static int parse_font_load(const char *wps_bufptr,
751 int id; 753 int id;
752 char *filename; 754 char *filename;
753 755
754 if (*ptr != '|') 756 if (*ptr != '(')
755 return WPS_ERROR_INVALID_PARAM; 757 return WPS_ERROR_INVALID_PARAM;
756 758
757 ptr++; 759 ptr++;
758 760
759 if (!(ptr = parse_list("ds", NULL, '|', ptr, &id, &filename))) 761 if (!(ptr = parse_list("ds", NULL, ',', ptr, &id, &filename)))
760 return WPS_ERROR_INVALID_PARAM; 762 return WPS_ERROR_INVALID_PARAM;
761 763
762 /* Check there is a terminating | */ 764 /* Check there is a terminating | */
763 if (*ptr != '|') 765 if (*ptr != ')')
764 return WPS_ERROR_INVALID_PARAM; 766 return WPS_ERROR_INVALID_PARAM;
765 767
766 if (id <= FONT_UI || id >= MAXFONTS-1) 768 if (id <= FONT_UI || id >= MAXFONTS-1)
@@ -774,7 +776,7 @@ static int parse_font_load(const char *wps_bufptr,
774 /* make sure the filename contains .fnt, 776 /* make sure the filename contains .fnt,
775 * we dont actually use it, but require it anyway */ 777 * we dont actually use it, but require it anyway */
776 ptr = strchr(filename, '.'); 778 ptr = strchr(filename, '.');
777 if (!ptr || strncmp(ptr, ".fnt|", 5)) 779 if (!ptr || strncmp(ptr, ".fnt)", 5))
778 return WPS_ERROR_INVALID_PARAM; 780 return WPS_ERROR_INVALID_PARAM;
779 skinfonts[id-FONT_FIRSTUSERFONT].id = -1; 781 skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
780 skinfonts[id-FONT_FIRSTUSERFONT].name = filename; 782 skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
@@ -788,7 +790,7 @@ static int parse_viewport_display(const char *wps_bufptr,
788 struct wps_data *wps_data) 790 struct wps_data *wps_data)
789{ 791{
790 (void)wps_data; 792 (void)wps_data;
791 char letter = wps_bufptr[0]; 793 char letter = wps_bufptr[1];
792 794
793 if (letter < 'a' || letter > 'z') 795 if (letter < 'a' || letter > 'z')
794 { 796 {
@@ -796,7 +798,7 @@ static int parse_viewport_display(const char *wps_bufptr,
796 return WPS_ERROR_INVALID_PARAM; 798 return WPS_ERROR_INVALID_PARAM;
797 } 799 }
798 token->value.i = letter; 800 token->value.i = letter;
799 return 1; 801 return 3;
800} 802}
801 803
802#ifdef HAVE_LCD_BITMAP 804#ifdef HAVE_LCD_BITMAP
@@ -807,12 +809,12 @@ static int parse_playlistview_text(struct playlistviewer *viewer,
807 const struct wps_tag *tag; 809 const struct wps_tag *tag;
808 int taglen = 0; 810 int taglen = 0;
809 const char *start = text; 811 const char *start = text;
810 if (*text != '|') 812 if (*text != ',')
811 return -1; 813 return -1;
812 text++; 814 text++;
813 viewer->lines[line].count = 0; 815 viewer->lines[line].count = 0;
814 viewer->lines[line].scroll = false; 816 viewer->lines[line].scroll = false;
815 while (*text != '|') 817 while (*text != ',' && *text != ')')
816 { 818 {
817 if (*text == '%') /* it is a token of some type */ 819 if (*text == '%') /* it is a token of some type */
818 { 820 {
@@ -826,6 +828,9 @@ static int parse_playlistview_text(struct playlistviewer *viewer,
826 case '>': 828 case '>':
827 case ';': 829 case ';':
828 case '#': 830 case '#':
831 case '(':
832 case ')':
833 case ',':
829 /* escaped characters */ 834 /* escaped characters */
830 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER; 835 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER;
831 viewer->lines[line].strings[cur_string][0] = *text; 836 viewer->lines[line].strings[cur_string][0] = *text;
@@ -850,7 +855,7 @@ static int parse_playlistview_text(struct playlistviewer *viewer,
850 int i = 0; 855 int i = 0;
851 /* just copy the string */ 856 /* just copy the string */
852 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING; 857 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
853 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != '|' && text[i] != '%') 858 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
854 { 859 {
855 viewer->lines[line].strings[cur_string][i] = text[i]; 860 viewer->lines[line].strings[cur_string][i] = text[i];
856 i++; 861 i++;
@@ -878,7 +883,7 @@ static int parse_playlistview_text(struct playlistviewer *viewer,
878 int i = 0; 883 int i = 0;
879 /* just copy the string */ 884 /* just copy the string */
880 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING; 885 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
881 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != '|' && text[i] != '%') 886 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
882 { 887 {
883 viewer->lines[line].strings[cur_string][i] = text[i]; 888 viewer->lines[line].strings[cur_string][i] = text[i];
884 i++; 889 i++;
@@ -891,14 +896,13 @@ static int parse_playlistview_text(struct playlistviewer *viewer,
891 return text - start; 896 return text - start;
892} 897}
893 898
894
895static int parse_playlistview(const char *wps_bufptr, 899static int parse_playlistview(const char *wps_bufptr,
896 struct wps_token *token, struct wps_data *wps_data) 900 struct wps_token *token, struct wps_data *wps_data)
897{ 901{
898 (void)wps_data; 902 (void)wps_data;
899 /* %Vp|<use icons>|<start offset>|info line text|no info text| */ 903 /* %Vp|<use icons>|<start offset>|info line text|no info text| */
900 struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer)); 904 struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer));
901 char *ptr = strchr(wps_bufptr, '|'); 905 char *ptr = strchr(wps_bufptr, '(');
902 int length; 906 int length;
903 if (!viewer || !ptr) 907 if (!viewer || !ptr)
904 return WPS_ERROR_INVALID_PARAM; 908 return WPS_ERROR_INVALID_PARAM;
@@ -906,7 +910,7 @@ static int parse_playlistview(const char *wps_bufptr,
906 viewer->show_icons = true; 910 viewer->show_icons = true;
907 viewer->start_offset = atoi(ptr+1); 911 viewer->start_offset = atoi(ptr+1);
908 token->value.data = (void*)viewer; 912 token->value.data = (void*)viewer;
909 ptr = strchr(ptr+1, '|'); 913 ptr = strchr(ptr+1, ',');
910 length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr); 914 length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr);
911 if (length < 0) 915 if (length < 0)
912 return WPS_ERROR_INVALID_PARAM; 916 return WPS_ERROR_INVALID_PARAM;
@@ -944,7 +948,7 @@ static int parse_viewport(const char *wps_bufptr,
944 948
945 if (*ptr == 'i') 949 if (*ptr == 'i')
946 { 950 {
947 if (*(ptr+1) == '|') 951 if (*(ptr+1) == '(')
948 { 952 {
949 char label = *(ptr+2); 953 char label = *(ptr+2);
950 if (label >= 'a' && label <= 'z') 954 if (label >= 'a' && label <= 'z')
@@ -955,9 +959,11 @@ static int parse_viewport(const char *wps_bufptr,
955 } 959 }
956 else 960 else
957 { 961 {
962 if (label != '-')
963 return WPS_ERROR_INVALID_PARAM;
958 skin_vp->label = VP_INFO_LABEL|VP_DEFAULT_LABEL; 964 skin_vp->label = VP_INFO_LABEL|VP_DEFAULT_LABEL;
959 skin_vp->hidden_flags = VP_NEVER_VISIBLE; 965 skin_vp->hidden_flags = VP_NEVER_VISIBLE;
960 ++ptr; 966 ptr += 3;
961 } 967 }
962 } 968 }
963 else 969 else
@@ -966,7 +972,7 @@ static int parse_viewport(const char *wps_bufptr,
966 } 972 }
967 else if (*ptr == 'l') 973 else if (*ptr == 'l')
968 { 974 {
969 if (*(ptr+1) == '|') 975 if (*(ptr+1) == '(')
970 { 976 {
971 char label = *(ptr+2); 977 char label = *(ptr+2);
972 if (label >= 'a' && label <= 'z') 978 if (label >= 'a' && label <= 'z')
@@ -979,17 +985,17 @@ static int parse_viewport(const char *wps_bufptr,
979 ptr += 3; 985 ptr += 3;
980 } 986 }
981 } 987 }
982 if (*ptr != '|') 988 if (*ptr != ',' && *ptr != '(')
983 return WPS_ERROR_INVALID_PARAM; 989 return WPS_ERROR_INVALID_PARAM;
984 990
985 ptr++; 991 ptr++;
986 struct viewport *vp = &skin_vp->vp; 992 struct viewport *vp = &skin_vp->vp;
987 /* format: %V|x|y|width|height|font|fg_pattern|bg_pattern| */ 993 /* format: %V|x|y|width|height|font| */
988 if (!(ptr = viewport_parse_viewport(vp, curr_screen, ptr, '|'))) 994 if (!(ptr = viewport_parse_viewport(vp, curr_screen, ptr, ',')))
989 return WPS_ERROR_INVALID_PARAM; 995 return WPS_ERROR_INVALID_PARAM;
990 996
991 /* Check for trailing | */ 997 /* Check for trailing ) */
992 if (*ptr != '|') 998 if (*ptr != ')')
993 return WPS_ERROR_INVALID_PARAM; 999 return WPS_ERROR_INVALID_PARAM;
994 1000
995 if (follow_lang_direction && lang_is_rtl()) 1001 if (follow_lang_direction && lang_is_rtl())
@@ -999,6 +1005,11 @@ static int parse_viewport(const char *wps_bufptr,
999 } 1005 }
1000 else 1006 else
1001 vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */ 1007 vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */
1008
1009#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1010 skin_vp->start_fgcolour = vp->fg_pattern;
1011 skin_vp->start_bgcolour = vp->bg_pattern;
1012#endif
1002 1013
1003 struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp); 1014 struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp);
1004 if (!list) 1015 if (!list)
@@ -1008,8 +1019,30 @@ static int parse_viewport(const char *wps_bufptr,
1008 /* Skip the rest of the line */ 1019 /* Skip the rest of the line */
1009 return skip_end_of_line(wps_bufptr); 1020 return skip_end_of_line(wps_bufptr);
1010} 1021}
1011
1012#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 1022#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1023static int parse_viewportcolour(const char *wps_bufptr,
1024 struct wps_token *token, struct wps_data *wps_data)
1025{
1026 (void)wps_data;
1027 const char *ptr = wps_bufptr;
1028 struct viewport_colour *colour = skin_buffer_alloc(sizeof(struct viewport_colour));
1029 int set;
1030 if (*ptr != '(' || !colour)
1031 return -1;
1032 ptr++;
1033 if (!(ptr = parse_list("c", &set, ',', ptr, &colour->colour)))
1034 return -1;
1035 if (*ptr != ')')
1036 return -1;
1037 if (!set)
1038 colour->colour = get_viewport_default_colour(curr_screen,
1039 token->type == WPS_TOKEN_VIEWPORT_FGCOLOUR);
1040 colour->vp = &curr_vp->vp;
1041 token->value.data = colour;
1042 ptr++;
1043 return ptr - wps_bufptr;
1044}
1045
1013static int parse_image_special(const char *wps_bufptr, 1046static int parse_image_special(const char *wps_bufptr,
1014 struct wps_token *token, 1047 struct wps_token *token,
1015 struct wps_data *wps_data) 1048 struct wps_data *wps_data)
@@ -1020,7 +1053,7 @@ static int parse_image_special(const char *wps_bufptr,
1020 const char *newline; 1053 const char *newline;
1021 bool error = false; 1054 bool error = false;
1022 1055
1023 pos = strchr(wps_bufptr + 1, '|'); 1056 pos = strchr(wps_bufptr + 1, ')');
1024 newline = strchr(wps_bufptr, '\n'); 1057 newline = strchr(wps_bufptr, '\n');
1025 1058
1026 error = (pos > newline); 1059 error = (pos > newline);
@@ -1029,7 +1062,7 @@ static int parse_image_special(const char *wps_bufptr,
1029 if (token->type == WPS_TOKEN_IMAGE_BACKDROP) 1062 if (token->type == WPS_TOKEN_IMAGE_BACKDROP)
1030 { 1063 {
1031 /* format: %X|filename.bmp| or %Xd */ 1064 /* format: %X|filename.bmp| or %Xd */
1032 if (*(wps_bufptr) == 'd') 1065 if (*(wps_bufptr+1) == 'd')
1033 { 1066 {
1034 wps_data->backdrop = NULL; 1067 wps_data->backdrop = NULL;
1035 return skip_end_of_line(wps_bufptr); 1068 return skip_end_of_line(wps_bufptr);
@@ -1063,10 +1096,10 @@ static int parse_setting_and_lang(const char *wps_bufptr,
1063 char temp[64]; 1096 char temp[64];
1064 1097
1065 /* Find the setting's cfg_name */ 1098 /* Find the setting's cfg_name */
1066 if (*ptr != '|') 1099 if (*ptr != '(')
1067 return WPS_ERROR_INVALID_PARAM; 1100 return WPS_ERROR_INVALID_PARAM;
1068 ptr++; 1101 ptr++;
1069 end = strchr(ptr,'|'); 1102 end = strchr(ptr,')');
1070 if (!end || (size_t)(end-ptr+1) > sizeof temp) 1103 if (!end || (size_t)(end-ptr+1) > sizeof temp)
1071 return WPS_ERROR_INVALID_PARAM; 1104 return WPS_ERROR_INVALID_PARAM;
1072 strlcpy(temp, ptr,end-ptr+1); 1105 strlcpy(temp, ptr,end-ptr+1);
@@ -1103,10 +1136,12 @@ static int parse_dir_level(const char *wps_bufptr,
1103 struct wps_token *token, 1136 struct wps_token *token,
1104 struct wps_data *wps_data) 1137 struct wps_data *wps_data)
1105{ 1138{
1106 char val[] = { *wps_bufptr, '\0' }; 1139 char val[] = { wps_bufptr[1], '\0' };
1140 if (wps_bufptr[0] != '(' || wps_bufptr[2] != ')')
1141 return WPS_ERROR_INVALID_PARAM;
1107 token->value.i = atoi(val); 1142 token->value.i = atoi(val);
1108 (void)wps_data; /* Kill warnings */ 1143 (void)wps_data; /* Kill warnings */
1109 return 1; 1144 return 3;
1110} 1145}
1111 1146
1112static int parse_timeout(const char *wps_bufptr, 1147static int parse_timeout(const char *wps_bufptr,
@@ -1119,28 +1154,31 @@ static int parse_timeout(const char *wps_bufptr,
1119 bool have_tenth = false; 1154 bool have_tenth = false;
1120 1155
1121 (void)wps_data; /* Kill the warning */ 1156 (void)wps_data; /* Kill the warning */
1122 1157 if (*wps_bufptr == '(')
1123 while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
1124 { 1158 {
1125 if (*wps_bufptr != '.') 1159 while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
1126 { 1160 {
1127 val *= 10; 1161 if (*wps_bufptr != '.')
1128 val += *wps_bufptr - '0';
1129 if (have_point)
1130 { 1162 {
1131 have_tenth = true; 1163 val *= 10;
1132 wps_bufptr++; 1164 val += *wps_bufptr - '0';
1133 skip++; 1165 if (have_point)
1134 break; 1166 {
1167 have_tenth = true;
1168 wps_bufptr++;
1169 skip++;
1170 break;
1171 }
1135 } 1172 }
1136 } 1173 else
1137 else 1174 have_point = true;
1138 have_point = true;
1139 1175
1140 wps_bufptr++; 1176 wps_bufptr++;
1141 skip++; 1177 skip++;
1178 }
1179 if (*wps_bufptr != ')')
1180 return -1;
1142 } 1181 }
1143
1144 if (have_tenth == false) 1182 if (have_tenth == false)
1145 val *= 10; 1183 val *= 10;
1146 1184
@@ -1203,7 +1241,7 @@ static int parse_progressbar(const char *wps_bufptr,
1203 pb->follow_lang_direction = follow_lang_direction > 0; 1241 pb->follow_lang_direction = follow_lang_direction > 0;
1204 pb->draw = false; 1242 pb->draw = false;
1205 1243
1206 if (*wps_bufptr != '|') /* regular old style */ 1244 if (*wps_bufptr != '(') /* regular old style */
1207 { 1245 {
1208 pb->x = 0; 1246 pb->x = 0;
1209 pb->width = vp->width; 1247 pb->width = vp->width;
@@ -1217,7 +1255,7 @@ static int parse_progressbar(const char *wps_bufptr,
1217 } 1255 }
1218 ptr = wps_bufptr + 1; 1256 ptr = wps_bufptr + 1;
1219 1257
1220 if (!(ptr = parse_list("sdddd", &set, '|', ptr, &filename, 1258 if (!(ptr = parse_list("sdddd", &set, ',', ptr, &filename,
1221 &x, &y, &width, &height))) 1259 &x, &y, &width, &height)))
1222 { 1260 {
1223 /* If we are in a conditional then we probably don't want to fail 1261 /* If we are in a conditional then we probably don't want to fail
@@ -1298,9 +1336,8 @@ static int parse_progressbar(const char *wps_bufptr,
1298#ifdef HAVE_ALBUMART 1336#ifdef HAVE_ALBUMART
1299static int parse_int(const char *newline, const char **_pos, int *num) 1337static int parse_int(const char *newline, const char **_pos, int *num)
1300{ 1338{
1301 *_pos = parse_list("d", NULL, '|', *_pos, num); 1339 *_pos = parse_list("d", NULL, ',', *_pos, num);
1302 1340 return (!*_pos || *_pos > newline || (**_pos != ',' && **_pos != ')'));
1303 return (!*_pos || *_pos > newline || **_pos != '|');
1304} 1341}
1305 1342
1306static int parse_albumart_load(const char *wps_bufptr, 1343static int parse_albumart_load(const char *wps_bufptr,
@@ -1330,7 +1367,7 @@ static int parse_albumart_load(const char *wps_bufptr,
1330 1367
1331 _pos = wps_bufptr; 1368 _pos = wps_bufptr;
1332 1369
1333 if (*_pos != '|') 1370 if (*_pos != '(')
1334 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */ 1371 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
1335 1372
1336 ++_pos; 1373 ++_pos;
@@ -1387,7 +1424,7 @@ static int parse_albumart_load(const char *wps_bufptr,
1387 } 1424 }
1388 } 1425 }
1389 /* extract max width data */ 1426 /* extract max width data */
1390 if (*_pos != '|') 1427 if (*_pos != ',')
1391 { 1428 {
1392 if (parse_int(newline, &_pos, &aa->width)) 1429 if (parse_int(newline, &_pos, &aa->width))
1393 return WPS_ERROR_INVALID_PARAM; 1430 return WPS_ERROR_INVALID_PARAM;
@@ -1429,7 +1466,7 @@ static int parse_albumart_load(const char *wps_bufptr,
1429 } 1466 }
1430 } 1467 }
1431 /* extract max height data */ 1468 /* extract max height data */
1432 if (*_pos != '|') 1469 if (*_pos != ',')
1433 { 1470 {
1434 if (parse_int(newline, &_pos, &aa->height)) 1471 if (parse_int(newline, &_pos, &aa->height))
1435 return WPS_ERROR_INVALID_PARAM; 1472 return WPS_ERROR_INVALID_PARAM;
@@ -1537,15 +1574,15 @@ static int parse_touchregion(const char *wps_bufptr,
1537 */ 1574 */
1538 1575
1539 1576
1540 if (*ptr != '|') 1577 if (*ptr != '(')
1541 return WPS_ERROR_INVALID_PARAM; 1578 return WPS_ERROR_INVALID_PARAM;
1542 ptr++; 1579 ptr++;
1543 1580
1544 if (!(ptr = parse_list("dddds", NULL, '|', ptr, &x, &y, &w, &h, &action))) 1581 if (!(ptr = parse_list("dddds", NULL, ',', ptr, &x, &y, &w, &h, &action)))
1545 return WPS_ERROR_INVALID_PARAM; 1582 return WPS_ERROR_INVALID_PARAM;
1546 1583
1547 /* Check there is a terminating | */ 1584 /* Check there is a terminating | */
1548 if (*ptr != '|') 1585 if (*ptr != ')')
1549 return WPS_ERROR_INVALID_PARAM; 1586 return WPS_ERROR_INVALID_PARAM;
1550 1587
1551 region = skin_buffer_alloc(sizeof(struct touchregion)); 1588 region = skin_buffer_alloc(sizeof(struct touchregion));
@@ -1561,7 +1598,7 @@ static int parse_touchregion(const char *wps_bufptr,
1561 region->wvp = curr_vp; 1598 region->wvp = curr_vp;
1562 region->armed = false; 1599 region->armed = false;
1563 1600
1564 end = strchr(action, '|'); 1601 end = strchr(action, ')');
1565 if (!end || (size_t)(end-action+1) > sizeof temp) 1602 if (!end || (size_t)(end-action+1) > sizeof temp)
1566 return WPS_ERROR_INVALID_PARAM; 1603 return WPS_ERROR_INVALID_PARAM;
1567 strlcpy(temp, action, end-action+1); 1604 strlcpy(temp, action, end-action+1);
@@ -1621,6 +1658,9 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
1621 case '>': 1658 case '>':
1622 case ';': 1659 case ';':
1623 case '#': 1660 case '#':
1661 case ')':
1662 case '(':
1663 case ',':
1624 /* escaped characters */ 1664 /* escaped characters */
1625 token->type = WPS_TOKEN_CHARACTER; 1665 token->type = WPS_TOKEN_CHARACTER;
1626 token->value.c = *wps_bufptr; 1666 token->value.c = *wps_bufptr;
@@ -2276,6 +2316,10 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
2276 curr_vp->lines = NULL; 2316 curr_vp->lines = NULL;
2277 2317
2278 viewport_set_defaults(&curr_vp->vp, screen); 2318 viewport_set_defaults(&curr_vp->vp, screen);
2319#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
2320 curr_vp->start_fgcolour = curr_vp->vp.fg_pattern;
2321 curr_vp->start_bgcolour = curr_vp->vp.bg_pattern;
2322#endif
2279#ifdef HAVE_LCD_BITMAP 2323#ifdef HAVE_LCD_BITMAP
2280 curr_vp->vp.font = FONT_UI; 2324 curr_vp->vp.font = FONT_UI;
2281#endif 2325#endif
diff --git a/apps/gui/skin_engine/skin_tokens.h b/apps/gui/skin_engine/skin_tokens.h
index f25b123d9d..47311312db 100644
--- a/apps/gui/skin_engine/skin_tokens.h
+++ b/apps/gui/skin_engine/skin_tokens.h
@@ -56,6 +56,8 @@ enum wps_token_type {
56 WPS_VIEWPORT_ENABLE, 56 WPS_VIEWPORT_ENABLE,
57 WPS_VIEWPORT_CUSTOMLIST, 57 WPS_VIEWPORT_CUSTOMLIST,
58 WPS_TOKEN_UIVIEWPORT_ENABLE, 58 WPS_TOKEN_UIVIEWPORT_ENABLE,
59 WPS_TOKEN_VIEWPORT_FGCOLOUR,
60 WPS_TOKEN_VIEWPORT_BGCOLOUR,
59 61
60 /* Battery */ 62 /* Battery */
61 TOKEN_MARKER_BATTERY, 63 TOKEN_MARKER_BATTERY,
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index 945932a125..5501dd580b 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -209,8 +209,13 @@ struct skin_viewport {
209 struct skin_line *lines; 209 struct skin_line *lines;
210 char hidden_flags; 210 char hidden_flags;
211 char label; 211 char label;
212 unsigned start_fgcolour;
213 unsigned start_bgcolour;
214};
215struct viewport_colour {
216 struct viewport *vp;
217 unsigned colour;
212}; 218};
213
214#ifdef HAVE_TOUCHSCREEN 219#ifdef HAVE_TOUCHSCREEN
215struct touchregion { 220struct touchregion {
216 struct skin_viewport* wvp;/* The viewport this region is in */ 221 struct skin_viewport* wvp;/* The viewport this region is in */