From 2d31d77a8ba231cb03ec35863c4c4ce2024f6509 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 29 Jul 2010 12:37:48 +0000 Subject: 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 --- apps/gui/skin_engine/skin_parser.c | 2119 ++++++++++-------------------------- 1 file changed, 590 insertions(+), 1529 deletions(-) (limited to 'apps/gui/skin_engine/skin_parser.c') diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index a62791e397..52e7e1155c 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2007 Nicolas Pennequin, Dan Everton, Matthias Mohr + * 2010 Jonathan Gordon * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,6 +29,10 @@ #include "plugin.h" #include "viewport.h" +#include "skin_buffer.h" +#include "skin_parser.h" +#include "tag_table.h" + #ifdef __PCTOOL__ #ifdef WPSEDITOR #include "proxy.h" @@ -71,377 +76,29 @@ #define WPS_ERROR_INVALID_PARAM -1 -/* which screen are we parsing for? */ -static enum screen_type curr_screen; - -/* level of current conditional. - -1 means we're not in a conditional. */ -static int level = -1; - -/* index of the last WPS_TOKEN_CONDITIONAL_OPTION - or WPS_TOKEN_CONDITIONAL_START in current level */ -static int lastcond[WPS_MAX_COND_LEVEL]; - -/* index of the WPS_TOKEN_CONDITIONAL in current level */ -static int condindex[WPS_MAX_COND_LEVEL]; - -/* number of condtional options in current level */ -static int numoptions[WPS_MAX_COND_LEVEL]; - -/* line number, debug only */ -static int line_number; - -/* the current viewport */ -static struct skin_viewport *curr_vp; -/* the current line, linked to the above viewport */ -static struct skin_line *curr_line; - -static int follow_lang_direction = 0; - -#if defined(DEBUG) || defined(SIMULATOR) -/* debugging function */ -extern void print_debug_info(struct wps_data *data, int fail, int line); -extern void debug_skin_usage(void); -#endif -/* Function for parsing of details for a token. At the moment the - function is called, the token type has already been set. The - function must fill in the details and possibly add more tokens - to the token array. It should return the number of chars that - has been consumed. - - wps_bufptr points to the char following the tag (i.e. where - details begin). - token is the pointer to the 'main' token being parsed - */ -typedef int (*wps_tag_parse_func)(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); - -struct wps_tag { - enum wps_token_type type; - const char name[3]; - unsigned char refresh_type; - const wps_tag_parse_func parse_func; -}; -static int skip_end_of_line(const char *wps_bufptr); -/* prototypes of all special parse functions : */ -static int parse_timeout(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_progressbar(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_dir_level(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_setting_and_lang(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); - - -static int parse_languagedirection(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data) +static bool isdefault(struct skin_tag_parameter *param) { - (void)wps_bufptr; - (void)token; - (void)wps_data; - follow_lang_direction = 2; /* 2 because it is decremented immediatly after - this token is parsed, after the next token it - will be 0 again. */ - return 0; + return param->type == DEFAULT; } -#ifdef HAVE_LCD_BITMAP -static int parse_viewport_display(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_playlistview(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_viewport(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_statusbar_enable(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_statusbar_disable(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_statusbar_inbuilt(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_image_display(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_image_load(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_font_load(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -#endif /*HAVE_LCD_BITMAP */ -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) -static int parse_viewportcolour(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_image_special(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -#endif -#ifdef HAVE_ALBUMART -static int parse_albumart_load(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -static int parse_albumart_display(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -#endif /* HAVE_ALBUMART */ -#ifdef HAVE_TOUCHSCREEN -static int parse_touchregion(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data); -#else -static int fulline_tag_not_supported(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data) -{ - (void)token; (void)wps_data; - return skip_end_of_line(wps_bufptr); -} -#define parse_touchregion fulline_tag_not_supported -#endif -#ifdef CONFIG_RTC -#define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC -#else -#define WPS_RTC_REFRESH WPS_REFRESH_STATIC -#endif - -/* array of available tags - those with more characters have to go first - (e.g. "xl" and "xd" before "x"). It needs to end with the unknown token. */ -static const struct wps_tag all_tags[] = { - - { WPS_TOKEN_ALIGN_CENTER, "ac", 0, NULL }, - { WPS_TOKEN_ALIGN_LEFT, "al", 0, NULL }, - { WPS_TOKEN_ALIGN_LEFT_RTL, "aL", 0, NULL }, - { WPS_TOKEN_ALIGN_RIGHT, "ar", 0, NULL }, - { WPS_TOKEN_ALIGN_RIGHT_RTL, "aR", 0, NULL }, - { WPS_NO_TOKEN, "ax", 0, parse_languagedirection }, - - { WPS_TOKEN_BATTERY_PERCENT, "bl", WPS_REFRESH_DYNAMIC, parse_progressbar }, - { WPS_TOKEN_BATTERY_VOLTS, "bv", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_BATTERY_TIME, "bt", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_BATTERY_SLEEPTIME, "bs", WPS_REFRESH_DYNAMIC, NULL }, -#if CONFIG_CHARGING >= CHARGING_MONITOR - { WPS_TOKEN_BATTERY_CHARGING, "bc", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#if CONFIG_CHARGING - { WPS_TOKEN_BATTERY_CHARGER_CONNECTED,"bp", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#ifdef HAVE_USB_POWER - { WPS_TOKEN_USB_POWERED, "bu", WPS_REFRESH_DYNAMIC, NULL }, -#endif - - { WPS_TOKEN_RTC_PRESENT , "cc", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_RTC_DAY_OF_MONTH, "cd", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,"ce", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_12HOUR_CFG, "cf", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_HOUR_24, "ck", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_HOUR_12, "cl", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_MONTH, "cm", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_MINUTE, "cM", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_SECOND, "cS", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_YEAR_2_DIGITS, "cy", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_YEAR_4_DIGITS, "cY", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_AM_PM_UPPER, "cP", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_AM_PM_LOWER, "cp", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_WEEKDAY_NAME, "ca", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_MONTH_NAME, "cb", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", WPS_RTC_REFRESH, NULL }, - { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", WPS_RTC_REFRESH, NULL }, - - /* current file */ - { WPS_TOKEN_FILE_BITRATE, "fb", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_CODEC, "fc", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_FREQUENCY, "ff", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_FREQUENCY_KHZ, "fk", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_NAME, "fn", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_PATH, "fp", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_SIZE, "fs", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_VBR, "fv", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_DIRECTORY, "d", WPS_REFRESH_STATIC, - parse_dir_level }, - - /* next file */ - { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_STATIC, - parse_dir_level }, - - /* current metadata */ - { WPS_TOKEN_METADATA_ARTIST, "ia", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_COMPOSER, "ic", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_GROUPING, "iG", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_DISC_NUMBER, "ik", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_YEAR, "iy", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL }, - - /* next metadata */ - { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_STATIC, NULL }, - -#if (CONFIG_CODEC != MAS3507D) - { WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#if (CONFIG_CODEC == SWCODEC) - { WPS_TOKEN_SOUND_SPEED, "Ss", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) - { WPS_TOKEN_VLED_HDD, "lh", WPS_REFRESH_DYNAMIC, NULL }, -#endif - - { WPS_TOKEN_MAIN_HOLD, "mh", WPS_REFRESH_DYNAMIC, NULL }, -#ifdef HAS_REMOTE_BUTTON_HOLD - { WPS_TOKEN_REMOTE_HOLD, "mr", WPS_REFRESH_DYNAMIC, NULL }, -#else - { WPS_TOKEN_UNKNOWN, "mr", 0, NULL }, -#endif - - { WPS_TOKEN_REPEAT_MODE, "mm", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_PLAYBACK_STATUS, "mp", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_BUTTON_VOLUME, "mv", WPS_REFRESH_DYNAMIC, - parse_timeout }, - -#ifdef HAVE_LCD_BITMAP - { WPS_TOKEN_PEAKMETER, "pm", WPS_REFRESH_PEAK_METER, NULL }, -#else - { WPS_TOKEN_PLAYER_PROGRESSBAR, "pf", - WPS_REFRESH_DYNAMIC | WPS_REFRESH_PLAYER_PROGRESS, parse_progressbar }, -#endif - { WPS_TOKEN_PROGRESSBAR, "pb", WPS_REFRESH_PLAYER_PROGRESS, - parse_progressbar }, - - { WPS_TOKEN_VOLUME, "pv", WPS_REFRESH_DYNAMIC, - parse_progressbar }, - - { WPS_TOKEN_TRACK_ELAPSED_PERCENT, "px", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TRACK_TIME_ELAPSED, "pc", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TRACK_TIME_REMAINING, "pr", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TRACK_LENGTH, "pt", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_TRACK_STARTING, "pS", WPS_REFRESH_DYNAMIC, parse_timeout }, - { WPS_TOKEN_TRACK_ENDING, "pE", WPS_REFRESH_DYNAMIC, parse_timeout }, - - { WPS_TOKEN_PLAYLIST_POSITION, "pp", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PLAYLIST_ENTRIES, "pe", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PLAYLIST_NAME, "pn", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PLAYLIST_SHUFFLE, "ps", WPS_REFRESH_DYNAMIC, NULL }, - -#ifdef HAVE_TAGCACHE - { WPS_TOKEN_DATABASE_PLAYCOUNT, "rp", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_DATABASE_RATING, "rr", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_DATABASE_AUTOSCORE, "ra", WPS_REFRESH_DYNAMIC, NULL }, -#endif - -#if CONFIG_CODEC == SWCODEC - { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL }, -#endif - - { WPS_TOKEN_HAVE_TUNER, "tp", WPS_REFRESH_STATIC, NULL }, -#if CONFIG_TUNER /* Re-uses the 't' and 'T' prefixes, be careful about doubleups */ - { WPS_TOKEN_TUNER_TUNED, "tt", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TUNER_SCANMODE, "tm", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TUNER_STEREO, "ts", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_TUNER_MINFREQ, "ta", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_TUNER_MAXFREQ, "tb", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_TUNER_CURFREQ, "tf", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_PRESET_ID, "Ti", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PRESET_NAME, "Tn", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PRESET_FREQ, "Tf", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_PRESET_COUNT, "Tc", WPS_REFRESH_STATIC, NULL }, - { WPS_TOKEN_HAVE_RDS, "tx", WPS_REFRESH_STATIC, NULL }, -#ifdef HAVE_RDS_CAP - { WPS_TOKEN_RDS_NAME, "ty", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_RDS_TEXT, "tz", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#endif /* CONFIG_TUNER */ - - { WPS_NO_TOKEN, "s", WPS_REFRESH_SCROLL, NULL }, - { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_timeout }, +/* which screen are we parsing for? */ +static enum screen_type curr_screen; -#ifdef HAVE_LCD_BITMAP - { WPS_NO_TOKEN, "we", 0, parse_statusbar_enable }, - { WPS_NO_TOKEN, "wd", 0, parse_statusbar_disable }, - { WPS_TOKEN_DRAW_INBUILTBAR, "wi", WPS_REFRESH_DYNAMIC, parse_statusbar_inbuilt }, +/* the current viewport */ +static struct skin_element *curr_viewport_element; +static struct skin_viewport *curr_vp; - { WPS_NO_TOKEN, "xl", 0, parse_image_load }, +struct line *curr_line; - { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC, - parse_image_display }, +static int follow_lang_direction = 0; - { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, - { WPS_NO_TOKEN, "Fl", 0, parse_font_load }, -#ifdef HAVE_ALBUMART - { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, - { WPS_TOKEN_ALBUMART_DISPLAY, "Cd", WPS_REFRESH_STATIC, parse_albumart_display }, - { WPS_TOKEN_ALBUMART_FOUND, "C", WPS_REFRESH_STATIC, NULL }, -#endif +typedef int (*parse_function)(struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data); - { WPS_VIEWPORT_ENABLE, "Vd", WPS_REFRESH_DYNAMIC, - parse_viewport_display }, - { WPS_TOKEN_UIVIEWPORT_ENABLE, "VI", WPS_REFRESH_STATIC, - parse_viewport_display }, #ifdef HAVE_LCD_BITMAP - { WPS_VIEWPORT_CUSTOMLIST, "Vp", WPS_REFRESH_STATIC, parse_playlistview }, - { WPS_TOKEN_LIST_TITLE_TEXT, "Lt", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_LIST_TITLE_ICON, "Li", WPS_REFRESH_DYNAMIC, NULL }, -#endif -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) - { WPS_TOKEN_VIEWPORT_FGCOLOUR, "Vf", WPS_REFRESH_STATIC, parse_viewportcolour }, - { WPS_TOKEN_VIEWPORT_BGCOLOUR, "Vb", WPS_REFRESH_STATIC, parse_viewportcolour }, -#endif - { WPS_NO_TOKEN, "V", 0, parse_viewport }, - -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) - { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, -#endif -#endif - - { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC, - parse_setting_and_lang }, - { WPS_TOKEN_TRANSLATEDSTRING, "Sx", WPS_REFRESH_STATIC, - parse_setting_and_lang }, - { WPS_TOKEN_LANG_IS_RTL , "Sr", WPS_REFRESH_STATIC, NULL }, - - { WPS_TOKEN_LASTTOUCH, "Tl", WPS_REFRESH_DYNAMIC, parse_timeout }, - { WPS_TOKEN_CURRENT_SCREEN, "cs", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_NO_TOKEN, "T", 0, parse_touchregion }, - - - /* Recording Tokens */ - { WPS_TOKEN_HAVE_RECORDING, "Rp", WPS_REFRESH_STATIC, NULL }, -#ifdef HAVE_RECORDING - { WPS_TOKEN_IS_RECORDING, "Rr", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_FREQ, "Rf", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_ENCODER, "Re", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_BITRATE, "Rb", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_MONO, "Rm", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_SECONDS, "Rs", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_MINUTES, "Rn", WPS_REFRESH_DYNAMIC, NULL }, - { WPS_TOKEN_REC_HOURS, "Rh", WPS_REFRESH_DYNAMIC, NULL }, -#endif - { WPS_TOKEN_UNKNOWN, "", 0, NULL } - /* the array MUST end with an empty string (first char is \0) */ -}; - - /* add a skin_token_list item to the list chain. ALWAYS appended because some of the * chains require the order to be kept. */ @@ -459,7 +116,6 @@ static void add_to_ll_chain(struct skin_token_list **list, struct skin_token_lis } /* traverse the image linked-list for an image */ -#ifdef HAVE_LCD_BITMAP struct gui_img* find_image(char label, struct wps_data *data) { struct skin_token_list *list = data->images; @@ -478,10 +134,10 @@ struct gui_img* find_image(char label, struct wps_data *data) /* traverse the viewport linked list for a viewport */ struct skin_viewport* find_viewport(char label, struct wps_data *data) { - struct skin_token_list *list = data->viewports; + struct skin_element *list = data->tree; while (list) { - struct skin_viewport *vp = (struct skin_viewport *)list->token->value.data; + struct skin_viewport *vp = (struct skin_viewport *)list->data; if (vp->label == label) return vp; list = list->next; @@ -489,6 +145,7 @@ struct skin_viewport* find_viewport(char label, struct wps_data *data) return NULL; } +#ifdef HAVE_LCD_BITMAP /* create and init a new wpsll item. * passing NULL to token will alloc a new one. @@ -498,9 +155,10 @@ struct skin_viewport* find_viewport(char label, struct wps_data *data) static struct skin_token_list *new_skin_token_list_item(struct wps_token *token, void* token_data) { - struct skin_token_list *llitem = skin_buffer_alloc(sizeof(struct skin_token_list)); + struct skin_token_list *llitem = + (struct skin_token_list *)skin_buffer_alloc(sizeof(struct skin_token_list)); if (!token) - token = skin_buffer_alloc(sizeof(struct wps_token)); + token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token)); if (!llitem || !token) return NULL; llitem->next = NULL; @@ -510,108 +168,36 @@ static struct skin_token_list *new_skin_token_list_item(struct wps_token *token, return llitem; } -/* Returns the number of chars that should be skipped to jump - immediately after the first eol, i.e. to the start of the next line */ -static int skip_end_of_line(const char *wps_bufptr) -{ - line_number++; - int skip = 0; - while(*(wps_bufptr + skip) != '\n') - skip++; - return ++skip; -} - -/* Starts a new subline in the current line during parsing */ -static bool skin_start_new_subline(struct skin_line *line, int curr_token) -{ - struct skin_subline *subline = skin_buffer_alloc(sizeof(struct skin_subline)); - if (!subline) - return false; - - subline->first_token_idx = curr_token; - subline->next = NULL; - - subline->line_type = 0; - subline->time_mult = 0; - - line->curr_subline->last_token_idx = curr_token-1; - line->curr_subline->next = subline; - line->curr_subline = subline; - return true; -} - -static bool skin_start_new_line(struct skin_viewport *vp, int curr_token) +static int parse_statusbar_tags(struct skin_element* element, + struct wps_token *token, + struct wps_data *wps_data) { - struct skin_line *line = skin_buffer_alloc(sizeof(struct skin_line)); - struct skin_subline *subline = NULL; - if (!line) - return false; - - /* init the subline */ - subline = &line->sublines; - subline->first_token_idx = curr_token; - subline->next = NULL; - subline->line_type = 0; - subline->time_mult = 0; - - /* init the new line */ - line->curr_subline = &line->sublines; - line->next = NULL; - line->subline_expire_time = 0; - - /* connect to curr_line and vp pointers. - * 1) close the previous lines subline - * 2) connect to vp pointer - * 3) connect to curr_line global pointer - */ - if (curr_line) + (void)element; + if (token->type == SKIN_TOKEN_DRAW_INBUILTBAR) { - curr_line->curr_subline->last_token_idx = curr_token - 1; - curr_line->next = line; - curr_line->curr_subline = NULL; + token->value.data = (void*)&curr_vp->vp; } - curr_line = line; - if (!vp->lines) - vp->lines = line; - return true; -} - -#ifdef HAVE_LCD_BITMAP - -static int parse_statusbar_enable(const char *wps_bufptr, - struct wps_token *token, - struct wps_data *wps_data) -{ - (void)token; /* Kill warnings */ - wps_data->wps_sb_tag = true; - wps_data->show_sb_on_wps = true; - struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data); - viewport_set_defaults(&default_vp->vp, curr_screen); - default_vp->vp.font = FONT_UI; - return skip_end_of_line(wps_bufptr); -} - -static int parse_statusbar_disable(const char *wps_bufptr, - struct wps_token *token, - struct wps_data *wps_data) -{ - (void)token; /* Kill warnings */ - wps_data->wps_sb_tag = true; - wps_data->show_sb_on_wps = false; - struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data); - viewport_set_fullscreen(&default_vp->vp, curr_screen); - default_vp->vp.font = FONT_UI; - return skip_end_of_line(wps_bufptr); -} - -static int parse_statusbar_inbuilt(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data) -{ - (void)wps_data; - token->value.data = (void*)&curr_vp->vp; - return skip_end_of_line(wps_bufptr); + else + { + struct skin_element *def_vp = wps_data->tree; + struct skin_viewport *default_vp = def_vp->data; + if (def_vp->params_count == 0) + { + wps_data->wps_sb_tag = true; + wps_data->show_sb_on_wps = (token->type == SKIN_TOKEN_ENABLE_THEME); + } + if (wps_data->show_sb_on_wps) + { + viewport_set_defaults(&default_vp->vp, curr_screen); + } + else + { + viewport_set_fullscreen(&default_vp->vp, curr_screen); + } + } + return 0; } - + static int get_image_id(int c) { if(c >= 'a' && c <= 'z') @@ -625,32 +211,20 @@ static int get_image_id(int c) char *get_image_filename(const char *start, const char* bmpdir, char *buf, int buf_size) { - const char *end = start; - int bmpdirlen = strlen(bmpdir); - - while (*end && *end != ',' && *end != ')') - end++; - if ( !end || (end - start) >= (buf_size - bmpdirlen - 2) ) - { - buf[0] = '\0'; - return NULL; - } - - strcpy(buf, bmpdir); - buf[bmpdirlen] = '/'; - memcpy( &buf[bmpdirlen + 1], start, end - start); - buf[bmpdirlen + 1 + end - start] = 0; - + snprintf(buf, buf_size, "%s/%s", bmpdir, start); + return buf; } -static int parse_image_display(const char *wps_bufptr, +static int parse_image_display(struct skin_element *element, struct wps_token *token, struct wps_data *wps_data) { - char label = wps_bufptr[1]; + char *text = element->params[0].data.text; + char label = text[0]; + char sublabel = text[1]; int subimage; - struct gui_img *img;; + struct gui_img *img; /* sanity check */ img = find_image(label, wps_data); @@ -660,7 +234,7 @@ static int parse_image_display(const char *wps_bufptr, return WPS_ERROR_INVALID_PARAM; } - if ((subimage = get_image_id(wps_bufptr[2])) != -1) + if ((subimage = get_image_id(sublabel)) != -1) { if (subimage >= img->num_subimages) return WPS_ERROR_INVALID_PARAM; @@ -674,32 +248,24 @@ static int parse_image_display(const char *wps_bufptr, } } -static int parse_image_load(const char *wps_bufptr, +static int parse_image_load(struct skin_element *element, struct wps_token *token, struct wps_data *wps_data) { - const char *ptr = wps_bufptr; const char* filename; const char* id; int x,y; struct gui_img *img; - /* format: %x|n|filename.bmp|x|y| - or %xl|n|filename.bmp|x|y| - or %xl|n|filename.bmp|x|y|num_subimages| + /* format: %x(n,filename.bmp,x,y) + or %xl(n,filename.bmp,x,y) + or %xl(n,filename.bmp,x,y,num_subimages) */ - if (*ptr != '(') - return WPS_ERROR_INVALID_PARAM; - - ptr++; - - if (!(ptr = parse_list("ssdd", NULL, ',', ptr, &id, &filename, &x, &y))) - return WPS_ERROR_INVALID_PARAM; - - /* Check there is a terminating ) */ - if (*ptr != ')' && *ptr != ',') - return WPS_ERROR_INVALID_PARAM; + id = element->params[0].data.text; + filename = element->params[1].data.text; + x = element->params[2].data.number; + y = element->params[3].data.number; /* check the image number and load state */ if(find_image(*id, wps_data)) @@ -707,7 +273,7 @@ static int parse_image_load(const char *wps_bufptr, /* Invalid image ID */ return WPS_ERROR_INVALID_PARAM; } - img = skin_buffer_alloc(sizeof(struct gui_img)); + img = (struct gui_img*)skin_buffer_alloc(sizeof(struct gui_img)); if (!img) return WPS_ERROR_INVALID_PARAM; /* save a pointer to the filename */ @@ -717,62 +283,44 @@ static int parse_image_load(const char *wps_bufptr, img->y = y; img->num_subimages = 1; img->always_display = false; + // img->just_drawn = false; + img->display = -1; /* save current viewport */ img->vp = &curr_vp->vp; - if (token->type == WPS_TOKEN_IMAGE_DISPLAY) + if (token->type == SKIN_TOKEN_IMAGE_DISPLAY) { img->always_display = true; } - else if (*ptr == ',') + else if (element->params_count == 5) { - /* Parse the (optional) number of sub-images */ - ptr++; - img->num_subimages = atoi(ptr); + img->num_subimages = element->params[4].data.number; if (img->num_subimages <= 0) return WPS_ERROR_INVALID_PARAM; - /* Check there is a terminating ) */ - while(isdigit(*ptr)) - ptr++; - if (*ptr != ')') - return WPS_ERROR_INVALID_PARAM; } - struct skin_token_list *item = new_skin_token_list_item(NULL, img); + struct skin_token_list *item = + (struct skin_token_list *)new_skin_token_list_item(NULL, img); if (!item) return WPS_ERROR_INVALID_PARAM; add_to_ll_chain(&wps_data->images, item); - /* Skip the rest of the line */ - return skip_end_of_line(wps_bufptr); + return 0; } struct skin_font { int id; /* the id from font_load */ char *name; /* filename without path and extension */ }; static struct skin_font skinfonts[MAXUSERFONTS]; -static int parse_font_load(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data) +static int parse_font_load(struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data) { (void)wps_data; (void)token; - const char *ptr = wps_bufptr; - int id; - char *filename; - - if (*ptr != '(') - return WPS_ERROR_INVALID_PARAM; - - ptr++; - - if (!(ptr = parse_list("ds", NULL, ',', ptr, &id, &filename))) - return WPS_ERROR_INVALID_PARAM; - - /* Check there is a terminating ) */ - if (*ptr != ')') - return WPS_ERROR_INVALID_PARAM; - - if (id <= FONT_UI || id >= MAXFONTS-1) - return WPS_ERROR_INVALID_PARAM; + int id = element->params[0].data.number; + char *filename = element->params[1].data.text; + char *ptr; + #if defined(DEBUG) || defined(SIMULATOR) if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL) { @@ -782,286 +330,65 @@ static int parse_font_load(const char *wps_bufptr, /* make sure the filename contains .fnt, * we dont actually use it, but require it anyway */ ptr = strchr(filename, '.'); - if (!ptr || strncmp(ptr, ".fnt)", 5)) + if (!ptr || strncmp(ptr, ".fnt", 4)) return WPS_ERROR_INVALID_PARAM; skinfonts[id-FONT_FIRSTUSERFONT].id = -1; skinfonts[id-FONT_FIRSTUSERFONT].name = filename; - return skip_end_of_line(wps_bufptr); + return 0; } -static int parse_viewport_display(const char *wps_bufptr, - struct wps_token *token, - struct wps_data *wps_data) -{ - (void)wps_data; - char letter = wps_bufptr[1]; - - if (letter < 'a' || letter > 'z') - { - /* invalid viewport tag */ - return WPS_ERROR_INVALID_PARAM; - } - token->value.i = letter; - return 3; -} - #ifdef HAVE_LCD_BITMAP -static int parse_playlistview_text(struct playlistviewer *viewer, - enum info_line_type line, char* text) -{ - int cur_string = 0; - const struct wps_tag *tag; - int taglen = 0; - const char *start = text; - if (*text != ',') - return -1; - text++; - viewer->lines[line].count = 0; - viewer->lines[line].scroll = false; - while (*text != ',' && *text != ')') - { - if (*text == '%') /* it is a token of some type */ - { - text++; - taglen = 0; - switch(*text) - { - case '%': - case '<': - case '|': - case '>': - case ';': - case '#': - case '(': - case ')': - case ',': - /* escaped characters */ - viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER; - viewer->lines[line].strings[cur_string][0] = *text; - viewer->lines[line].strings[cur_string++][1] = '\0'; - text++; - break; - default: - for (tag = all_tags; - strncmp(text, tag->name, strlen(tag->name)) != 0; - tag++) ; - /* %s isnt stored as a tag so manually check for it */ - if (tag->type == WPS_NO_TOKEN) - { - if (!strncmp(tag->name, "s", 1)) - { - viewer->lines[line].scroll = true; - taglen = 1; - } - } - else if (tag->type == WPS_TOKEN_UNKNOWN) - { - int i = 0; - /* just copy the string */ - viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING; - while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%') - { - viewer->lines[line].strings[cur_string][i] = text[i]; - i++; - } - viewer->lines[line].strings[cur_string][i] = '\0'; - cur_string++; - taglen = i; - } - else - { - if (tag->parse_func) - { - /* unsupported tag, reject */ - return -1; - } - taglen = strlen(tag->name); - viewer->lines[line].tokens[viewer->lines[line].count++] = tag->type; - } - text += taglen; - } - } - else - { - /* regular string */ - int i = 0; - /* just copy the string */ - viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING; - while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%') - { - viewer->lines[line].strings[cur_string][i] = text[i]; - i++; - } - viewer->lines[line].strings[cur_string][i] = '\0'; - cur_string++; - text += i; - } - } - return text - start; -} -static int parse_playlistview(const char *wps_bufptr, - struct wps_token *token, struct wps_data *wps_data) +static int parse_playlistview(struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data) { (void)wps_data; - /* %Vp|||info line text|no info text| */ - struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer)); - char *ptr = strchr(wps_bufptr, '('); - int length; - if (!viewer || !ptr) + struct playlistviewer *viewer = + (struct playlistviewer *)skin_buffer_alloc(sizeof(struct playlistviewer)); + if (!viewer) return WPS_ERROR_INVALID_PARAM; viewer->vp = &curr_vp->vp; viewer->show_icons = true; - viewer->start_offset = atoi(ptr+1); + viewer->start_offset = element->params[0].data.number; + viewer->lines[0] = element->params[1].data.code; + viewer->lines[1] = element->params[2].data.code; + token->value.data = (void*)viewer; - ptr = strchr(ptr+1, ','); - length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr); - if (length < 0) - return WPS_ERROR_INVALID_PARAM; - length = parse_playlistview_text(viewer, TRACK_HAS_NO_INFO, ptr+length); - if (length < 0) - return WPS_ERROR_INVALID_PARAM; - - return skip_end_of_line(wps_bufptr); + + return 0; } #endif -static int parse_viewport(const char *wps_bufptr, - struct wps_token *token, - struct wps_data *wps_data) -{ - (void)token; /* Kill warnings */ - const char *ptr = wps_bufptr; - - struct skin_viewport *skin_vp = skin_buffer_alloc(sizeof(struct skin_viewport)); - - /* check for the optional letter to signify its a hideable viewport */ - /* %Vl|