Index: apps/gui/gwps-common.c
===================================================================
--- apps/gui/gwps-common.c.orig
+++ apps/gui/gwps-common.c
@@ -1405,7 +1405,55 @@ static char *get_token_value(struct gui_
         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;
     }
@@ -1718,7 +1766,8 @@ static bool update_curr_subline(struct g
    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)
@@ -1731,7 +1780,8 @@ static void write_line(struct screen *di
     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) {
@@ -1741,7 +1791,12 @@ static void write_line(struct screen *di
     else {
         left_width = 0;
     }
-    left_xpos = display->getleftmargin();
+    if(customline){
+        left_xpos = data->line_xpos;
+    }
+    else {
+        left_xpos = display->getleftmargin();
+    }
 
     if (format_align->center != 0) {
         display->getstringsize((unsigned char *)format_align->center,
@@ -1750,8 +1805,13 @@ static void write_line(struct screen *di
     else {
         center_width = 0;
     }
-    center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2;
-
+    if(customline){
+        center_xpos=(data->line_width - center_width) / 2 + data->line_xpos;
+    }
+    else {
+        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);
@@ -1759,7 +1819,12 @@ static void write_line(struct screen *di
     else {
         right_width = 0;
     }
-    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
@@ -1847,40 +1912,82 @@ static void write_line(struct screen *di
     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
-    {
+    if(customline){
+       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 line first */
-        display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
-        display->fillrect(0, ypos, display->width, string_height);
-        display->set_drawmode(DRMODE_SOLID);
+           /* 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_scroll(0, line, (unsigned char *)"");
+           /* 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 {
+       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 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
 
-        /* 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);
-        }
+           /* 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);
+           }
+       }
     }
 }
 
@@ -1907,6 +2014,13 @@ bool gui_wps_refresh(struct gui_wps *gwp
 
     bool update_line, new_subline_refresh;
 
+#ifdef HAVE_LCD_COLOR
+    int fgcolor_save;
+    if(display->depth>2){
+    	fgcolor_save=display->get_foreground();
+    }
+#endif
+    
 #ifdef HAVE_LCD_BITMAP
     gui_wps_statusbar_draw(gwps, true);
 
@@ -2020,10 +2134,10 @@ bool gui_wps_refresh(struct gui_wps *gwp
                 /* 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);
         }
     }
 
@@ -2070,6 +2184,12 @@ bool gui_wps_refresh(struct gui_wps *gwp
     }
 #endif
 
+#ifdef HAVE_LCD_COLOR
+    if(display->depth>2){
+        display->set_foreground(fgcolor_save);
+    }
+#endif
+
     return true;
 }
 
Index: apps/gui/gwps.h
===================================================================
--- apps/gui/gwps.h.orig
+++ apps/gui/gwps.h
@@ -211,6 +211,13 @@ enum wps_token_type {
     /* Albumart */
     WPS_TOKEN_ALBUMART_DISPLAY,
     WPS_TOKEN_ALBUMART_FOUND,
+    
+    /* customline */
+    WPS_TOKEN_CUSTOMLINE_XPOS,
+    WPS_TOKEN_CUSTOMLINE_YPOS,
+    WPS_TOKEN_CUSTOMLINE_WIDTH,
+    WPS_TOKEN_CUSTOMLINE_FONT,
+    WPS_TOKEN_CUSTOMLINE_COLOR,
 #endif
 
     /* Metadata */
@@ -375,6 +382,12 @@ struct wps_data
     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 */
Index: apps/screen_access.h
===================================================================
--- apps/screen_access.h.orig
+++ apps/screen_access.h
@@ -69,7 +69,7 @@ struct screen
     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);
@@ -128,6 +128,10 @@ struct screen
     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);
Index: apps/screen_access.c
===================================================================
--- apps/screen_access.c.orig
+++ apps/screen_access.c
@@ -47,6 +47,7 @@ void screen_init(struct screen * screen,
             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;
@@ -98,7 +99,9 @@ void screen_init(struct screen * screen,
             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;
@@ -125,6 +128,7 @@ void screen_init(struct screen * screen,
             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;
@@ -178,7 +182,9 @@ void screen_init(struct screen * screen,
             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;
Index: firmware/export/lcd.h
===================================================================
--- firmware/export/lcd.h.orig
+++ firmware/export/lcd.h
@@ -62,6 +62,7 @@ extern void lcd_setmargins(int leftmargi
 extern int  lcd_getleftmargin(void);
 extern int  lcd_getrightmargin(void);
 extern int  lcd_getymargin(void);
+extern int  lcd_getmarginwidth(void);
 extern int  lcd_getstringsize(const unsigned char *str, int *w, int *h);
 
 extern void lcd_update(void);
@@ -81,6 +82,14 @@ extern void lcd_puts_scroll(int x, int y
 extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
                                   int style);
 
+extern void lcd_puts_customline_scroll(int i, const unsigned char *string);
+extern void lcd_puts_customline_scroll_style(int i, const unsigned char *str,
+        int style);
+extern void lcd_puts_customline_scroll_offset(int i, const unsigned char *string,
+        int offset);
+extern void lcd_puts_customline_scroll_style_offset(int i, const unsigned char *string,
+														int style, int offset);
+
 #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR)
 extern void lcd_yuv_blit(unsigned char * const src[3],
                          int src_x, int src_y, int stride,
@@ -314,6 +323,11 @@ extern void lcd_puts_style_offset(int x,
 extern void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
                                   int style, int offset);
 
+extern void lcd_puts_customline_scroll_offset(int i, const unsigned char *string,
+        int offset);
+extern void lcd_puts_customline_scroll_style_offset(int i, const unsigned char *string,
+        int style, int offset);
+
 /* low level drawing function pointer arrays */
 #if LCD_DEPTH >= 8
 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs;
@@ -397,6 +411,13 @@ struct scrollinfo {
     int y_margin;
     int left_margin;
     int right_margin;
+	/* Custome line arguments */
+	bool customline;
+	int line_font;
+	int line_xpos;
+	int line_ypos;
+	int line_width;
+    int fgcolor;
 };
 
 #endif /* __LCD_H__ */
Index: firmware/drivers/lcd-16bit.c
===================================================================
--- firmware/drivers/lcd-16bit.c.orig
+++ firmware/drivers/lcd-16bit.c
@@ -159,6 +159,11 @@ int lcd_getymargin(void)
     return ymargin;
 }
 
+int lcd_getmarginwidth(void)
+{
+	return lcd_getrightmargin()-lcd_getleftmargin();
+}
+
 void lcd_setfont(int newfont)
 {
     curfont = newfont;
@@ -852,6 +857,69 @@ void lcd_puts_style_offset(int x, int y,
     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 */
+	scrolling_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 ***/
 
 /* Reverse the invert setting of the scrolling line (if any) at given char
@@ -893,6 +961,90 @@ void lcd_bidir_scroll(int percent)
     bidir_limit = percent;
 }
 
+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 = &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 + scroll_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 ( bidir_limit ) {
+            s->bidir = s->width < (s->line_width) *
+                (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, 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;
+        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);
@@ -918,8 +1070,17 @@ void lcd_puts_scroll_style_offset(int x,
     
     s = &scroll[y];
 
+	// 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 + scroll_delay;
     s->invert = false;
+    s->invert = false;
+    
     if (style & STYLE_INVERT) {
         s->invert = true;
         lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset);
@@ -978,7 +1139,8 @@ static void scroll_thread(void)
     int index;
     int xpos, ypos;
     int lastmode;
-
+    int fgcolor_save;
+    
     /* initialize scroll struct array */
     scrolling_lines = 0;
 
@@ -997,15 +1159,25 @@ static void scroll_thread(void)
             /* check pause */
             if (TIME_BEFORE(current_tick, s->start_tick))
                 continue;
-
+		
             if (s->backward)
                 s->offset -= scroll_step;
             else
                 s->offset += scroll_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) {
@@ -1027,12 +1199,17 @@ static void scroll_thread(void)
                     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, s->right_margin);
+            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);
+            
+            lcd_set_foreground(fgcolor_save);
         }
 
         sleep(scroll_ticks);
Index: firmware/drivers/lcd-remote-2bit-vi.c
===================================================================
--- firmware/drivers/lcd-remote-2bit-vi.c.orig
+++ firmware/drivers/lcd-remote-2bit-vi.c
@@ -151,6 +151,11 @@ int lcd_remote_getymargin(void)
     return ymargin;
 }
 
+int lcd_remote_getmarginwidth(void)
+{
+	return lcd_remote_getrightmargin()-lcd_remote_getleftmargin();
+}
+
 void lcd_remote_setfont(int newfont)
 {
     curfont = newfont;
@@ -1005,6 +1010,41 @@ void lcd_remote_puts_offset(int x, int y
     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,
@@ -1024,13 +1064,42 @@ void lcd_remote_puts_style_offset(int x,
     ypos = ymargin + y*h;
     drawmode = (style & STYLE_INVERT) ?
                (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_remote_putsxyofs(xpos, ypos, offset, str, 0);
+    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_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 */
+	scrolling_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 ***/
 
 /* Reverse the invert setting of the scrolling line (if any) at given char
@@ -1096,7 +1165,14 @@ void lcd_remote_puts_scroll_style_offset
     if(y>=SCROLLABLE_LINES) return;
 
     s = &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 + scroll_delay;
     s->invert = false;
     if (style & STYLE_INVERT) {
@@ -1204,14 +1280,24 @@ static void scroll_thread(void)
             if (TIME_BEFORE(current_tick, s->start_tick))
                 continue;
 
+			if (s->customline) {
+				lcd_remote_setfont(s->line_font);
+			}
+			
             if (s->backward)
                 s->offset -= scroll_step;
             else
                 s->offset += scroll_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) {
@@ -1236,11 +1322,10 @@ static void scroll_thread(void)
             lastmode = drawmode;
             drawmode = s->invert ?
                        (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line, s->right_margin);
+            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);
-        }
-
+            lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height);			
+       }
 
         next_tick += scroll_ticks;
         delay = next_tick - current_tick - 1;
@@ -1252,6 +1337,7 @@ static void scroll_thread(void)
     }
 }
 
+
 /* LCD init */
 void lcd_remote_init(void)
 {
@@ -1265,3 +1351,87 @@ void lcd_remote_init(void)
                   sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
 		  IF_COP(, CPU, false));
 }
+
+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 = &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 + scroll_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 ( bidir_limit ) {
+			s->bidir = s->width < (s->line_width) *
+				(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_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;
+		scrolling_lines |= (1<<i);
+	}
+	else 
+		/* force a bit switch-off since it doesn't scroll */
+		scrolling_lines &= ~(1<<i);
+}
+
Index: firmware/export/lcd-remote.h
===================================================================
--- firmware/export/lcd-remote.h.orig
+++ firmware/export/lcd-remote.h
@@ -125,6 +125,7 @@ extern void lcd_remote_putc(int x, int y
 extern void lcd_remote_stop_scroll(void);
 extern void lcd_remote_scroll_speed(int speed);
 extern void lcd_remote_scroll_delay(int ms);
+
 extern void lcd_remote_puts_scroll(int x, int y, const unsigned char *str);
 extern void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *str,
                                          int style);
@@ -134,6 +135,13 @@ extern void lcd_remote_puts_scroll_style
                                                 const unsigned char *string,
                                                 int style, int offset);
 
+extern void lcd_remote_puts_customline_scroll(int i, const unsigned char *string);
+extern void lcd_remote_puts_customline_scroll_style(int i, const unsigned char *str,
+        int style);
+extern void lcd_remote_puts_customline_scroll_offset(int i, const unsigned char *string,
+        int offset);
+extern void lcd_remote_puts_customline_scroll_style_offset(int i, const unsigned char *string,
+														int style, int offset);
 extern void lcd_remote_update(void);
 extern void lcd_remote_update_rect(int x, int y, int width, int height);
 
@@ -146,6 +154,7 @@ extern void lcd_remote_setmargins(int le
 extern int  lcd_remote_getleftmargin(void);
 extern int  lcd_remote_getrightmargin(void);
 extern int  lcd_remote_getymargin(void);
+extern int  lcd_remote_getmarginwidth(void);
 extern void lcd_remote_setfont(int font);
 extern int lcd_remote_getcurfont(void);
 extern void lcd_remote_setfont(int font);
Index: firmware/drivers/lcd-2bit-vert.c
===================================================================
--- firmware/drivers/lcd-2bit-vert.c.orig
+++ firmware/drivers/lcd-2bit-vert.c
@@ -150,6 +150,11 @@ int lcd_getymargin(void)
     return ymargin;
 }
 
+int lcd_getmarginwidth(void)
+{
+	return lcd_getrightmargin()-lcd_getleftmargin();
+}
+
 void lcd_setfont(int newfont)
 {
     curfont = newfont;
@@ -1032,6 +1037,68 @@ void lcd_puts_style_offset(int x, int y,
     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);
+}
+
+/* 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 */
+	scrolling_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;
+}
 /*** scrolling ***/
 
 /* Reverse the invert setting of the scrolling line (if any) at given char
@@ -1098,14 +1165,22 @@ void lcd_puts_scroll_style_offset(int x,
 
     s = &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 + scroll_delay;
     s->invert = false;
-    if (style & STYLE_INVERT) {
-        s->invert = true;
-        lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset);
-    }
-    else
-        lcd_puts_offset(x,y,string,offset);
+	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);
 
@@ -1158,7 +1233,7 @@ static void scroll_thread(void)
     int index;
     int xpos, ypos;
     int lastmode;
-
+	
     /* initialize scroll struct array */
     scrolling_lines = 0;
 
@@ -1174,14 +1249,24 @@ static void scroll_thread(void)
             if (TIME_BEFORE(current_tick, s->start_tick))
                 continue;
 
+            if (s->customline) {
+				lcd_setfont(s->line_font);
+			}
+						
             if (s->backward)
                 s->offset -= scroll_step;
             else
                 s->offset += scroll_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) {
@@ -1206,11 +1291,7 @@ static void scroll_thread(void)
             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);
         }
@@ -1218,3 +1299,86 @@ static void scroll_thread(void)
         sleep(scroll_ticks);
     }
 }
+
+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 = &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 + scroll_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 ( bidir_limit ) {
+			s->bidir = s->width < (s->line_width) *
+				(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, 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;
+		scrolling_lines |= (1<<i);
+	}
+	else 
+		/* force a bit switch-off since it doesn't scroll */
+		scrolling_lines &= ~(1<<i);
+}
Index: firmware/drivers/lcd-remote-1bit-v.c
===================================================================
--- firmware/drivers/lcd-remote-1bit-v.c.orig
+++ firmware/drivers/lcd-remote-1bit-v.c
@@ -101,6 +101,10 @@ int lcd_remote_getymargin(void)
     return ymargin;
 }
 
+int lcd_remote_getmarginwidth(void)
+{
+	return lcd_remote_getrightmargin()-lcd_remote_getleftmargin();
+}
 
 void lcd_remote_setfont(int newfont)
 {
@@ -695,6 +699,70 @@ void lcd_remote_puts_style_offset(int x,
     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_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;
+    }
+}
+
+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 */
+	scrolling_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 ***/
 
 /* Reverse the invert setting of the scrolling line (if any) at given char
@@ -867,15 +935,24 @@ static void scroll_thread(void)
             if (TIME_BEFORE(current_tick, s->start_tick))
                 continue;
 
+			if (s->customline) {
+				lcd_remote_setfont(s->line_font);
+			}
+			
             if (s->backward)
                 s->offset -= scroll_step;
             else
                 s->offset += scroll_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) {
                     /* at beginning of line */
@@ -899,11 +976,7 @@ static void scroll_thread(void)
             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);
         }
@@ -931,3 +1004,86 @@ void lcd_remote_init(void)
                   sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
 		  IF_COP(, CPU, false));
 }
+
+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 = &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 + scroll_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 ( bidir_limit ) {
+			s->bidir = s->width < (s->line_width) *
+				(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_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;
+		scrolling_lines |= (1<<i);
+	}
+	else 
+		/* force a bit switch-off since it doesn't scroll */
+		scrolling_lines &= ~(1<<i);
+}
Index: apps/gui/wps_parser.c
===================================================================
--- apps/gui/wps_parser.c.orig
+++ apps/gui/wps_parser.c
@@ -120,8 +120,43 @@ static int parse_albumart_load(const cha
         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 HAVE_LCD_COLOR
+/*
+ * Helper function to convert a string of 6 hex digits to a native colour
+ */
+
+#define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
+                                                   (toupper(c)) - 'A' + 10)
+
+static int hex_to_rgb(const char* hex)
+{   int ok = 1;
+    int i;
+    int red, green, blue;
+
+    if (strlen(hex) == 6) {
+        for (i=0; i < 6; i++ ) {
+           if (!isxdigit(hex[i])) {
+              ok=0;
+              break;
+           }
+        }
+
+        if (ok) {
+            red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]);
+            green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]);
+            blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]);
+            return LCD_RGBPACK(red,green,blue);
+        }
+    }
+
+    return 0;
+}
+#endif /* HAVE_LCD_COLOR */
+
 /* array of available tags - those with more characters have to go first
    (e.g. "xl" and "xd" before "x"). It needs to end with the unknown token. */
 static const struct wps_tag all_tags[] = {
@@ -271,6 +306,8 @@ static const struct wps_tag all_tags[] =
     { 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 }
@@ -628,6 +665,68 @@ static int parse_scrollmargins(const cha
     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 );
+}
+
 static int parse_albumart_load(const char *wps_bufptr,
                           struct wps_token *token,
                           struct wps_data *wps_data)
@@ -1099,6 +1198,13 @@ void wps_data_init(struct wps_data *wps_
     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)
