diff -u -r rockbox_svn.orig/apps/gui/gwps-common.c rockbox_svn/apps/gui/gwps-common.c --- rockbox_svn.orig/apps/gui/gwps-common.c 2007-09-13 23:08:10.671875000 -0500 +++ rockbox_svn/apps/gui/gwps-common.c 2007-09-13 23:05:53.390625000 -0500 @@ -1447,7 +1447,55 @@ case WPS_TOKEN_ALIGN_SCROLLMARGIN_RIGHT: gwps->display->setmargins( gwps->display->getleftmargin(), token->value.i, gwps->display->getymargin() ); return NULL; - + + case WPS_TOKEN_CUSTOMLINE_XPOS: + gwps->data->line_xpos=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_YPOS: + gwps->data->line_ypos=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_WIDTH: + gwps->data->line_width=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_FONT: + gwps->data->line_font=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_COLOR: + gwps->data->line_fgcolor=token->value.i; + gwps->data->customline = true; +#ifdef HAVE_LCD_COLOR + if(gwps->display->depth>2){ + gwps->display->set_foreground(gwps->data->line_fgcolor); + } +#endif + + gwps->display->setmargins( gwps->data->line_xpos, gwps->data->line_xpos+gwps->data->line_width, gwps->data->line_ypos ); + + switch (gwps->data->line_font) { + case 1: + gwps->display->setfont(FONT_USER1); + break; + case 2: + gwps->display->setfont(FONT_USER2); + break; + case 3: + gwps->display->setfont(FONT_USER3); + break; + case 4: + gwps->display->setfont(FONT_USER4); + break; + case 5: + gwps->display->setfont(FONT_USER5); + break; + case 6: + gwps->display->setfont(FONT_USER6); + break; + case 7: + gwps->display->setfont(FONT_USER7); + break; + } + return NULL; + default: return NULL; } @@ -1762,7 +1810,8 @@ line is the index of the line on the screen. scroll indicates whether the line is a scrolling one or not. */ -static void write_line(struct screen *display, +static void write_line(struct wps_data *data, + struct screen *display, struct align_pos *format_align, int line, bool scroll) @@ -1775,7 +1824,8 @@ int space_width; int string_height; const int scroll_width = display->getrightmargin()-display->getleftmargin(); - + bool customline=data->customline; + /* calculate different string sizes and positions */ display->getstringsize((unsigned char *)" ", &space_width, &string_height); if (format_align->left != 0) { @@ -1787,16 +1837,28 @@ display->getstringsize((unsigned char *)format_align->center, ¢er_width, &string_height); } - - left_xpos = display->getleftmargin(); - center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2; + + if(customline){ + left_xpos = data->line_xpos; + center_xpos=(data->line_width - center_width) / 2 + data->line_xpos; + } + else { + left_xpos = display->getleftmargin(); + center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2; + } + if (format_align->right != 0) { display->getstringsize((unsigned char *)format_align->right, &right_width, &string_height); } - right_xpos = (display->getrightmargin() - right_width); + if(customline){ + right_xpos = (data->line_xpos+data->line_width - right_width); + } + else { + right_xpos = (display->getrightmargin() - right_width); + } /* Checks for overlapping strings. If needed the overlapping strings will be merged, separated by a @@ -1878,42 +1940,105 @@ } ypos = (line * string_height) + display->getymargin(); + - - if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) - { - display->puts_scroll(0, line, - (unsigned char *)format_align->left); - } - else - { -#ifdef HAVE_LCD_BITMAP - /* clear the line first */ - display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - display->fillrect(0, ypos, display->width, string_height); - display->set_drawmode(DRMODE_SOLID); -#endif - - /* Nasty hack: we output an empty scrolling string, - which will reset the scroller for that line */ - display->puts_scroll(0, line, (unsigned char *)""); - - /* print aligned strings */ - if (left_width != 0) - { - display->putsxy(left_xpos, ypos, - (unsigned char *)format_align->left); - } - if (center_width != 0) - { - display->putsxy(center_xpos, ypos, - (unsigned char *)format_align->center); + if(customline){ + switch (data->line_font) { + case 1: + display->setfont(FONT_USER1); + break; + case 2: + display->setfont(FONT_USER2); + break; + case 3: + display->setfont(FONT_USER3); + break; + case 4: + display->setfont(FONT_USER4); + break; + case 5: + display->setfont(FONT_USER5); + break; + case 6: + display->setfont(FONT_USER6); + break; + case 7: + display->setfont(FONT_USER7); + break; } - if (right_width != 0) - { - display->putsxy(right_xpos, ypos, - (unsigned char *)format_align->right); + if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) + { + display->puts_customline_scroll(line, + (unsigned char *)format_align->left); + } + else + { +#ifdef HAVE_LCD_BITMAP + /* Clear the area first if there is something to display */ + if (left_width || center_width || right_width) { + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(data->line_xpos, data->line_ypos, data->line_width, string_height); + display->set_drawmode(DRMODE_SOLID); } +#endif + /* Nasty hack: we output an empty scrolling string, + which will reset the scroller for that line */ + display->puts_customline_scroll(line, (unsigned char *)""); + + /* print aligned strings */ + if (left_width != 0) + { + display->putsxy(left_xpos, data->line_ypos, + (unsigned char *)format_align->left); + } + if (center_width != 0) + { + display->putsxy(center_xpos, data->line_ypos, + (unsigned char *)format_align->center); + } + if (right_width != 0) + { + display->putsxy(right_xpos, data->line_ypos, + (unsigned char *)format_align->right); + } + } + } else { +#ifdef HAVE_LCD_BITMAP + /* Clear the area first if there is something to display */ + if (left_width || center_width || right_width) { + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(0, ypos, display->width, string_height); + display->set_drawmode(DRMODE_SOLID); + } +#endif + if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) + { + display->puts_scroll(0, line, + (unsigned char *)format_align->left); + } + else + { + /* Nasty hack: we output an empty scrolling string, + which will reset the scroller for that line */ + display->puts_scroll(0, line, (unsigned char *)""); + + /* print aligned strings */ + if (left_width != 0) + { + display->putsxy(left_xpos, ypos, + (unsigned char *)format_align->left); + } + if (center_width != 0) + { + display->putsxy(center_xpos, ypos, + (unsigned char *)format_align->center); + } + if (right_width != 0) + { + display->putsxy(right_xpos, ypos, + (unsigned char *)format_align->right); + } + } } } @@ -1940,6 +2065,16 @@ bool update_line, new_subline_refresh; +#ifdef HAVE_LCD_COLOR + int fgcolor_save; + if(display->depth>2){ + fgcolor_save=display->get_foreground(); + } +#endif + int leftmargin_save=display->getleftmargin(); + int rightmargin_save=display->getrightmargin(); + int ymargin_save=display->getymargin(); + #ifdef HAVE_LCD_BITMAP gui_wps_statusbar_draw(gwps, true); @@ -2054,10 +2189,10 @@ /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) - write_line(display, &align, line, true); + write_line(data, display, &align, line, true); } else - write_line(display, &align, line, false); + write_line(data, display, &align, line, false); } } @@ -2104,6 +2239,12 @@ } #endif +#ifdef HAVE_LCD_COLOR + if(display->depth>2){ + display->set_foreground(fgcolor_save); + } +#endif + display->setmargins( leftmargin_save, rightmargin_save, ymargin_save ); return true; } diff -u -r rockbox_svn.orig/apps/gui/gwps-common.c.orig rockbox_svn/apps/gui/gwps-common.c.orig --- rockbox_svn.orig/apps/gui/gwps-common.c.orig 2007-09-13 23:07:55.937500000 -0500 +++ rockbox_svn/apps/gui/gwps-common.c.orig 2007-09-13 23:05:24.625000000 -0500 @@ -1787,7 +1787,7 @@ display->getstringsize((unsigned char *)format_align->center, ¢er_width, &string_height); } - + left_xpos = display->getleftmargin(); center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2; diff -u -r rockbox_svn.orig/apps/gui/gwps.h rockbox_svn/apps/gui/gwps.h --- rockbox_svn.orig/apps/gui/gwps.h 2007-09-13 23:07:46.078125000 -0500 +++ rockbox_svn/apps/gui/gwps.h 2007-09-13 23:05:53.421875000 -0500 @@ -200,6 +200,13 @@ WPS_TOKEN_IMAGE_PRELOAD, WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, WPS_TOKEN_IMAGE_DISPLAY, + + /* customline */ + WPS_TOKEN_CUSTOMLINE_XPOS, + WPS_TOKEN_CUSTOMLINE_YPOS, + WPS_TOKEN_CUSTOMLINE_WIDTH, + WPS_TOKEN_CUSTOMLINE_FONT, + WPS_TOKEN_CUSTOMLINE_COLOR, /* Albumart */ WPS_TOKEN_ALBUMART_DISPLAY, @@ -370,6 +377,12 @@ int num_strings; bool wps_loaded; + + /* customline */ + int line_xpos, line_ypos, line_width; + int line_font; + int line_fgcolor; + bool customline; }; /* initial setup of wps_data */ diff -u -r rockbox_svn.orig/apps/gui/wps_parser.c rockbox_svn/apps/gui/wps_parser.c --- rockbox_svn.orig/apps/gui/wps_parser.c 2007-09-13 23:07:55.984375000 -0500 +++ rockbox_svn/apps/gui/wps_parser.c 2007-09-13 23:05:53.437500000 -0500 @@ -130,6 +130,8 @@ struct wps_token *token, struct wps_data *wps_data); static int parse_albumart_conditional(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); +static int parse_customline(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); #endif /*HAVE_LCD_BITMAP */ #ifdef CONFIG_RTC @@ -288,14 +290,14 @@ parse_image_display }, { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, - { WPS_NO_TOKEN, "m", 0, parse_scrollmargins }, - { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_DYNAMIC, parse_albumart_conditional }, #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif + { WPS_NO_TOKEN, "m", 0, parse_scrollmargins }, + { WPS_NO_TOKEN, "e", 0, parse_customline }, #endif { WPS_TOKEN_UNKNOWN, "", 0, NULL } @@ -829,6 +831,67 @@ else return 0; }; +static int parse_customline(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + /* format: %e|x|y|w|font|color */ + const char* _pos; + + if(*wps_bufptr!='|') + return(0); /* malformed token: */ + + _pos=wps_bufptr+1; + if(!isdigit(*_pos)) + return(0); /* malformed token: */ + + wps_data->num_tokens +=5; + token->type = WPS_TOKEN_CUSTOMLINE_XPOS; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_YPOS; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_WIDTH; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_FONT; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos) + return(0); /* malformed token: */ + + ++_pos; + char fg_color[7]; + snprintf(fg_color, 7, "%s", _pos); + + token->type = WPS_TOKEN_CUSTOMLINE_COLOR; +#ifdef HAVE_LCD_COLOR + token->value.i = hex_to_rgb(fg_color); +#else + token->value.i=0; +#endif + + _pos+=6; + return( _pos - wps_bufptr + 1 ); +} /* Parse a generic token from the given string. Return the length read */ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) @@ -1134,6 +1197,13 @@ wps_data->full_line_progressbar = false; #endif wps_data->wps_loaded = false; + + wps_data->customline = false; + wps_data->line_xpos = -1; + wps_data->line_ypos = 1; + wps_data->line_width = -1; + wps_data->line_fgcolor = -1; + wps_data->line_font = -1; } static void wps_reset(struct wps_data *data) diff -u -r rockbox_svn.orig/apps/gui/wps_parser.c.orig rockbox_svn/apps/gui/wps_parser.c.orig --- rockbox_svn.orig/apps/gui/wps_parser.c.orig 2007-09-13 23:07:46.093750000 -0500 +++ rockbox_svn/apps/gui/wps_parser.c.orig 2007-09-13 23:05:15.093750000 -0500 @@ -288,14 +288,13 @@ parse_image_display }, { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, - { WPS_NO_TOKEN, "m", 0, parse_scrollmargins }, - { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_DYNAMIC, parse_albumart_conditional }, #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif + { WPS_NO_TOKEN, "m", 0, parse_scrollmargins }, #endif { WPS_TOKEN_UNKNOWN, "", 0, NULL } diff -u -r rockbox_svn.orig/apps/screen_access.c rockbox_svn/apps/screen_access.c --- rockbox_svn.orig/apps/screen_access.c 2007-09-13 23:08:11.484375000 -0500 +++ rockbox_svn/apps/screen_access.c 2007-09-13 23:05:53.453125000 -0500 @@ -49,6 +49,7 @@ screen->getymargin=&lcd_remote_getymargin; screen->getleftmargin=&lcd_remote_getleftmargin; screen->getrightmargin=&lcd_remote_getrightmargin; + screen->getmarginwidth=&lcd_remote_getmarginwidth; screen->getstringsize=&lcd_remote_getstringsize; #if 1 /* all remote LCDs are bitmapped so far */ screen->setfont=&lcd_remote_setfont; @@ -100,7 +101,9 @@ screen->puts=&lcd_remote_puts; screen->puts_offset=&lcd_remote_puts_offset; screen->puts_scroll=&lcd_remote_puts_scroll; + screen->puts_customline_scroll=&lcd_remote_puts_customline_scroll; screen->puts_scroll_offset=&lcd_remote_puts_scroll_offset; + screen->puts_customline_scroll_offset=&lcd_remote_puts_customline_scroll_offset; screen->scroll_speed=&lcd_remote_scroll_speed; screen->scroll_delay=&lcd_remote_scroll_delay; screen->stop_scroll=&lcd_remote_stop_scroll; @@ -135,6 +138,7 @@ screen->getymargin=&lcd_getymargin; screen->getleftmargin=&lcd_getleftmargin; screen->getrightmargin=&lcd_getrightmargin; + screen->getmarginwidth=&lcd_getmarginwidth; screen->getstringsize=&lcd_getstringsize; #ifdef HAVE_LCD_BITMAP screen->setfont=&lcd_setfont; @@ -189,7 +193,9 @@ screen->puts=&lcd_puts; screen->puts_offset=&lcd_puts_offset; screen->puts_scroll=&lcd_puts_scroll; + screen->puts_customline_scroll=&lcd_puts_customline_scroll; screen->puts_scroll_offset=&lcd_puts_scroll_offset; + screen->puts_customline_scroll_offset=&lcd_puts_customline_scroll_offset; screen->scroll_speed=&lcd_scroll_speed; screen->scroll_delay=&lcd_scroll_delay; screen->stop_scroll=&lcd_stop_scroll; diff -u -r rockbox_svn.orig/apps/screen_access.h rockbox_svn/apps/screen_access.h --- rockbox_svn.orig/apps/screen_access.h 2007-09-13 23:08:11.500000000 -0500 +++ rockbox_svn/apps/screen_access.h 2007-09-13 23:05:53.468750000 -0500 @@ -73,7 +73,7 @@ int (*getleftmargin)(void); int (*getrightmargin)(void); int (*getymargin)(void); - + int (*getmarginwidth)(void); int (*getstringsize)(const unsigned char *str, int *w, int *h); #if defined(HAVE_LCD_BITMAP) || defined(HAVE_REMOTE_LCD) /* always bitmap */ void (*setfont)(int newfont); @@ -133,6 +133,10 @@ void (*puts_scroll)(int x, int y, const unsigned char *string); void (*puts_scroll_offset)(int x, int y, const unsigned char *string, int offset); + void (*puts_customline_scroll)(int i, const unsigned char *string); + void (*puts_customline_scroll_offset)(int i, const unsigned char *string, + int offset); + void (*scroll_speed)(int speed); void (*scroll_delay)(int ms); void (*stop_scroll)(void); diff -u -r rockbox_svn.orig/apps/settings.h rockbox_svn/apps/settings.h --- rockbox_svn.orig/apps/settings.h 2007-09-13 23:08:11.593750000 -0500 +++ rockbox_svn/apps/settings.h 2007-09-13 23:05:41.093750000 -0500 @@ -744,6 +744,11 @@ #if defined(HAVE_RTC_ALARM) && \ (defined(HAVE_RECORDING) || CONFIG_TUNER) int alarm_wake_up_screen; + #if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI) + unsigned int ipod_scroll_wheel_acceleration_fast; + unsigned int ipod_scroll_wheel_acceleration_faster; + unsigned int ipod_scroll_wheel_acceleration_fastest; + #endif #endif /* customizable icons */ #ifdef HAVE_LCD_BITMAP diff -u -r rockbox_svn.orig/firmware/drivers/lcd-16bit.c rockbox_svn/firmware/drivers/lcd-16bit.c --- rockbox_svn.orig/firmware/drivers/lcd-16bit.c 2007-09-13 23:08:11.671875000 -0500 +++ rockbox_svn/firmware/drivers/lcd-16bit.c 2007-09-13 23:05:53.484375000 -0500 @@ -133,6 +133,11 @@ return ymargin; } +int lcd_getmarginwidth(void) +{ + return lcd_getrightmargin()-lcd_getleftmargin(); +} + void lcd_setfont(int newfont) { curfont = newfont; @@ -574,7 +579,7 @@ backdrop = lcd_backdrop + y * LCD_WIDTH + x; fgfunc = lcd_fastpixelfuncs[drawmode]; bgfunc = lcd_fastpixelfuncs[drawmode ^ DRMODE_INVERSEVID]; - do + do { const unsigned char *src_col = src++; unsigned data = *src_col >> src_y; @@ -582,7 +587,7 @@ int numbits = 8 - src_y; fb_data *backdrop_col = backdrop++; dst_end = dst_col + height * LCD_WIDTH; - do + do { switch (drawmode) { @@ -612,7 +617,7 @@ dst_col += LCD_WIDTH; backdrop_col += LCD_WIDTH; data >>= 1; - if (--numbits == 0) + if (--numbits == 0) { src_col += stride; data = *src_col; @@ -742,16 +747,18 @@ lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height); } -/* put a string at a given pixel position, skipping first ofs pixel columns */ -static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str, int rmargin) { unsigned short ch; unsigned short *ucs; struct font* pf = font_get(curfont); - + int used_rightmargin=rmargin?rmargin:rightmargin; + ucs = bidi_l2v(str, 1); - while ((ch = *ucs++) != 0 && x < LCD_WIDTH) + while ((ch = *ucs++) != 0 && x < used_rightmargin) { int width; const unsigned char *bits; @@ -767,7 +774,7 @@ bits = font_get_bits(pf, ch, curfont); - lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); x += width - ofs; ofs = 0; @@ -777,7 +784,7 @@ /* put a string at a given pixel position */ void lcd_putsxy(int x, int y, const unsigned char *str) { - lcd_putsxyofs(x, y, 0, str); + lcd_putsxyofs(x, y, 0, str, 0); } /*** line oriented text output ***/ @@ -825,19 +832,163 @@ else bg_pattern = style & STYLE_COLOR_MASK; } - lcd_putsxyofs(xpos, ypos, offset, str); + lcd_putsxyofs(xpos, ypos, offset, str, 0); drawmode ^= DRMODE_INVERSEVID; xrect = xpos + MAX(w - offset, 0); - lcd_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); - if (LCD_WIDTH>rightmargin) { - lcd_fillrect(rightmargin, ypos, LCD_WIDTH - rightmargin, h); - } + lcd_fillrect(xrect, ypos, rightmargin - xrect, h); drawmode = lastmode; fg_pattern = oldfgcolor; bg_pattern = oldbgcolor; } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf,ch,curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ +void lcd_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_puts_customline_scroll_style_offset(int i, + const unsigned char *string, int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_getleftmargin(); + s->line_ypos = lcd_getymargin(); + s->fgcolor = lcd_get_foreground(); + s->line_width = lcd_getrightmargin()-lcd_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + lcd_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_puts_customline_offset(i,string,offset); + + lcd_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1<customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->fgcolor = lcd_get_foreground(); s->start_tick = current_tick + lcd_scroll_info.delay; s->invert = false; if (style & STYLE_INVERT) { @@ -904,12 +1062,12 @@ s->offset = offset; s->startx = leftmargin + x * s->width / s->len; s->backward = false; - s->left_margin=leftmargin; - s->right_margin=rightmargin; s->line_color = (style&STYLE_COLORED)? (style&STYLE_COLOR_MASK): -1; lcd_scroll_info.lines |= (1<y_margin=ymargin; + s->left_margin=leftmargin; + s->right_margin=rightmargin; } else /* force a bit switch-off since it doesn't scroll */ @@ -925,6 +1083,7 @@ int lastmode; unsigned old_fgcolor = fg_pattern; unsigned old_bgcolor = bg_pattern; + int fgcolor_save; for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { /* really scroll? */ @@ -953,9 +1112,18 @@ else s->offset += lcd_scroll_info.step; + if (s->customline) { + lcd_setfont(s->line_font); + } + pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -977,16 +1145,16 @@ s->offset %= s->width; } + fgcolor_save = lcd_get_foreground(); + lcd_set_foreground(s->fgcolor); + lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_putsxyofs(xpos, ypos, s->offset, s->line); - if (LCD_WIDTH>s->right_margin) { - drawmode ^= DRMODE_INVERSEVID; - lcd_fillrect(s->right_margin, ypos, LCD_WIDTH - s->right_margin, pf->height); - } + lcd_putsxyofs(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; lcd_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); + lcd_set_foreground(fgcolor_save); } fg_pattern = old_fgcolor; Only in rockbox_svn.orig/firmware/drivers: lcd-16bit.c.orig diff -u -r rockbox_svn.orig/firmware/drivers/lcd-1bit-vert.c rockbox_svn/firmware/drivers/lcd-1bit-vert.c --- rockbox_svn.orig/firmware/drivers/lcd-1bit-vert.c 2007-09-13 23:07:32.296875000 -0500 +++ rockbox_svn/firmware/drivers/lcd-1bit-vert.c 2007-09-13 23:04:59.062500000 -0500 @@ -121,7 +121,7 @@ flippixel, nopixel, setpixel, setpixel, nopixel, clearpixel, nopixel, clearpixel }; - + static void flipblock(unsigned char *address, unsigned mask, unsigned bits) ICODE_ATTR; static void flipblock(unsigned char *address, unsigned mask, unsigned bits) @@ -179,7 +179,7 @@ static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) { unsigned data = *(char *)address; - + bits = ~bits ^ data; *address = data ^ (bits & mask); } @@ -293,17 +293,17 @@ x1 = x2; x2 = x; } - + /* nothing to draw? */ if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) - return; - + return; + /* clipping */ if (x1 < 0) x1 = 0; if (x2 >= LCD_WIDTH) x2 = LCD_WIDTH-1; - + bfunc = lcd_blockfuncs[drawmode]; dst = &lcd_framebuffer[y>>3][x1]; mask = 1 << (y & 7); @@ -332,14 +332,14 @@ /* nothing to draw? */ if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) - return; - + return; + /* clipping */ if (y1 < 0) y1 = 0; if (y2 >= LCD_HEIGHT) y2 = LCD_HEIGHT-1; - + bfunc = lcd_blockfuncs[drawmode]; dst = &lcd_framebuffer[y1>>3][x]; ny = y2 - (y1 & ~7); @@ -401,7 +401,7 @@ width = LCD_WIDTH - x; if (y + height > LCD_HEIGHT) height = LCD_HEIGHT - y; - + if (drawmode & DRMODE_INVERSEVID) { if (drawmode & DRMODE_BG) @@ -480,7 +480,7 @@ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) return; - + /* clipping */ if (x < 0) { @@ -509,7 +509,7 @@ bfunc = lcd_blockfuncs[drawmode]; mask = 0xFFu << (shift + src_y); mask_bottom = 0xFFu >> (~ny & 7); - + if (shift == 0) { bool copyopt = (drawmode == DRMODE_SOLID); @@ -522,9 +522,9 @@ { const unsigned char *src_row = src; unsigned char *dst_row = dst; - + dst_end = dst_row + width; - do + do bfunc(dst_row++, mask, *src_row++); while (dst_row < dst_end); } @@ -554,7 +554,7 @@ unsigned char *dst_col = dst++; unsigned mask_col = mask; unsigned data = 0; - + for (y = ny; y >= 8; y -= 8) { data |= *src_col << shift; @@ -611,7 +611,7 @@ lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); - + x += width - ofs; ofs = 0; } @@ -684,8 +684,8 @@ int offset) { lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); -} - +} + void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, int style, int offset) { @@ -720,7 +720,7 @@ /* scroll bidirectional or forward only depending on the string width */ if ( lcd_scroll_info.bidir_limit ) { - s->bidir = s->width < (rightmargin - leftmargin) * + s->bidir = s->width < (right_margin - xmargin) * (100 + lcd_scroll_info.bidir_limit) / 100; } else diff -u -r rockbox_svn.orig/firmware/drivers/lcd-2bit-horz.c rockbox_svn/firmware/drivers/lcd-2bit-horz.c --- rockbox_svn.orig/firmware/drivers/lcd-2bit-horz.c 2007-09-13 23:08:11.687500000 -0500 +++ rockbox_svn/firmware/drivers/lcd-2bit-horz.c 2007-09-13 23:05:41.187500000 -0500 @@ -172,7 +172,7 @@ { unsigned mask = pixmask[x & 3]; fb_data *address = &lcd_framebuffer[y][x>>2]; - + *address ^= mask; } @@ -347,7 +347,7 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) { unsigned data = *address; - + bits ^= data; *address = data ^ (bits & mask); } @@ -465,11 +465,11 @@ x1 = x2; x2 = nx; } - + /* nothing to draw? */ if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) - return; - + return; + /* clipping */ if (x1 < 0) x1 = 0; @@ -481,7 +481,7 @@ nx = x2 - (x1 & ~3); mask = 0xFFu >> (2 * (x1 & 3)); mask_right = 0xFFu << (2 * (~nx & 3)); - + for (; nx >= 4; nx -= 4) { bfunc(dst++, mask, 0xFFu); @@ -509,18 +509,18 @@ /* nothing to draw? */ if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) - return; - + return; + /* clipping */ if (y1 < 0) y1 = 0; if (y2 >= LCD_HEIGHT) y2 = LCD_HEIGHT-1; - + bfunc = lcd_blockfuncs[drawmode]; dst = &lcd_framebuffer[y1][x>>2]; mask = pixmask[x & 3]; - + dst_end = dst + (y2 - y1) * LCD_FBWIDTH; do { @@ -579,7 +579,7 @@ nx = width - 1 + (x & 3); mask = 0xFFu >> (2 * (x & 3)); mask_right = 0xFFu << (2 * (~nx & 3)); - + for (; nx >= 4; nx -= 4) { unsigned char *dst_col = dst; @@ -631,7 +631,7 @@ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) return; - + /* clipping */ if (x < 0) { @@ -654,15 +654,15 @@ src_y &= 7; src_end = src + width; - fgfunc = lcd_pixelfuncs[drawmode]; - bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; + fgfunc = lcd_pixelfuncs[drawmode]; + bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; nx = x; do { const unsigned char *src_col = src++; unsigned data = *src_col >> src_y; int numbits = 8 - ((int)src_y); - + ymax = y + height; ny = y; do @@ -719,7 +719,7 @@ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) return; - + /* clipping */ if (x < 0) { @@ -749,7 +749,7 @@ mask = 0xFF00u >> (2 * (shift + src_x)); mask_right = 0xFFu << (2 * (~nx & 3)); - + shift *= 2; dst_end = dst + height * LCD_FBWIDTH; do @@ -758,11 +758,11 @@ unsigned char *dst_row = dst; unsigned mask_row = mask >> 8; unsigned data = 0; - + for (x = nx; x >= 4; x -= 4) { data = (data << 8) | *src_row++; - + if (mask_row & 0xFF) { setblock(dst_row, mask_row, data >> shift); @@ -815,7 +815,7 @@ lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); - + x += width - ofs; ofs = 0; } @@ -885,8 +885,8 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) { lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); -} - +} + void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, int style, int offset) { diff -u -r rockbox_svn.orig/firmware/drivers/lcd-2bit-vert.c rockbox_svn/firmware/drivers/lcd-2bit-vert.c --- rockbox_svn.orig/firmware/drivers/lcd-2bit-vert.c 2007-09-13 23:08:11.703125000 -0500 +++ rockbox_svn/firmware/drivers/lcd-2bit-vert.c 2007-09-13 23:05:53.515625000 -0500 @@ -128,6 +128,11 @@ return ymargin; } +int lcd_getmarginwidth(void) +{ + return lcd_getrightmargin()-lcd_getleftmargin(); +} + void lcd_setfont(int newfont) { curfont = newfont; @@ -240,7 +245,7 @@ { unsigned data = *address; unsigned bgp = bg_pattern; - + bits = bgp ^ ((bgp ^ fg_pattern) & bits); *address = data ^ ((data ^ bits) & mask); } @@ -251,7 +256,7 @@ { unsigned data = *address; unsigned bgp = *(address + lcd_backdrop_offset); - + bits = bgp ^ ((bgp ^ fg_pattern) & bits); *address = data ^ ((data ^ bits) & mask); } @@ -296,7 +301,7 @@ { unsigned data = *address; unsigned fgp = fg_pattern; - + bits = fgp ^ ((fgp ^ bg_pattern) & bits); *address = data ^ ((data ^ bits) & mask); } @@ -307,7 +312,7 @@ { unsigned data = *address; unsigned fgp = fg_pattern; - + bits = fgp ^ ((fgp ^ *(address + lcd_backdrop_offset)) & bits); *address = data ^ ((data ^ bits) & mask); } @@ -334,7 +339,7 @@ lcd_pixelfuncs = lcd_pixelfuncs_backdrop; lcd_blockfuncs = lcd_blockfuncs_backdrop; } - else + else { lcd_backdrop_offset = 0; lcd_pixelfuncs = lcd_pixelfuncs_bgcolor; @@ -469,17 +474,17 @@ x1 = x2; x2 = x; } - + /* nothing to draw? */ if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) - return; - + return; + /* clipping */ if (x1 < 0) x1 = 0; if (x2 >= LCD_WIDTH) x2 = LCD_WIDTH-1; - + bfunc = lcd_blockfuncs[drawmode]; dst = &lcd_framebuffer[y>>2][x1]; mask = pixmask[y & 3]; @@ -508,14 +513,14 @@ /* nothing to draw? */ if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) - return; - + return; + /* clipping */ if (y1 < 0) y1 = 0; if (y2 >= LCD_HEIGHT) y2 = LCD_HEIGHT-1; - + bfunc = lcd_blockfuncs[drawmode]; dst = &lcd_framebuffer[y1>>2][x]; ny = y2 - (y1 & ~3); @@ -577,7 +582,7 @@ width = LCD_WIDTH - x; if (y + height > LCD_HEIGHT) height = LCD_HEIGHT - y; - + if (drawmode & DRMODE_INVERSEVID) { if ((drawmode & DRMODE_BG) && !lcd_backdrop) @@ -657,7 +662,7 @@ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) return; - + /* clipping */ if (x < 0) { @@ -686,7 +691,7 @@ bfunc = lcd_blockfuncs[drawmode]; mask = 0xFFu << (shift + src_y); mask_bottom = 0xFFu >> (~ny & 7); - + if (shift == 0) { unsigned dmask1, dmask2, data; @@ -695,7 +700,7 @@ { const unsigned char *src_row = src; fb_data *dst_row = dst + LCD_WIDTH; - + dmask1 = lcd_dibits[mask&0x0F]; dmask2 = lcd_dibits[(mask>>4)&0x0F]; dst_end = dst_row + width; @@ -724,7 +729,7 @@ dmask1 = lcd_dibits[mask&0x0F]; dmask2 = lcd_dibits[(mask>>4)&0x0F]; dst_end = dst + width; - + if (dmask1 != 0) { if (dmask2 != 0) @@ -760,8 +765,8 @@ fb_data *dst_col = dst++; unsigned mask_col = mask; unsigned data = 0; - - for (y = ny; y >= 8; y -= 8) + + for (y = ny; y >= 8; y -= 8) { data |= *src_col << shift; @@ -824,7 +829,7 @@ if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) return; - + /* clipping */ if (x < 0) { @@ -852,7 +857,7 @@ mask = 0xFFu << (2 * (shift + src_y)); mask_bottom = 0xFFu >> (2 * (~ny & 3)); - + if (shift == 0) { for (; ny >= 4; ny -= 4) @@ -863,9 +868,9 @@ { const fb_data *src_row = src; fb_data *dst_row = dst; - + dst_end = dst_row + width; - do + do setblock(dst_row++, mask, *src_row++); while (dst_row < dst_end); } @@ -895,7 +900,7 @@ fb_data *dst_col = dst++; unsigned mask_col = mask; unsigned data = 0; - + for (y = ny; y >= 4; y -= 4) { data |= *src_col << shift; @@ -952,7 +957,7 @@ lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); - + x += width - ofs; ofs = 0; } @@ -1011,6 +1016,68 @@ drawmode = lastmode; } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf,ch,curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} /*** scrolling ***/ void lcd_puts_scroll(int x, int y, const unsigned char *string) @@ -1026,8 +1093,8 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) { lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); -} - +} + void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, int style, int offset) { @@ -1038,14 +1105,22 @@ s = &lcd_scroll_info.scroll[y]; + // MWE reset customline attributes + s->customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->fgcolor = lcd_get_foreground(); + s->start_tick = current_tick + lcd_scroll_info.delay; s->invert = false; if (style & STYLE_INVERT) { s->invert = true; - lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); + lcd_puts_style_offset(0,0,string,STYLE_INVERT,offset); } else - lcd_puts_offset(x,y,string,offset); + lcd_puts_offset(0,0,string,offset); lcd_getstringsize(string, &w, &h); @@ -1062,7 +1137,7 @@ /* scroll bidirectional or forward only depending on the string width */ if ( lcd_scroll_info.bidir_limit ) { - s->bidir = s->width < (rightmargin - leftmargin) * + s->bidir = s->width < (LCD_WIDTH - leftmargin) * (100 + lcd_scroll_info.bidir_limit) / 100; } else @@ -1110,14 +1185,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_scroll_info.step; else s->offset += lcd_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -1128,7 +1212,7 @@ } if (s->offset >= s->width - (s->right_margin - xpos)) { /* at end of line */ - s->offset = s->width - (s->right_margin - xpos); + s->offset = s->width - (s->rightmargin - xpos); s->backward = true; s->start_tick = current_tick + lcd_scroll_info.delay * 2; } @@ -1142,12 +1226,91 @@ lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_putsxyofs(xpos, ypos, s->offset, s->line); - if (LCD_WIDTH>s->right_margin) { - drawmode ^= DRMODE_INVERSEVID; - lcd_fillrect(s->right_margin, ypos, LCD_WIDTH - s->right_margin, pf->height); - } + lcd_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; lcd_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } } + +void lcd_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_puts_customline_scroll_style_offset(int i, + const unsigned char *string, int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_getleftmargin(); + s->line_ypos = lcd_getymargin(); + s->line_width = lcd_getrightmargin()-lcd_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + lcd_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_puts_customline_offset(i,string,offset); + + lcd_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1< width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, + pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_remote_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_remote_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_remote_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_remote_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_remote_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) @@ -722,7 +791,7 @@ /* scroll bidirectional or forward only depending on the string width */ if ( lcd_remote_scroll_info.bidir_limit ) { - s->bidir = s->width < (rightmargin - leftmargin) * + s->bidir = s->width < (rightmargin - xmargin) * (100 + lcd_remote_scroll_info.bidir_limit) / 100; } else @@ -770,14 +839,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_remote_scroll_info.step; else s->offset += lcd_remote_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -802,11 +880,7 @@ lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); - if (LCD_REMOTE_WIDTH > s->right_margin) { - drawmode ^= DRMODE_INVERSEVID; - lcd_remote_fillrect(s->right_margin, ypos, LCD_WIDTH - s->right_margin, pf->height); - } + lcd_remote_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } @@ -820,3 +894,86 @@ lcd_remote_init_device(); #endif } + +void lcd_remote_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_remote_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_remote_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_remote_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_remote_getleftmargin(); + s->line_ypos = lcd_remote_getymargin(); + s->line_width = lcd_remote_getrightmargin()-lcd_remote_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + lcd_remote_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_remote_puts_customline_offset(i,string,offset); + + lcd_remote_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1<>3][x]; unsigned data = *address; - *address = data ^ ((data ^ *(fb_remote_data *)((long)address + *address = data ^ ((data ^ *(fb_remote_data *)((long)address + remote_backdrop_offset)) & mask); } @@ -279,7 +284,7 @@ { unsigned data = *address; - *address = data ^ ((data ^ *(fb_remote_data *)((long)address + *address = data ^ ((data ^ *(fb_remote_data *)((long)address + remote_backdrop_offset)) & mask & bits); } @@ -924,16 +929,18 @@ lcd_remote_bitmap_part(src, 0, 0, width, x, y, width, height); } -/* put a string at a given pixel position, skipping first ofs pixel columns */ -void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str, int rmargin) { unsigned short ch; unsigned short *ucs; struct font* pf = font_get(curfont); - + int used_rightmargin=rmargin?rmargin:rightmargin; + ucs = bidi_l2v(str, 1); - while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH) + while ((ch = *ucs++) != 0 && x < used_rightmargin) { int width; const unsigned char *bits; @@ -949,7 +956,7 @@ bits = font_get_bits(pf, ch, curfont); - lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, + lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); x += width - ofs; @@ -960,7 +967,7 @@ /* put a string at a given pixel position */ void lcd_remote_putsxy(int x, int y, const unsigned char *str) { - lcd_remote_putsxyofs(x, y, 0, str); + lcd_remote_putsxyofs(x, y, 0, str, 0); } /*** line oriented text output ***/ @@ -981,6 +988,41 @@ lcd_remote_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_remote_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf, ch, curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, + pf->height); + + x += width - ofs; + ofs = 0; + } +} + /* put a string at a given char position, style, and pixel position, * skipping first offset pixel columns */ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, @@ -1000,13 +1042,42 @@ ypos = ymargin + y*h; drawmode = (style & STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, offset, str); + lcd_remote_putsxyofs(xpos, ypos, offset, str, 0); drawmode ^= DRMODE_INVERSEVID; xrect = xpos + MAX(w - offset, 0); - lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); drawmode = lastmode; } +void lcd_remote_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_remote_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_remote_putsxyofs(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_remote_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_remote_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) { @@ -1033,6 +1104,13 @@ s = &lcd_remote_scroll_info.scroll[y]; + // MWE reset customline attributes + s->customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->start_tick = current_tick + lcd_remote_scroll_info.delay; s->invert = false; if (style & STYLE_INVERT) { @@ -1070,12 +1148,14 @@ } end = strchr(s->line, '\0'); - strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2); + strncpy(end, (char *)string, rightmargin/2); s->len = utf8length((char *)string); s->offset = offset; s->startx = leftmargin + x * s->width / s->len;; s->backward = false; + s->left_margin=leftmargin; + s->right_margin=rightmargin; lcd_remote_scroll_info.lines |= (1<y_margin=ymargin; } @@ -1103,14 +1183,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_remote_scroll_info.step; else s->offset += lcd_remote_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -1119,9 +1208,9 @@ s->backward = false; s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; } - if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) { + if (s->offset >= s->width - (s->right_margin - xpos)) { /* at end of line */ - s->offset = s->width - (LCD_REMOTE_WIDTH - xpos); + s->offset = s->width - (s->right_margin - xpos); s->backward = true; s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; } @@ -1135,9 +1224,9 @@ lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); + lcd_remote_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; - lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); + lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } } @@ -1149,3 +1238,87 @@ lcd_remote_init_device(); #endif } + +void lcd_remote_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_remote_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_remote_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_remote_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_remote_getleftmargin(); + s->line_ypos = lcd_remote_getymargin(); + s->line_width = lcd_remote_getrightmargin()-lcd_remote_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + lcd_remote_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_remote_puts_customline_offset(i,string,offset); + + lcd_remote_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1<= 8 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; diff -u -r rockbox_svn.orig/firmware/export/scroll_engine.h rockbox_svn/firmware/export/scroll_engine.h --- rockbox_svn.orig/firmware/export/scroll_engine.h 2007-09-13 23:07:32.421875000 -0500 +++ rockbox_svn/firmware/export/scroll_engine.h 2007-09-13 23:05:53.609375000 -0500 @@ -51,6 +51,13 @@ int y_margin; int left_margin; int right_margin; + /* Customline arguments */ + bool customline; + int line_font; + int line_xpos; + int line_ypos; + int line_width; + int fgcolor; #ifdef HAVE_LCD_COLOR int line_color; #endif