Index: apps/gui/wps/wps_buffer.c =================================================================== --- apps/gui/wps/wps_buffer.c (revision 0) +++ apps/gui/wps/wps_buffer.c (revision 0) @@ -0,0 +1,87 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wps_parser.c 19880 2009-01-29 20:49:43Z mcuelenaere $ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * Copyright (C) 2009 Jonathan Gordon + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "config.h" +#include "buffer.h" +#include "settings.h" + +/* WPS buffer management. + * This module is used to allocate space in a single global WPS buffer for + * tokens for both/all screens. + * + * This is mostly just copy/paste from firmware/buffer.c + */ + +static unsigned char *buffer_start = NULL, *buffer_pos = NULL; +static size_t buf_size; + +void wps_buffer_init(void) +{ + if (buffer_start == NULL) + { + buf_size = /* global_settings.wps_buf_size */ 0x200000; // 2MB for now + buffer_start = buffer_alloc(buf_size); + buffer_pos = buffer_start; + } + else + { + /* reset the buffer.... */ + buffer_pos = buffer_start; + } +} + +/* get the number of bytes currently being used */ +size_t wps_buffer_usage(void) +{ + return buffer_pos-buffer_start; +} + +/* Allocate size bytes from the buffer */ +void* wps_buffer_alloc(size_t size) +{ + void* retval = buffer_pos; + if (wps_buffer_usage()+size >= buf_size) + { + return NULL; + } + buffer_pos += size; + /* 32-bit aligned */ + buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); + return retval; +} + +void* wps_buffer_grab(size_t *freespace) +{ + *freespace = buf_size - wps_buffer_usage(); + return buffer_pos; +} + +void wps_buffer_increment(size_t used) +{ + buffer_pos += used; + /* 32-bit aligned */ + buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); +} + Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (revision 19918) +++ apps/gui/gwps-common.c (working copy) @@ -331,8 +331,12 @@ #if LCD_DEPTH > 1 if (gui_wps[i].display->depth > 1) { - gui_wps[i].data->viewports[0].vp.fg_pattern = gui_wps[i].display->get_foreground(); - gui_wps[i].data->viewports[0].vp.bg_pattern = gui_wps[i].display->get_background(); + struct wps_viewport *vp = find_viewport(gui_wps[i].data, '\0'); + if (vp) + { + vp->vp.fg_pattern = gui_wps[i].display->get_foreground(); + vp->vp.bg_pattern = gui_wps[i].display->get_background(); + } } #endif #endif @@ -504,15 +508,40 @@ pb->x, pb->x + pb->width, pb->y+1, pb->height-2); } +struct gui_img* find_img(struct wps_data *wps_data, char id) +{ + struct wpsll *llitem = wps_data->images; + struct gui_img *img; + for(llitem = wps_data->images; llitem; llitem = llitem->next) + { + img = (struct gui_img *)llitem->token->value.data; + if (img->id == id) + return img; + } + return NULL; +} +struct wps_viewport* find_viewport(struct wps_data *wps_data, char id) +{ + struct wpsll *llitem = wps_data->viewports; + struct wps_viewport *vp; + for(llitem = wps_data->viewports; llitem; llitem = llitem->next) + { + vp = (struct wps_viewport *)llitem->token->value.data; + if (vp->label == id) + return vp; + } + return NULL; +} /* clears the area where the image was shown */ static void clear_image_pos(struct gui_wps *gwps, int n) { if(!gwps) return; struct wps_data *data = gwps->data; + struct gui_img *img = find_img(data, n); gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - gwps->display->fillrect(data->img[n].x, data->img[n].y, - data->img[n].bm.width, data->img[n].subimage_height); + gwps->display->fillrect(img->x, img->y, + img->bm.width, img->subimage_height); gwps->display->set_drawmode(DRMODE_SOLID); } @@ -520,26 +549,27 @@ { struct screen *display = gwps->display; struct wps_data *data = gwps->data; - if(data->img[n].always_display) + struct gui_img *img = find_img(data, n); + if(img->always_display) display->set_drawmode(DRMODE_FG); else display->set_drawmode(DRMODE_SOLID); #if LCD_DEPTH > 1 - if(data->img[n].bm.format == FORMAT_MONO) { + if(img->bm.format == FORMAT_MONO) { #endif - display->mono_bitmap_part(data->img[n].bm.data, - 0, data->img[n].subimage_height * subimage, - data->img[n].bm.width, data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].subimage_height); + display->mono_bitmap_part(img->bm.data, + 0, img->subimage_height * subimage, + img->bm.width, img->x, + img->y, img->bm.width, + img->subimage_height); #if LCD_DEPTH > 1 } else { - display->transparent_bitmap_part((fb_data *)data->img[n].bm.data, - 0, data->img[n].subimage_height * subimage, - data->img[n].bm.width, data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].subimage_height); + display->transparent_bitmap_part((fb_data *)img->bm.data, + 0, img->subimage_height * subimage, + img->bm.width, img->x, + img->y, img->bm.width, + img->subimage_height); } #endif } @@ -549,20 +579,20 @@ if(!gwps || !gwps->data || !gwps->display) return; - int n; struct wps_data *data = gwps->data; struct screen *display = gwps->display; - - for (n = 0; n < MAX_IMAGES; n++) + struct wpsll *llitem; + for ( llitem = data->images; llitem; llitem = llitem->next) { - if (data->img[n].loaded) + struct gui_img *img = (struct gui_img*)llitem->token->value.data; + if (img->loaded) { - if (data->img[n].display >= 0) + if (img->display >= 0) { - wps_draw_image(gwps, n, data->img[n].display); - } else if (data->img[n].always_display && data->img[n].vp == vp) + wps_draw_image(gwps, img->id, img->display); + } else if (img->always_display && img->vp == vp) { - wps_draw_image(gwps, n, 0); + wps_draw_image(gwps, img->id, 0); } } } @@ -804,7 +834,7 @@ return &(token->value.c); case WPS_TOKEN_STRING: - return data->strings[token->value.i]; + return token->value.data; case WPS_TOKEN_TRACK_TIME_ELAPSED: format_time(buf, buf_size, @@ -1558,12 +1588,12 @@ #ifdef HAVE_LCD_BITMAP case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: { - struct gui_img *img = data->img; int n = data->tokens[i].value.i & 0xFF; + struct gui_img *img = find_img(data, n); int subimage = data->tokens[i].value.i >> 8; - if (n >= 0 && n < MAX_IMAGES && img[n].loaded) - img[n].display = subimage; + if (img->loaded) + img->display = subimage; break; } #endif @@ -1606,20 +1636,11 @@ break; case WPS_VIEWPORT_ENABLE: { - char label = data->tokens[i].value.i; - int j; + struct wps_viewport *thisvp = data->tokens[i].value.data; char temp = VP_DRAW_HIDEABLE; - for(j=0;jnum_viewports;j++) - { - temp = VP_DRAW_HIDEABLE; - if ((data->viewports[j].hidden_flags&VP_DRAW_HIDEABLE) && - (data->viewports[j].label == label)) - { - if (data->viewports[j].hidden_flags&VP_DRAW_WASHIDDEN) - temp |= VP_DRAW_WASHIDDEN; - data->viewports[j].hidden_flags = temp; - } - } + if (thisvp->hidden_flags&VP_DRAW_WASHIDDEN) + temp |= VP_DRAW_WASHIDDEN; + thisvp->hidden_flags = temp; } break; default: @@ -1942,7 +1963,7 @@ if(!gwps || !data || !state || !display) return false; - int v, line, i, subline_idx; + int line, i, subline_idx; unsigned char flags; char linebuf[MAX_PATH]; unsigned char vp_refresh_mode; @@ -1970,7 +1991,8 @@ /* reset to first subline if refresh all flag is set */ if (refresh_mode == WPS_REFRESH_ALL) { - display->set_viewport(&data->viewports[0].vp); + struct wps_viewport *wvp = find_viewport(data, '\0'); + display->set_viewport(&wvp->vp); display->clear_viewport(); for (i = 0; i <= data->num_lines; i++) @@ -1996,50 +2018,55 @@ state->ff_rewind_count = ffwd_offset; /* disable any viewports which are conditionally displayed */ - for (v = 0; v < data->num_viewports; v++) + struct wpsll *viewportll; + for(viewportll=data->viewports; viewportll; viewportll = viewportll->next) { - if (data->viewports[v].hidden_flags&VP_DRAW_HIDEABLE) + struct wps_viewport *wvp = viewportll->token->value.data; + if (wvp->hidden_flags&VP_DRAW_HIDEABLE) { - if (data->viewports[v].hidden_flags&VP_DRAW_HIDDEN) - data->viewports[v].hidden_flags |= VP_DRAW_WASHIDDEN; + if (wvp->hidden_flags&VP_DRAW_HIDDEN) + wvp->hidden_flags |= VP_DRAW_WASHIDDEN; else - data->viewports[v].hidden_flags |= VP_DRAW_HIDDEN; + wvp->hidden_flags |= VP_DRAW_HIDDEN; } } - for (v = 0; v < data->num_viewports; v++) + for(viewportll=data->viewports; viewportll; viewportll = viewportll->next) { - display->set_viewport(&data->viewports[v].vp); + struct wps_viewport *wvp = viewportll->token->value.data; + display->set_viewport(&wvp->vp); vp_refresh_mode = refresh_mode; #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ - for (i = 0; i < MAX_IMAGES; i++) + struct wpsll *llitem; + for ( llitem = data->images; llitem; llitem = llitem->next) { - data->img[i].display = -1; + struct gui_img *img = (struct gui_img*)llitem->token->value.data; + img->display = -1; } #endif /* dont redraw the viewport if its disabled */ - if ((data->viewports[v].hidden_flags&VP_DRAW_HIDDEN)) + if ((wvp->hidden_flags&VP_DRAW_HIDDEN)) { - if (!(data->viewports[v].hidden_flags&VP_DRAW_WASHIDDEN)) - display->scroll_stop(&data->viewports[v].vp); - data->viewports[v].hidden_flags |= VP_DRAW_WASHIDDEN; + if (!(wvp->hidden_flags&VP_DRAW_WASHIDDEN)) + display->scroll_stop(&wvp->vp); + wvp->hidden_flags |= VP_DRAW_WASHIDDEN; continue; } - else if (((data->viewports[v].hidden_flags& + else if (((wvp->hidden_flags& (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) { vp_refresh_mode = WPS_REFRESH_ALL; - data->viewports[v].hidden_flags = VP_DRAW_HIDEABLE; + wvp->hidden_flags = VP_DRAW_HIDEABLE; } if (vp_refresh_mode == WPS_REFRESH_ALL) { display->clear_viewport(); } - for (line = data->viewports[v].first_line; - line <= data->viewports[v].last_line; line++) + for (line = wvp->first_line; + line <= wvp->last_line; line++) { memset(linebuf, 0, sizeof(linebuf)); update_line = false; @@ -2065,8 +2092,8 @@ /* the peakmeter should be alone on its line */ update_line = false; - int h = font_get(data->viewports[v].vp.font)->height; - int peak_meter_y = (line - data->viewports[v].first_line)* h; + int h = font_get(wvp->vp.font)->height; + int peak_meter_y = (line - wvp->first_line)* h; /* The user might decide to have the peak meter in the last line so that it is only displayed if no status bar is @@ -2103,17 +2130,17 @@ viewport there will be a blank line. To get around this we dont allow any actual drawing to happen in the deault vp if other vp's are defined */ - ((data->num_viewports>1 && v!=0) || data->num_viewports == 1)) + ((viewportll->next && wvp->label!='\0') || !viewportll->next)) { if (flags & WPS_REFRESH_SCROLL) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((vp_refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) - write_line(display, &align, line - data->viewports[v].first_line, true); + write_line(display, &align, line - wvp->first_line, true); } else - write_line(display, &align, line - data->viewports[v].first_line, false); + write_line(display, &align, line - wvp->first_line, false); } } @@ -2121,11 +2148,11 @@ /* progressbar */ if (vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) { - if (data->viewports[v].pb) - draw_progressbar(gwps, data->viewports[v].pb); + if (wvp->pb) + draw_progressbar(gwps, wvp->pb); } /* Now display any images in this viewport */ - wps_display_images(gwps, &data->viewports[v].vp); + wps_display_images(gwps, &wvp->vp); #endif } Index: apps/gui/wps_debug.c =================================================================== --- apps/gui/wps_debug.c (revision 19916) +++ apps/gui/wps_debug.c (working copy) @@ -43,7 +43,7 @@ return next ? "next " : ""; } -static char *get_token_desc(struct wps_token *token, struct wps_data *data, +static char *get_token_desc(struct wps_token *token, char *buf, int bufsize) { bool next = token->next; @@ -65,7 +65,7 @@ case WPS_TOKEN_STRING: snprintf(buf, bufsize, "String '%s'", - data->strings[token->value.i]); + token->value.data); break; #ifdef HAVE_LCD_BITMAP @@ -456,7 +456,7 @@ /* Dump parsed WPS */ for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++) { - get_token_desc(token, data, buf, sizeof(buf)); + get_token_desc(token, buf, sizeof(buf)); switch(token->type) { @@ -502,26 +502,30 @@ if (wps_verbose_level > 0) { - DEBUGF("Number of viewports : %d\n", data->num_viewports); - for (v = 0; v < data->num_viewports; v++) + struct wpsll *ll; + for (v=0, ll=data->viewports; ll; ll = ll->next, v++) { - DEBUGF("vp %d: First line: %d\n", v, data->viewports[v].first_line); - DEBUGF("vp %d: Last line: %d\n", v, data->viewports[v].last_line); + struct wps_viewport *vp = ll->token->value.data; + DEBUGF("vp %d: First line: %d\n", v, vp->first_line); + DEBUGF("vp %d: Last line: %d\n", v, vp->last_line); } DEBUGF("Number of sublines : %d\n", data->num_sublines); DEBUGF("Number of tokens : %d\n", data->num_tokens); + DEBUGF("Buffer Usage: %ld\n", wps_buffer_usage()); DEBUGF("\n"); } if (wps_verbose_level > 1) { - for (v = 0; v < data->num_viewports; v++) + struct wpsll *ll; + for (v=0, ll=data->viewports; ll; ll = ll->next, v++) { - DEBUGF("Viewport %d - +%d+%d (%dx%d)\n",v,data->viewports[v].vp.x, - data->viewports[v].vp.y, - data->viewports[v].vp.width, - data->viewports[v].vp.height); - for (i = data->viewports[v].first_line, line = &data->lines[data->viewports[v].first_line]; i <= data->viewports[v].last_line; i++,line++) + struct wps_viewport *vp = ll->token->value.data; + DEBUGF("Viewport %d - +%d+%d (%dx%d)\n",v,vp->vp.x, + vp->vp.y, + vp->vp.width, + vp->vp.height); + for (i = vp->first_line, line = &data->lines[vp->first_line]; i <= vp->last_line; i++,line++) { DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n", i, line->num_sublines, line->first_subline_idx); @@ -544,36 +548,12 @@ } } } + DEBUGF("Buffer Usage: %ld\n", wps_buffer_usage()); DEBUGF("\n"); } } -static void print_wps_strings(struct wps_data *data) -{ - int i, len, total_len = 0, buf_used = 0; - - if (wps_verbose_level > 1) DEBUGF("Strings:\n"); - for (i = 0; i < data->num_strings; i++) - { - len = strlen(data->strings[i]); - total_len += len; - buf_used += len + 1; - if (wps_verbose_level > 1) - DEBUGF("%2d: (%2d) '%s'\n", i, len, data->strings[i]); - } - if (wps_verbose_level > 1) DEBUGF("\n"); - - if (wps_verbose_level > 0) - { - DEBUGF("Number of unique strings: %d (max: %d)\n", - data->num_strings, WPS_MAX_STRINGS); - DEBUGF("Total string length: %d\n", total_len); - DEBUGF("String buffer used: %d out of %d bytes\n", - buf_used, STRING_BUFFER_SIZE); - DEBUGF("\n"); - } -} #endif void print_debug_info(struct wps_data *data, enum wps_parse_error fail, int line) @@ -582,7 +562,6 @@ if (debug_wps && wps_verbose_level) { dump_wps_tokens(data); - print_wps_strings(data); print_line_info(data); } #endif /* SIMULATOR */ @@ -609,7 +588,7 @@ case PARSE_FAIL_INVALID_CHAR: DEBUGF("ERR: Unexpected conditional char after token %d: \"%s\"", data->num_tokens-1, - get_token_desc(&data->tokens[data->num_tokens-1], data, + get_token_desc(&data->tokens[data->num_tokens-1], buf, sizeof(buf)) ); break; @@ -617,7 +596,7 @@ case PARSE_FAIL_COND_SYNTAX_ERROR: DEBUGF("ERR: Conditional syntax error after token %d: \"%s\"", data->num_tokens-1, - get_token_desc(&data->tokens[data->num_tokens-1], data, + get_token_desc(&data->tokens[data->num_tokens-1], buf, sizeof(buf)) ); break; @@ -625,7 +604,7 @@ case PARSE_FAIL_COND_INVALID_PARAM: DEBUGF("ERR: Invalid parameter list for token %d: \"%s\"", data->num_tokens, - get_token_desc(&data->tokens[data->num_tokens], data, + get_token_desc(&data->tokens[data->num_tokens], buf, sizeof(buf)) ); break; Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 19916) +++ apps/gui/gwps.h (working copy) @@ -56,9 +56,28 @@ #endif /* HAVE_ALBUMART */ /* wps_data*/ +struct wps_token { + unsigned char type; /* enough to store the token type */ + /* Whether the tag (e.g. track name or the album) refers the + current or the next song (false=current, true=next) */ + bool next; + + union { + char c; + unsigned int i; + void *data; /* pointer into global wps buffer */ + } value; +}; + +struct wpsll { + struct wps_token *token; + struct wpsll *next; +}; + #ifdef HAVE_LCD_BITMAP struct gui_img{ + short id; struct bitmap bm; struct viewport* vp; /* The viewport to display this image in */ short int x; /* x-pos */ @@ -90,21 +109,10 @@ #ifdef HAVE_LCD_BITMAP -#define MAX_IMAGES (26*2) /* a-z and A-Z */ -#define MAX_PROGRESSBARS 3 - -/* The image buffer is big enough to store one full-screen native bitmap, - plus two full-screen mono bitmaps. */ - -#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ - + (2*LCD_HEIGHT*LCD_WIDTH/8)) - #define WPS_MAX_VIEWPORTS 24 #define WPS_MAX_LINES ((LCD_HEIGHT/5+1) * 2) #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) #define WPS_MAX_TOKENS 1024 -#define WPS_MAX_STRINGS 128 -#define STRING_BUFFER_SIZE 1024 #define WPS_MAX_COND_LEVEL 10 #else @@ -113,8 +121,6 @@ #define WPS_MAX_LINES 2 #define WPS_MAX_SUBLINES 12 #define WPS_MAX_TOKENS 64 -#define WPS_MAX_STRINGS 32 -#define STRING_BUFFER_SIZE 64 #define WPS_MAX_COND_LEVEL 5 #endif @@ -296,19 +302,8 @@ WPS_TOKEN_SETTING, }; -struct wps_token { - unsigned char type; /* enough to store the token type */ - /* Whether the tag (e.g. track name or the album) refers the - current or the next song (false=current, true=next) */ - bool next; - union { - char c; - unsigned short i; - } value; -}; - /* Description of a subline on the WPS */ struct wps_subline { @@ -363,16 +358,14 @@ struct wps_data { #ifdef HAVE_LCD_BITMAP - struct gui_img img[MAX_IMAGES]; - unsigned char img_buf[IMG_BUFSIZE]; - unsigned char* img_buf_ptr; - int img_buf_free; bool wps_sb_tag; bool show_sb_on_wps; - struct progressbar progressbar[MAX_PROGRESSBARS]; - short progressbar_count; + struct wpsll *images; + struct wpsll *progressbars; + struct wps_token *backdrop; + bool peak_meter_enabled; #ifdef HAVE_ALBUMART @@ -401,9 +394,7 @@ the index of the line being parsed. */ int num_lines; - /* Number of viewports in the WPS */ - int num_viewports; - struct wps_viewport viewports[WPS_MAX_VIEWPORTS]; + struct wpsll *viewports; struct wps_line lines[WPS_MAX_LINES]; @@ -417,10 +408,8 @@ int num_tokens; struct wps_token tokens[WPS_MAX_TOKENS]; - char string_buffer[STRING_BUFFER_SIZE]; - char *strings[WPS_MAX_STRINGS]; - int num_strings; - + struct wpsll *strings; + bool wps_loaded; /* tick the volume button was last pressed */ @@ -507,4 +496,16 @@ bool gui_sync_wps_uses_albumart(void); #endif + +struct gui_img* find_img(struct wps_data *wps_data, char id); /* in gwps-common.c */ +struct wps_viewport* find_viewport(struct wps_data *wps_data, char id); + +/* wps_buffer functions */ + +void wps_buffer_init(void); +void* wps_buffer_alloc(size_t size); +void* wps_buffer_grab(size_t *freespace); +void wps_buffer_increment(size_t used); +size_t wps_buffer_usage(void); + #endif Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 19916) +++ apps/gui/wps_parser.c (working copy) @@ -79,22 +79,9 @@ /* the current line in the file */ static int line; -#ifdef HAVE_LCD_BITMAP +/* the current viewport */ +static struct wps_viewport *curr_vp; -#if LCD_DEPTH > 1 -#define MAX_BITMAPS (MAX_IMAGES+MAX_PROGRESSBARS+1) /* WPS images + pbar bitmap + backdrop */ -#else -#define MAX_BITMAPS (MAX_IMAGES+MAX_PROGRESSBARS) /* WPS images + pbar bitmap */ -#endif - -#define PROGRESSBAR_BMP MAX_IMAGES -#define BACKDROP_BMP (MAX_BITMAPS-1) - -/* pointers to the bitmap filenames in the WPS source */ -static const char *bmp_names[MAX_BITMAPS]; - -#endif /* HAVE_LCD_BITMAP */ - #if defined(DEBUG) || defined(SIMULATOR) /* debugging function */ extern void print_debug_info(struct wps_data *data, int fail, int line); @@ -342,6 +329,19 @@ /* the array MUST end with an empty string (first char is \0) */ }; +static void add_to_ll_chain(struct wpsll **list, struct wpsll *item) +{ + if (*list == NULL) + *list = item; + else + { + struct wpsll *t = *list; + while (t->next) + t = t->next; + t->next = item; + } +} + /* 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) @@ -368,12 +368,13 @@ struct wps_data *wps_data) { (void)token; /* Kill warnings */ + struct wps_viewport *vp = find_viewport(wps_data, '\0'); wps_data->wps_sb_tag = true; wps_data->show_sb_on_wps = true; - if (wps_data->viewports[0].vp.y == 0) + if (vp->vp.y == 0) { - wps_data->viewports[0].vp.y = STATUSBAR_HEIGHT; - wps_data->viewports[0].vp.height -= STATUSBAR_HEIGHT; + vp->vp.y = STATUSBAR_HEIGHT; + vp->vp.height -= STATUSBAR_HEIGHT; } return skip_end_of_line(wps_bufptr); } @@ -383,12 +384,13 @@ struct wps_data *wps_data) { (void)token; /* Kill warnings */ + struct wps_viewport *vp = find_viewport(wps_data, '\0'); wps_data->wps_sb_tag = true; wps_data->show_sb_on_wps = false; - if (wps_data->viewports[0].vp.y == STATUSBAR_HEIGHT) + if (vp->vp.y == STATUSBAR_HEIGHT) { - wps_data->viewports[0].vp.y = 0; - wps_data->viewports[0].vp.height += STATUSBAR_HEIGHT; + vp->vp.y = 0; + vp->vp.height += STATUSBAR_HEIGHT; } return skip_end_of_line(wps_bufptr); } @@ -397,16 +399,19 @@ char* filename, struct bitmap *bm) { + (void)wps_data; int format; + size_t bm_space_avilable; #ifdef HAVE_REMOTE_LCD if (wps_data->remote_wps) format = FORMAT_ANY|FORMAT_REMOTE; else #endif format = FORMAT_ANY|FORMAT_TRANSPARENT; - + bm->data = wps_buffer_grab(&bm_space_avilable); + int ret = read_bmp_file(filename, bm, - wps_data->img_buf_free, + bm_space_avilable, format,NULL); if (ret > 0) @@ -415,8 +420,8 @@ if (ret % 2) ret++; /* Always consume an even number of bytes */ #endif - wps_data->img_buf_ptr += ret; - wps_data->img_buf_free -= ret; + /* let the buffer manager know how much we used */ + wps_buffer_increment(ret); return true; } @@ -459,11 +464,11 @@ struct wps_token *token, struct wps_data *wps_data) { - (void)wps_data; - int n = get_image_id(wps_bufptr[0]); + int n = (wps_bufptr[0]); + struct gui_img *img = find_img(wps_data, n); int subimage; - if (n == -1) + if (n == -1 || !img) { /* invalid picture display tag */ return WPS_ERROR_INVALID_PARAM; @@ -472,7 +477,7 @@ if ((subimage = get_image_id(wps_bufptr[1])) != -1) { /* Sanity check */ - if (subimage >= wps_data->img[n].num_subimages) + if (subimage >= img->num_subimages) return WPS_ERROR_INVALID_PARAM; /* Store sub-image number to display in high bits */ @@ -488,19 +493,21 @@ struct wps_token *token, struct wps_data *wps_data) { - int n; const char *ptr = wps_bufptr; const char *pos; const char* filename; const char* id; const char *newline; int x,y; - + struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll)); + struct gui_img *img = wps_buffer_alloc(sizeof(struct gui_img)); + /* tokens for image lod are not saved, so we need a new copy to be able to link them */ + struct wps_token *tmp_token = wps_buffer_alloc(sizeof(struct wps_token)); + tmp_token->value.data = img; /* 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; @@ -513,28 +520,22 @@ if (*ptr != '|') return WPS_ERROR_INVALID_PARAM; - /* get the image ID */ - n = get_image_id(*id); - - /* check the image number and load state */ - if(n < 0 || n >= MAX_IMAGES || wps_data->img[n].loaded) - { - /* Invalid image ID */ - return WPS_ERROR_INVALID_PARAM; - } - + /* store the image ID */ + img->id = (id[0]); + /* save a pointer to the filename */ - bmp_names[n] = filename; + img->bm.data = (unsigned char*)filename; - wps_data->img[n].x = x; - wps_data->img[n].y = y; + img->x = x; + img->y = y; + img->num_subimages = 1; /* save current viewport */ - wps_data->img[n].vp = &wps_data->viewports[wps_data->num_viewports].vp; + img->vp = &curr_vp->vp; if (token->type == WPS_TOKEN_IMAGE_DISPLAY) { - wps_data->img[n].always_display = true; + img->always_display = true; } else { @@ -543,12 +544,15 @@ newline = strchr(ptr, '\n'); pos = strchr(ptr, '|'); if (pos && pos < newline) - wps_data->img[n].num_subimages = atoi(ptr); + img->num_subimages = atoi(ptr); - if (wps_data->img[n].num_subimages <= 0) + if (img->num_subimages <= 0) return WPS_ERROR_INVALID_PARAM; } - + llitem->token = tmp_token; + llitem->next = NULL; + add_to_ll_chain(&wps_data->images, llitem); + /* Skip the rest of the line */ return skip_end_of_line(wps_bufptr); } @@ -559,13 +563,25 @@ { (void)wps_data; char letter = wps_bufptr[0]; - - if (letter < 'a' || letter > 'z') + struct wps_viewport *vp = find_viewport(wps_data, letter); + /* viewports are regularly mentioned before being setup. + * so if find_viewport() doesnt find one we need to create it first. + * this means in parse_viewport() we need to make sure it hasnt been created yet + * before allocating room on the buffer for one + */ + if (vp == NULL) { + struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll)); + struct wps_viewport *wvp = wps_buffer_alloc(sizeof(struct wps_viewport)); + llitem->token = token; + llitem->next = NULL; + token->value.data = wvp; + wvp->label = letter; + add_to_ll_chain(&wps_data->viewports, llitem); /* invalid viewport tag */ return WPS_ERROR_INVALID_PARAM; } - token->value.i = letter; + token->value.data = vp; return 1; } @@ -578,6 +594,11 @@ struct viewport* vp; int depth; uint32_t set = 0; + struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll)); + struct wps_viewport *wvp = NULL, *prev_vp = curr_vp; + bool add_to_ll = true; + /* tokens for viewport load are not saved, so we need a new copy to be able to link them */ + struct wps_token *tmp_token = NULL; enum { PL_X = 0, PL_Y, @@ -595,15 +616,9 @@ lcd_height = LCD_REMOTE_HEIGHT; } #endif - - if (wps_data->num_viewports >= WPS_MAX_VIEWPORTS) - return WPS_ERROR_INVALID_PARAM; - wps_data->num_viewports++; /* check for the optional letter to signify its a hideable viewport */ /* %Vl|