summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-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
-rw-r--r--apps/gui/statusbar-skinned.c8
-rw-r--r--apps/gui/viewport.c77
-rw-r--r--apps/gui/viewport.h1
-rw-r--r--apps/gui/wps.c16
-rw-r--r--apps/misc.c10
-rw-r--r--apps/radio/radio_skin.c8
10 files changed, 199 insertions, 143 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 */
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index a53555a291..fcd4cfbd9e 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -200,7 +200,7 @@ void sb_create_from_settings(enum screen_type screen)
200 { 200 {
201 y = screens[screen].lcdheight - STATUSBAR_HEIGHT; 201 y = screens[screen].lcdheight - STATUSBAR_HEIGHT;
202 } 202 }
203 len = snprintf(ptr, remaining, "%%V|0|%d|-|%d|0|-|-|\n%%wi\n", 203 len = snprintf(ptr, remaining, "%%V(0,%d,-,%d,0)\n%%wi\n",
204 y, height); 204 y, height);
205 remaining -= len; 205 remaining -= len;
206 ptr += len; 206 ptr += len;
@@ -215,9 +215,7 @@ void sb_create_from_settings(enum screen_type screen)
215 215
216 if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */ 216 if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */
217 { 217 {
218 len = snprintf(ptr, remaining, "%%ax%%Vi|%s|\n", ptr2); 218 len = snprintf(ptr, remaining, "%%ax%%Vi(-,%s)\n", ptr2);
219 while ((ptr2 = strchr(ptr, ',')))
220 *ptr2 = '|';
221 } 219 }
222 else 220 else
223 { 221 {
@@ -232,7 +230,7 @@ void sb_create_from_settings(enum screen_type screen)
232 default: 230 default:
233 height = screens[screen].lcdheight; 231 height = screens[screen].lcdheight;
234 } 232 }
235 len = snprintf(ptr, remaining, "%%ax%%Vi|0|%d|-|%d|1|-|-|\n", 233 len = snprintf(ptr, remaining, "%%ax%%Vi(-,0,%d,-,%d,1)\n",
236 y, height); 234 y, height);
237 } 235 }
238 sb_skin_data_load(screen, buf, false); 236 sb_skin_data_load(screen, buf, false);
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index a100d56cd5..8731015c79 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -376,6 +376,34 @@ void viewport_set_defaults(struct viewport *vp,
376 376
377 377
378#ifdef HAVE_LCD_BITMAP 378#ifdef HAVE_LCD_BITMAP
379
380int get_viewport_default_colour(enum screen_type screen, bool fgcolour)
381{
382 (void)screen;
383 int colour;
384#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
385 if (fgcolour)
386 {
387#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
388 if (screen == SCREEN_REMOTE)
389 colour = REMOTE_FG_FALLBACK;
390 else
391#endif
392 colour = global_settings.fg_color;
393 }
394 else
395 {
396#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
397 if (screen == SCREEN_REMOTE)
398 colour = REMOTE_BG_FALLBACK;
399 else
400#endif
401 colour = global_settings.bg_color;
402 }
403#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
404 return colour;
405}
406
379const char* viewport_parse_viewport(struct viewport *vp, 407const char* viewport_parse_viewport(struct viewport *vp,
380 enum screen_type screen, 408 enum screen_type screen,
381 const char *bufptr, 409 const char *bufptr,
@@ -383,7 +411,6 @@ const char* viewport_parse_viewport(struct viewport *vp,
383{ 411{
384 /* parse the list to the viewport struct */ 412 /* parse the list to the viewport struct */
385 const char *ptr = bufptr; 413 const char *ptr = bufptr;
386 int depth;
387 uint32_t set = 0; 414 uint32_t set = 0;
388 415
389 enum { 416 enum {
@@ -392,33 +419,11 @@ const char* viewport_parse_viewport(struct viewport *vp,
392 PL_WIDTH, 419 PL_WIDTH,
393 PL_HEIGHT, 420 PL_HEIGHT,
394 PL_FONT, 421 PL_FONT,
395 PL_FG,
396 PL_BG,
397 }; 422 };
398 423
399 /* Work out the depth of this display */ 424 if (!(ptr = parse_list("ddddd", &set, separator, ptr,
400 depth = screens[screen].depth; 425 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font)))
401#if (LCD_DEPTH == 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH == 1) 426 return NULL;
402 if (depth == 1)
403 {
404 if (!(ptr = parse_list("ddddd", &set, separator, ptr,
405 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font)))
406 return NULL;
407 }
408 else
409#endif
410#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
411 if (depth >= 2)
412 {
413 if (!(ptr = parse_list(ARG_STRING(depth), &set, separator, ptr,
414 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font,
415 &vp->fg_pattern,&vp->bg_pattern)))
416 return NULL;
417 }
418 else
419#endif
420 {}
421#undef ARG_STRING
422 427
423 /* X and Y *must* be set */ 428 /* X and Y *must* be set */
424 if (!LIST_VALUE_PARSED(set, PL_X) || !LIST_VALUE_PARSED(set, PL_Y)) 429 if (!LIST_VALUE_PARSED(set, PL_X) || !LIST_VALUE_PARSED(set, PL_Y))
@@ -441,24 +446,8 @@ const char* viewport_parse_viewport(struct viewport *vp,
441 vp->height = (vp->height + screens[screen].lcdheight) - vp->y; 446 vp->height = (vp->height + screens[screen].lcdheight) - vp->y;
442 447
443#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) 448#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
444 if (!LIST_VALUE_PARSED(set, PL_FG)) 449 vp->fg_pattern = get_viewport_default_colour(screen, true);
445 { 450 vp->bg_pattern = get_viewport_default_colour(screen, false);
446#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
447 if (screen == SCREEN_REMOTE)
448 vp->fg_pattern = REMOTE_FG_FALLBACK;
449 else
450#endif
451 vp->fg_pattern = FG_FALLBACK;
452 }
453 if (!LIST_VALUE_PARSED(set, PL_BG))
454 {
455#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
456 if (screen == SCREEN_REMOTE)
457 vp->bg_pattern = REMOTE_BG_FALLBACK;
458 else
459#endif
460 vp->bg_pattern = BG_FALLBACK;
461 }
462#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */ 451#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
463 452
464#ifdef HAVE_LCD_COLOR 453#ifdef HAVE_LCD_COLOR
diff --git a/apps/gui/viewport.h b/apps/gui/viewport.h
index 6a4dd02654..943cac2451 100644
--- a/apps/gui/viewport.h
+++ b/apps/gui/viewport.h
@@ -48,6 +48,7 @@ void viewport_set_defaults(struct viewport *vp,
48 const enum screen_type screen); 48 const enum screen_type screen);
49void viewport_set_fullscreen(struct viewport *vp, 49void viewport_set_fullscreen(struct viewport *vp,
50 const enum screen_type screen); 50 const enum screen_type screen);
51int get_viewport_default_colour(enum screen_type screen, bool fgcolour);
51 52
52#ifdef HAVE_LCD_BITMAP 53#ifdef HAVE_LCD_BITMAP
53void viewportmanager_theme_enable(enum screen_type screen, bool enable, 54void viewportmanager_theme_enable(enum screen_type screen, bool enable,
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 7b84782477..fa97e50897 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -129,26 +129,26 @@ void wps_data_load(enum screen_type screen, const char *buf, bool isfile)
129 char *skin_buf[NB_SCREENS] = { 129 char *skin_buf[NB_SCREENS] = {
130#ifdef HAVE_LCD_BITMAP 130#ifdef HAVE_LCD_BITMAP
131#if LCD_DEPTH > 1 131#if LCD_DEPTH > 1
132 "%Xd\n" 132 "%X(d)\n"
133#endif 133#endif
134 "%s%?it<%?in<%in. |>%it|%fn>\n" 134 "%s%?it<%?in<%in. |>%it|%fn>\n"
135 "%s%?ia<%ia|%?d2<%d2|(root)>>\n" 135 "%s%?ia<%ia|%?d(2)<%d(2)|%(root%)>>\n"
136 "%s%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>\n\n" 136 "%s%?id<%id|%?d(1)<%d(1)|%(root%)>> %?iy<%(%iy%)|>\n\n"
137 "%al%pc/%pt%ar[%pp:%pe]\n" 137 "%al%pc/%pt%ar[%pp:%pe]\n"
138 "%fbkBit %?fv<avg|> %?iv<(id3v%iv)|(no id3)>\n" 138 "%fbkBit %?fv<avg|> %?iv<%(id3v%iv%)|%(no id3%)>\n"
139 "%pb\n%pm\n", 139 "%pb\n%pm\n",
140#else 140#else
141 "%s%pp/%pe: %?it<%it|%fn> - %?ia<%ia|%d2> - %?id<%id|%d1>\n" 141 "%s%pp/%pe: %?it<%it|%fn> - %?ia<%ia|%d(2)> - %?id<%id|%d(1)>\n"
142 "%pc%?ps<*|/>%pt\n", 142 "%pc%?ps<*|/>%pt\n",
143#endif 143#endif
144#ifdef HAVE_REMOTE_LCD 144#ifdef HAVE_REMOTE_LCD
145#if LCD_REMOTE_DEPTH > 1 145#if LCD_REMOTE_DEPTH > 1
146 "%Xd\n" 146 "%X(d)\n"
147#endif 147#endif
148 "%s%?ia<%ia|%?d2<%d2|(root)>>\n" 148 "%s%?ia<%ia|%?d(2)<%d(2)|%(root%)>>\n"
149 "%s%?it<%?in<%in. |>%it|%fn>\n" 149 "%s%?it<%?in<%in. |>%it|%fn>\n"
150 "%al%pc/%pt%ar[%pp:%pe]\n" 150 "%al%pc/%pt%ar[%pp:%pe]\n"
151 "%fbkBit %?fv<avg|> %?iv<(id3v%iv)|(no id3)>\n" 151 "%fbkBit %?fv<avg|> %?iv<%(id3v%iv%)|%(no id3%)>\n"
152 "%pb\n", 152 "%pb\n",
153#endif 153#endif
154 }; 154 };
diff --git a/apps/misc.c b/apps/misc.c
index 747abe076b..d0300f0a4f 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -967,6 +967,7 @@ const char* parse_list(const char *fmt, uint32_t *set_vals,
967 const char** s; 967 const char** s;
968 int* d; 968 int* d;
969 bool set, is_negative; 969 bool set, is_negative;
970 bool is_last_var;
970 int i=0; 971 int i=0;
971 972
972 va_start(ap, str); 973 va_start(ap, str);
@@ -981,6 +982,7 @@ const char* parse_list(const char *fmt, uint32_t *set_vals,
981 goto err; 982 goto err;
982 p++; 983 p++;
983 } 984 }
985 is_last_var = fmt[1] == '\0';
984 set = false; 986 set = false;
985 switch (*fmt++) 987 switch (*fmt++)
986 { 988 {
@@ -988,9 +990,9 @@ const char* parse_list(const char *fmt, uint32_t *set_vals,
988 s = va_arg(ap, const char **); 990 s = va_arg(ap, const char **);
989 991
990 *s = p; 992 *s = p;
991 while (*p && *p != sep) 993 while (*p && *p != sep && *p != ')')
992 p++; 994 p++;
993 set = (s[0][0]!='-') && (s[0][1]!=sep) ; 995 set = (s[0][0]!='-') && (s[0][1]!=sep && s[0][1]!=')') ;
994 break; 996 break;
995 997
996 case 'd': /* int */ 998 case 'd': /* int */
@@ -1028,7 +1030,7 @@ const char* parse_list(const char *fmt, uint32_t *set_vals,
1028 { 1030 {
1029 if (!set_vals || *p != '-') 1031 if (!set_vals || *p != '-')
1030 goto err; 1032 goto err;
1031 while (*p && *p != sep) 1033 while (*p && *p != sep && (!is_last_var || (is_last_var && *p!=')')))
1032 p++; 1034 p++;
1033 } 1035 }
1034 else 1036 else
@@ -1053,7 +1055,7 @@ const char* parse_list(const char *fmt, uint32_t *set_vals,
1053 goto err; 1055 goto err;
1054 else 1056 else
1055 { 1057 {
1056 while (*p && *p != sep) 1058 while (*p && *p != sep && (!is_last_var || (is_last_var && *p!=')')))
1057 p++; 1059 p++;
1058 } 1060 }
1059 1061
diff --git a/apps/radio/radio_skin.c b/apps/radio/radio_skin.c
index 2185c96b6c..838d1f96da 100644
--- a/apps/radio/radio_skin.c
+++ b/apps/radio/radio_skin.c
@@ -46,11 +46,11 @@ void fms_data_load(enum screen_type screen, const char *buf, bool isfile)
46 if (!success ) /* load the default */ 46 if (!success ) /* load the default */
47 { 47 {
48 const char default_fms[] = "%s%?Ti<%Ti. |>%?Tn<%Tn|%Tf>\n" 48 const char default_fms[] = "%s%?Ti<%Ti. |>%?Tn<%Tn|%Tf>\n"
49 "%Sx|Station:| %tf MHz\n" 49 "%Sx(Station:) %tf MHz\n"
50 "%?St|force fm mono|<%Sx|Force Mono||%?ts<%Sx|Stereo||%Sx|Mono|>>\n" 50 "%?St(force fm mono)<%Sx(Force Mono)|%?ts<%Sx(Stereo)|%Sx(Mono)>>\n"
51 "%Sx|Mode:| %?tm<%Sx|Scan||%Sx|Preset|>\n" 51 "%Sx(Mode:) %?tm<%Sx(Scan)|%Sx(Preset)>\n"
52#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) 52#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
53 "%?Rr<%Sx|Time:| %Rh:%Rn:%Rs|%?St|prerecording time|<%pm|%Sx|Prerecord Time| %Rs>>\n" 53 "%?Rr<%Sx(Time:) %Rh:%Rn:%Rs|%?St(prerecording time)<%pm|%Sx(Prerecord Time) %Rs>>\n"
54#endif 54#endif
55 "%pb\n" 55 "%pb\n"
56#ifdef HAVE_RDS_CAP 56#ifdef HAVE_RDS_CAP