Index: apps/settings.h
===================================================================
RCS file: /cvsroot/rockbox/apps/settings.h,v
retrieving revision 1.256
diff -u -r1.256 settings.h
--- apps/settings.h	19 Dec 2006 01:26:37 -0000	1.256
+++ apps/settings.h	16 Jan 2007 01:18:28 -0000
@@ -577,6 +602,7 @@
 unsigned int rec_timesplit_seconds(void);
 unsigned long rec_sizesplit_bytes(void);
 void settings_apply_trigger(void);
+int hex_to_rgb(const char* hex);
 
 /* global settings */
 extern struct user_settings global_settings;
diff -u -r1.443 settings.c
--- apps/settings.c	31 Dec 2006 02:44:53 -0000	1.443
+++ apps/settings.c	16 Jan 2007 01:20:14 -0000
@@ -762,7 +768,7 @@
 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
                                                    (toupper(c)) - 'A' + 10)
 
-static int hex_to_rgb(const char* hex)
+int hex_to_rgb(const char* hex)
 {   int ok = 1;
     int i;
     int red, green, blue;
diff -u -r gwps-common.c gwps-common.c
--- apps/gui/gwps-common.c	2006-08-06 21:28:44.000000000 +0300
+++ apps/gui/gwps-common.c	2006-08-06 21:24:41.000000000 +0300
@@ -1294,6 +1294,42 @@
             case 0:
                 *buf++ = '%';
                 break;
+            case 'e': /* Line settings (x/y/width and font face */
+        	fmt++;
+        	if (*fmt == '|') {
+        	    char *p=strchr(fmt, '|');
+        	    if (p) {
+        		fmt = ++p;
+        		gwps->data->line_xpos = atoi(p);
+        		p = strchr(p, '|');
+        		if (p) {
+        		    fmt = ++p;
+        		    gwps->data->line_ypos = atoi(p);
+        		    p = strchr(p, '|');
+        		    if (p) {
+        			fmt = ++p;
+        			gwps->data->line_width = atoi(p);
+        			p = strchr(p, '|');
+        			if (p) {
+        			    fmt = ++p;
+        			    gwps->data->line_font = atoi(p);
+        			    p = strchr(p, '|');
+        			    if (p) {
+        				fmt = ++p;
+        				char fg_color[7];
+        				snprintf(fg_color, 7, "%s", p);
+        				gwps->data->line_fgcolor = hex_to_rgb(fg_color);
+        				p = strchr(p, '|');
+        				if (p) {
+        				    fmt = ++p;
+        				}
+        			    }
+        			}
+        		    }
+        		}
+        	    }
+        	}
+        	break;
             case 'a':
                 ++fmt;
                 /* remember where the current aligned text started */
@@ -1844,6 +2329,46 @@
             }
 #endif
 #ifdef HAVE_LCD_BITMAP
+	    /* If need to refresh a line and we have a custom font we
+	       should set the font face prior getting the font size */
+            if (flags & (WPS_REFRESH_DYNAMIC | WPS_REFRESH_STATIC | WPS_REFRESH_SCROLL))
+            {
+	        	if (((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC|WPS_REFRESH_SCROLL)) ||
+    	    	    new_subline_refresh) && 
+        		    ((int)data->line_xpos || (int)data->line_ypos ||
+        		     (int)data->line_width || (int)data->line_font))
+	        	{
+    	    	    if (data->line_font_prev != data->line_font) {
+        				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;
+        				}
+        		
+		        		data->line_font_prev = data->line_font;
+    	    	    }
+    	    	}
+    	    }
+        	    
             /* calculate different string sizes and positions */
             display->getstringsize((unsigned char *)" ", &space_width, &string_height);
             if (format_align.left != 0) {
@@ -1966,6 +2491,38 @@
 #endif
 
             if (flags & WPS_REFRESH_SCROLL) {
+                /* Custom line with scroll capabilities */
+                if (((refresh_mode & WPS_REFRESH_SCROLL) ||
+                    new_subline_refresh) && 
+	        	    ((int)data->line_xpos || (int)data->line_ypos ||
+    	    	     (int)data->line_width || (int)data->line_font))
+    	    	{
+	        	    /* 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((int)data->line_xpos,
+        				      (int)data->line_ypos,
+        				      (int)data->line_width,
+        			    	  string_height);
+	        		    display->set_drawmode(DRMODE_SOLID);
+    	    	    }
+        		    
+        		    if (data->line_fgcolor_prev != data->line_fgcolor) {
+	        			display->set_foreground(data->line_fgcolor);
+    	    			data->line_fgcolor_prev = data->line_fgcolor;
+	        	    }
+    	    	    
+        		    display->setmargins(data->line_xpos, data->line_ypos);
+        		    display->set_custom_width(data->line_width);
+        	    
+                    /* Nasty hack: we output an empty scrolling string,
+                       which will reset the scroller for that line */
+                    display->puts_customline_scroll(i, (unsigned char *)"");
+                    
+                    display->puts_customline_scroll(i,
+                                        (unsigned char *)format_align.left
+                                        );
+    	    	} else
 
                 /* scroll line */
                 if ((refresh_mode & WPS_REFRESH_SCROLL) ||
@@ -2014,8 +2567,59 @@
 #endif
                 }
             }
+            /* Custom lines with x/y/width coordinates and font face/color */
             else if (flags & (WPS_REFRESH_DYNAMIC | WPS_REFRESH_STATIC))
             {
+        	if (((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC)) ||
+        	    new_subline_refresh) && 
+        	    ((int)data->line_xpos || (int)data->line_ypos ||
+        	     (int)data->line_width || (int)data->line_font))
+        	{
+        	    update_line = true;
+        	    
+        	    /* 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((int)data->line_xpos,
+        			      (int)data->line_ypos,
+        			      (int)data->line_width,
+        			      string_height);
+        		    display->set_drawmode(DRMODE_SOLID);
+        	    }
+        	    
+        	    if (data->line_fgcolor_prev != data->line_fgcolor) {
+	        		display->set_foreground(data->line_fgcolor);
+    	    		data->line_fgcolor_prev = data->line_fgcolor;
+        	    }
+        	    
+        	    display->setmargins(data->line_xpos, data->line_ypos);
+        	    display->set_custom_width(data->line_width);
+        	    
+        	    /* Print aligned strings */
+        	    if (left_width != 0) 
+        	    {
+        			display->putsxy((int)data->line_xpos,
+        				(int)data->line_ypos,
+        				(unsigned char *)format_align.left
+        				);
+        	    }
+        	    if (center_width != 0) 
+        	    {
+        			display->putsxy((int)data->line_xpos+
+        					(int)((data->line_width-center_width)/2),
+        				(int)data->line_ypos,
+        				(unsigned char *)format_align.center
+        				);
+        	    }
+        	    if (right_width != 0) 
+        	    {
+        			display->putsxy((int)data->line_xpos+
+        				    ((int)data->line_width-right_width),
+        				(int)data->line_ypos,
+        				(unsigned char *)format_align.right
+        				);
+        	    }
+        	} else
                 /* dynamic / static line */
                 if ((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC)) ||
                     new_subline_refresh)
@@ -2025,9 +2633,11 @@
                     update_line = true;
 
                     /* clear the line first */
-                    display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
-                    display->fillrect(0, ypos, display->width, string_height);
-                    display->set_drawmode(DRMODE_SOLID);
+                    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);
+                    }
 
                     /* Nasty hack: we output an empty scrolling string,
                        which will reset the scroller for that line */
@@ -2073,6 +2199,15 @@
     /* Now we know wether the peak meter is used.
        So we can enable / disable the peak meter thread */
     data->peak_meter_enabled = enable_pm;
+    /* Reset margins */
+    data->line_xpos=0;
+    data->line_ypos=0;
+    data->line_width=0;
+    data->line_font=0;
+    /* Reset display color */
+    data->line_fgcolor_prev = 0;
+    data->line_fgcolor = global_settings.fg_color;
+	display->set_foreground(global_settings.fg_color);
 #endif
 
 #ifdef CONFIG_BACKLIGHT
diff -u -r gwps.h gwps.h
--- apps/gui/gwps.h	2006-08-03 23:17:14.000000000 +0300
+++ apps/gui/gwps.h	2006-08-06 11:57:51.000000000 +0300
@@ -390,6 +390,9 @@
     int progress_end;
     bool wps_loaded;
     bool peak_meter_enabled;
+    int line_xpos, line_ypos, line_width;
+    int line_font, line_font_prev;
+    int line_fgcolor, line_fgcolor_prev;
 };
 
 /* initial setup of wps_data */
diff -u -r1.27 screen_access.h
--- apps/screen_access.h	1 Jul 2006 10:14:27 -0000	1.27
+++ apps/screen_access.h	29 Sep 2006 11:10:05 -0000
@@ -116,6 +118,7 @@
 #endif
     void (*init)(void);
     void (*puts_scroll)(int x, int y, const unsigned char *string);
+    void (*puts_customline_scroll)(int i, const unsigned char *string);
     void (*scroll_speed)(int speed);
     void (*scroll_delay)(int ms);
     void (*stop_scroll)(void);
diff -u -r1.26 screen_access.c
--- apps/screen_access.c	1 Jul 2006 10:14:26 -0000	1.26
+++ apps/screen_access.c	29 Sep 2006 11:11:44 -0000
@@ -176,6 +176,7 @@
 
             screen->init=&lcd_init;
             screen->puts_scroll=&lcd_puts_scroll;
+            screen->puts_customline_scroll=&lcd_puts_customline_scroll;
             screen->stop_scroll=&lcd_stop_scroll;
             screen->clear_display=&lcd_clear_display;
 #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
diff -u -r1.68 lcd.h
--- firmware/export/lcd.h	12 Aug 2006 09:27:26 -0000	1.68
+++ firmware/export/lcd.h	29 Sep 2006 11:12:31 -0000
@@ -66,6 +66,9 @@
 extern void lcd_stop_scroll(void);
 extern void lcd_scroll_speed(int speed);
 extern void lcd_scroll_delay(int ms);
+extern void lcd_puts_customline_scroll(int i, const unsigned char *string);
+extern void lcd_puts_customline_scroll_style_offset(int i, const unsigned char *string,
+											        int style, int offset);
 extern void lcd_puts_scroll(int x, int y, const unsigned char* string);
 extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
                                   int style);
@@ -345,6 +354,13 @@
     bool bidir;
     bool invert; /* invert the scrolled text */
     long start_tick;
+    /* Custome line arguments */
+    bool customline;
+    int line_font;
+    int line_xpos;
+    int line_ypos;
+    int line_width;
+    int line_fgcolor;
 };
 #else /* !HAVE_LCD_BITMAP */
 
diff -u -r1.39 lcd-16bit.c
--- firmware/drivers/lcd-16bit.c	25 Sep 2006 12:45:13 -0000	1.39
+++ firmware/drivers/lcd-16bit.c	29 Sep 2006 11:13:57 -0000
@@ -837,6 +850,77 @@
     bidir_limit = percent;
 }
 
+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 = &scroll[i];
+    
+    s->customline = true;
+    s->line_font = curfont;
+    s->line_xpos = lcd_getxmargin();
+    s->line_ypos = lcd_getymargin();
+    s->line_fgcolor = lcd_get_foreground();
+    s->line_width = lcd_get_custom_width()-lcd_getxmargin();
+
+    s->start_tick = current_tick + scroll_delay;
+    s->invert = false;
+    if (style & STYLE_INVERT) {
+        s->invert = true;
+        lcd_puts_style_offset(0,0,string,STYLE_INVERT,offset);
+    }
+    else
+        lcd_puts_offset(0,0,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 ( bidir_limit ) {
+            s->bidir = s->width < (lcd_get_custom_width() - xmargin) *
+                (100 + 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, lcd_get_custom_width()/2);
+
+        s->len = utf8length(string);
+        s->offset = offset;
+        s->startx = xmargin + xmargin * s->width / s->len;
+        s->backward = false;
+        scrolling_lines |= (1<<i);
+    }
+    else
+        /* force a bit switch-off since it doesn't scroll */
+        scrolling_lines &= ~(1<<i);
+}
+
 void lcd_puts_scroll(int x, int y, const unsigned char *string)
 {
     lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -917,6 +1001,7 @@
     int index;
     int xpos, ypos;
     int lastmode;
+    int fgcolor_orig;
 
     /* initialize scroll struct array */
     scrolling_lines = 0;
@@ -932,7 +1017,15 @@
             /* check pause */
             if (TIME_BEFORE(current_tick, s->start_tick))
                 continue;
-
+            
+            if (s->customline) {
+            	fgcolor_orig = lcd_get_foreground(); 
+            	lcd_setfont(s->line_font);
+            	lcd_set_foreground(s->line_fgcolor);
+            	lcd_setmargins(s->line_xpos, s->line_ypos);
+            	lcd_set_custom_width(s->line_width);
+            }
+            	
             if (s->backward)
                 s->offset -= scroll_step;
             else
@@ -941,6 +1032,11 @@
             pf = font_get(curfont);
             xpos = s->startx;
             ypos = ymargin + index * pf->height;
+            
+            if (s->customline) {
+            	xpos = s->line_xpos;
+            	ypos = s->line_ypos;
+            }
 
             if (s->bidir) { /* scroll bidirectional */
                 if (s->offset <= 0) {
@@ -990,6 +1067,10 @@
             drawmode = lastmode;
             lcd_update_rect(xpos, ypos, lcd_get_custom_width() - xpos, 
             				pf->height);
+            				
+            if (s->customline) {
+            	lcd_set_foreground(fgcolor_orig);
+            }
         }
 
         sleep(scroll_ticks);
