Horizontal scrolling patch by Shachar Liberman


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8412 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/list.c b/apps/gui/list.c
index 83a1fbf..2ae5f99 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -37,7 +37,8 @@
 #define SCROLL_LIMIT 2
 #endif
 
-
+static int offset_step = 15;
+static bool offset_outof_view = false;
 
 void gui_list_init(struct gui_list * gui_list,
     list_get_name callback_get_item_name,
@@ -53,6 +54,7 @@
     gui_list->limit_scroll = false;
     gui_list->data=data;
     gui_list->cursor_flash_state=false;
+    gui_list->offsetval = 0;
 }
 
 void gui_list_set_display(struct gui_list * gui_list, struct screen * display)
@@ -179,14 +181,47 @@
         entry_name = gui_list->callback_get_item_name(current_item,
                                                       gui_list->data,
                                                       entry_buffer);
-        if(current_item == gui_list->selected_item)
-        {
-            /* The selected item must be displayed scrolling */
+
 #ifdef HAVE_LCD_BITMAP
-            if (global_settings.invert_cursor)/* Display inverted-line-style*/
-                display->puts_scroll_style(0, i, entry_name, STYLE_INVERT);
+    /* position the string at the right offset place */
+    int item_offset;
+    int str_width,h;
+    display->getstringsize(entry_name, &str_width, &h);
+
+    if (offset_outof_view)
+        item_offset = gui_list->offsetval;
+    else
+        /* if text is smaller then view */
+        if (str_width <= display->width - text_pos)
+            item_offset = 0;
+        else
+            /* if text got out of view  */
+            if (gui_list->offsetval > str_width - (display->width - text_pos))
+                item_offset = str_width - (display->width - text_pos);
             else
-                display->puts_scroll(0, i, entry_name);
+                item_offset = gui_list->offsetval;
+                
+#endif        
+
+        if(current_item == gui_list->selected_item) {
+        /* The selected item must be displayed scrolling */
+#ifdef HAVE_LCD_BITMAP
+            if (global_settings.invert_cursor) /* Display inverted-line-style*/
+
+                /* if text got out of view */
+                if (item_offset > str_width - (display->width - text_pos))
+                    /* don't scroll */
+                    display->puts_style_offset(0, i, entry_name, STYLE_INVERT,item_offset);
+                else
+                    display->puts_scroll_style_offset(0, i, entry_name, STYLE_INVERT,item_offset);
+                    
+            else  /*  if (global_settings.invert_cursor) */
+            
+                if (item_offset > str_width - (display->width - text_pos))
+                    display->puts_offset(0, i, entry_name,item_offset); 
+                else
+                    display->puts_scroll_offset(0, i, entry_name,item_offset);
+
 #else
                 display->puts_scroll(text_pos, i, entry_name);
 #endif
@@ -197,7 +232,7 @@
         else
         {/* normal item */
 #ifdef HAVE_LCD_BITMAP
-            display->puts(0, i, entry_name);
+            display->puts_offset(0, i, entry_name,item_offset);
 #else
             display->puts(text_pos, i, entry_name);
 #endif
@@ -229,6 +264,40 @@
     gui_textarea_update(display);
 }
 
+#ifdef HAVE_LCD_BITMAP
+void gui_list_screen_scroll_step(int ofs)
+{
+     offset_step = ofs;
+}
+
+void gui_list_screen_scroll_out_of_view(bool enable)
+{
+    if (enable)
+        offset_outof_view = true;
+    else
+        offset_outof_view = false;
+}
+
+void gui_list_offset_right(struct gui_list * gui_list)
+{
+    /* there should be a callback to find out what's the longest item on the list,
+     * and then, by finding out the width with get_stringsize, we would stop the 
+     * list from scrolling at that point */
+     
+    gui_list->offsetval+=offset_step;
+    if (gui_list->offsetval > 1000)
+        gui_list->offsetval = 1000;
+}
+
+void gui_list_offset_left(struct gui_list * gui_list)
+{
+    gui_list->offsetval-=offset_step;
+    if (gui_list->offsetval < 0)
+        gui_list->offsetval = 0;
+
+}
+#endif /* HAVE_LCD_BITMAP */
+
 void gui_list_select_item(struct gui_list * gui_list, int item_number)
 {
     if( item_number > gui_list->nb_items-1 || item_number < 0 )
@@ -384,6 +453,7 @@
     FOR_NB_SCREENS(i)
     {
         gui_list_set_nb_items(&(lists->gui_list[i]), nb_items);
+        lists->gui_list[i].offsetval = 0;
     }
 }
 void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback)
@@ -432,6 +502,22 @@
                                   screens[screen].nb_lines);
 }
 
+#ifdef HAVE_LCD_BITMAP
+void gui_synclist_offset_right(struct gui_synclist * lists)
+{
+    int i;
+    FOR_NB_SCREENS(i)
+        gui_list_offset_right(&(lists->gui_list[i]));
+}
+
+void gui_synclist_offset_left(struct gui_synclist * lists)
+{
+    int i;
+    FOR_NB_SCREENS(i)
+        gui_list_offset_left(&(lists->gui_list[i]));
+}
+#endif /* HAVE_LCD_BITMAP */
+
 void gui_synclist_select_previous_page(struct gui_synclist * lists,
                                        enum screen_type screen)
 {
@@ -502,6 +588,31 @@
             gui_synclist_select_next(lists);
             gui_synclist_draw(lists);
             return LIST_NEXT;
+            
+#ifdef LIST_PGRIGHT
+        case LIST_PGRIGHT:
+        case LIST_PGRIGHT | BUTTON_REPEAT:
+#ifdef LIST_RC_PGRIGHT
+        case LIST_RC_PGRIGHT:
+        case LIST_RC_PGRIGHT | BUTTON_REPEAT:
+#endif
+        gui_synclist_offset_right(lists);
+        gui_synclist_draw(lists);
+        return true;
+#endif
+
+#ifdef LIST_PGLEFT
+        case LIST_PGLEFT:
+        case LIST_PGLEFT | BUTTON_REPEAT:
+#ifdef LIST_RC_PGLEFT
+        case LIST_RC_PGLEFT:
+        case LIST_RC_PGLEFT | BUTTON_REPEAT:
+#endif
+        gui_synclist_offset_left(lists);
+        gui_synclist_draw(lists);
+        return true;
+#endif
+
 /* for pgup / pgdown, we are obliged to have a different behaviour depending on the screen
  * for which the user pressed the key since for example, remote and main screen doesn't
  * have the same number of lines*/
diff --git a/apps/gui/list.h b/apps/gui/list.h
index 25fb07d..e177f5e 100644
--- a/apps/gui/list.h
+++ b/apps/gui/list.h
@@ -33,12 +33,16 @@
 #define LIST_PREV      BUTTON_UP
 #define LIST_PGUP      (BUTTON_ON | BUTTON_UP)
 #define LIST_PGDN      (BUTTON_ON | BUTTON_DOWN)
+#define LIST_PGRIGHT   (BUTTON_ON | BUTTON_RIGHT)
+#define LIST_PGLEFT    (BUTTON_ON | BUTTON_LEFT)
 
 #ifdef CONFIG_REMOTE_KEYPAD
 #define LIST_RC_NEXT   BUTTON_RC_FF
 #define LIST_RC_PREV   BUTTON_RC_REW
 #define LIST_RC_PGUP   BUTTON_RC_SOURCE
 #define LIST_RC_PGDN   BUTTON_RC_BITRATE
+#define LIST_RC_PGRIGHT (BUTTON_RC_VOL_UP)
+#define LIST_RC_PGLEFT (BUTTON_RC_VOL_DOWN)
 #endif /* CONFIG_REMOTE_KEYPAD */
 
 #elif CONFIG_KEYPAD == RECORDER_PAD
@@ -46,6 +50,8 @@
 #define LIST_PREV      BUTTON_UP
 #define LIST_PGUP      (BUTTON_ON | BUTTON_UP)
 #define LIST_PGDN      (BUTTON_ON | BUTTON_DOWN)
+#define LIST_PGRIGHT   (BUTTON_ON | BUTTON_RIGHT)
+#define LIST_PGLEFT    (BUTTON_ON | BUTTON_LEFT)
 
 #ifdef CONFIG_REMOTE_KEYPAD
 #define LIST_RC_NEXT   BUTTON_RC_RIGHT
@@ -64,6 +70,8 @@
 #elif CONFIG_KEYPAD == ONDIO_PAD
 #define LIST_NEXT      BUTTON_DOWN
 #define LIST_PREV      BUTTON_UP
+#define LIST_PGRIGHT   (BUTTON_MENU | BUTTON_RIGHT)
+#define LIST_PGLEFT    (BUTTON_MENU | BUTTON_LEFT)
 
 #elif (CONFIG_KEYPAD == IPOD_4G_PAD)
 #define LIST_NEXT      BUTTON_SCROLL_FWD
@@ -78,6 +86,8 @@
 #define LIST_PREV      BUTTON_UP
 #define LIST_PGUP      (BUTTON_ON | BUTTON_UP)
 #define LIST_PGDN      (BUTTON_ON | BUTTON_DOWN)
+#define LIST_PGRIGHT   (BUTTON_ON | BUTTON_RIGHT)
+#define LIST_PGLEFT    (BUTTON_ON | BUTTON_LEFT)
 
 #elif CONFIG_KEYPAD == IAUDIO_X5_PAD
 #define LIST_NEXT      BUTTON_DOWN
@@ -116,12 +126,14 @@
  *             a buffer when it's not necessary)
  * Returns a pointer to a string that contains the text to display
  */
+
 typedef char * list_get_name(int selected_item,
                              void * data,
                              char *buffer);
 
 struct gui_list
 {
+    int offsetval; /* value of screen offset */
     int nb_items;
     int selected_item;
     bool cursor_flash_state;
@@ -222,6 +234,13 @@
  * (Item 0 gets selected if the end of the list is reached)
  * - gui_list : the list structure
  */
+
+extern void gui_list_screen_scroll_step(int ofs);
+/* parse global setting to static int */
+
+extern void gui_list_screen_scroll_out_of_view(bool enable);
+/* parse global setting to static bool */
+ 
 extern void gui_list_select_next(struct gui_list * gui_list);
 
 /*
@@ -236,6 +255,22 @@
  * - gui_list : the list structure
  * - nb_lines : the number of lines to try to move the cursor
  */
+ 
+extern void gui_list_offset_right(struct gui_list * gui_list);
+
+/*
+ * Makes all the item in the list scroll by one step to the right.
+ * Should stop increasing the value when reaching the widest item value 
+ * in the list.
+ */
+
+extern void gui_list_offset_left(struct gui_list * gui_list);
+
+/*
+ * Makes all the item in the list scroll by one step to the left.
+ * stops at starting position.
+ */ 
+ 
 extern void gui_list_select_next_page(struct gui_list * gui_list,
                                       int nb_lines);
 
@@ -312,6 +347,8 @@
                                      int item_number);
 extern void gui_synclist_select_next(struct gui_synclist * lists);
 extern void gui_synclist_select_previous(struct gui_synclist * lists);
+extern void gui_synclist_offset_right(struct gui_synclist * lists);
+extern void gui_synclist_offset_left(struct gui_synclist * lists);
 extern void gui_synclist_select_next_page(struct gui_synclist * lists,
                                           enum screen_type screen);
 extern void gui_synclist_select_previous_page(struct gui_synclist * lists,
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 8feccef..008f016 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -3557,3 +3557,14 @@
 voice: "Brightness"
 new:
 
+id: LANG_SCREEN_SCROLL_VIEW
+desc: should lines scroll out of the screen
+eng: "Screen Scrolls Out Of View"
+voice: "Screen Scrolls Out Of View"
+new:
+
+id: LANG_SCREEN_SCROLL_STEP
+desc: Pixels to advance per Screen scroll
+eng: "Screen Scroll Step Size"
+voice: "Screen Scroll Step Size"
+new:
diff --git a/apps/screen_access.c b/apps/screen_access.c
index 56fe131..b47bd10 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -66,10 +66,16 @@
             screen->scroll_speed=&lcd_remote_scroll_speed;
             screen->scroll_delay=&lcd_remote_scroll_delay;
             screen->scroll_step=&lcd_remote_scroll_step;
-            screen->puts_scroll_style=&lcd_remote_puts_scroll_style;
             screen->invertscroll=&lcd_remote_invertscroll;
-#endif /* LCD_REMOTE_DEPTH > 1 */
 
+            screen->puts_scroll_style=&lcd_remote_puts_scroll_style;          
+            screen->puts_scroll_offset=&lcd_remote_puts_scroll_offset;
+            screen->puts_scroll_style_offset=&lcd_remote_puts_scroll_style_offset;
+            
+            screen->puts_offset=&lcd_remote_puts_offset;
+            screen->puts_style=&lcd_remote_puts_style;
+            screen->puts_style_offset=&lcd_remote_puts_style_offset;
+#endif /* LCD_REMOTE_DEPTH > 1 */
 #if 0 /* no charcell remote LCDs so far */
             screen->width=11;
             screen->height=2;
@@ -93,6 +99,7 @@
             screen->backlight_on=&remote_backlight_on;
             screen->backlight_off=&remote_backlight_off;
             break;
+            
 #endif /* HAVE_REMOTE_LCD */
 
         case SCREEN_MAIN:
@@ -128,8 +135,14 @@
             screen->scroll_speed=&lcd_scroll_speed;
             screen->scroll_delay=&lcd_scroll_delay;
             screen->scroll_step=&lcd_scroll_step;
-            screen->puts_scroll_style=&lcd_puts_scroll_style;
             screen->invertscroll=&lcd_invertscroll;
+
+            screen->puts_scroll_offset=&lcd_puts_scroll_offset;
+            screen->puts_scroll_style_offset=&lcd_puts_scroll_style_offset;
+            
+            screen->puts_offset=&lcd_puts_offset;
+            screen->puts_style_offset=&lcd_puts_style_offset;
+            screen->puts_style=&lcd_puts_style;
 #endif /* HAVE_LCD_BITMAP */
 
 #ifdef HAVE_LCD_CHARCELLS
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 8eb8915..81d0675 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -69,10 +69,23 @@
     void (*setfont)(int newfont);
     int (*getstringsize)(const unsigned char *str, int *w, int *h);
     void (*putsxy)(int x, int y, const unsigned char *str);
-
     void (*scroll_step)(int pixels);
-    void (*puts_scroll_style)(int x, int y,
-                              const unsigned char *string, int style);
+
+
+    void (*puts_scroll_style)(int x, int y, const unsigned char *string,
+                                 int style);
+    void (*puts_scroll_offset)(int x, int y, const unsigned char *string,
+                                 int offset);
+    void (*puts_scroll_style_offset)(int x, int y, const unsigned char *string,
+                                  int style, int offset);
+                                  
+    void (*puts_offset)(int x, int y, const unsigned char *str, int offset);
+    void (*puts_style)(int x, int y, const unsigned char *string, int style);
+    void (*puts_style_offset)(int x, int y, const unsigned char *str, 
+                                  int style, int offset);   
+
+                             
+              
     void (*mono_bitmap)(const unsigned char *src,
                         int x, int y, int width, int height);
     void (*set_drawmode)(int mode);
diff --git a/apps/settings.c b/apps/settings.c
index 7088cee..ad81207 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -71,6 +71,7 @@
 #include "select.h"
 #include "statusbar.h"
 #include "splash.h"
+#include "list.h"
 
 #if CONFIG_CODEC == MAS3507D
 void dac_line_in(bool enable);
@@ -492,6 +493,15 @@
     {4, S_O(brightness), 9, "brightness", NULL }, 
 #endif
 
+#ifdef HAVE_LCD_BITMAP
+    {1, S_O(offset_out_of_view), false, "Screen Scrolls Out Of View", off_on },
+#if LCD_WIDTH > 127
+    {8, S_O(screen_scroll_step), 16, "screen scroll step", NULL }, /* 1...160 */
+#else
+    {7, S_O(screen_scroll_step), 16, "screen scroll step", NULL }, /* 1...112 */
+#endif
+#endif /* HAVE_LCD_BITMAP */
+
     /* If values are just added to the end, no need to bump the version. */
     /* new stuff to be added at the end */
 
@@ -957,6 +967,8 @@
         font_reset();
 
     lcd_scroll_step(global_settings.scroll_step);
+    gui_list_screen_scroll_step(global_settings.screen_scroll_step);
+    gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
 #else
     lcd_jump_scroll(global_settings.jump_scroll);
     lcd_jump_scroll_delay(global_settings.jump_scroll_delay * (HZ/10));
diff --git a/apps/settings.h b/apps/settings.h
index d60c39f..97e608d 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -319,6 +319,8 @@
     int bidir_limit;   /* bidir scroll length limit */
     int scroll_delay;  /* delay (in 1/10s) before starting scroll */
     int scroll_step;   /* pixels to advance per update */
+    bool offset_out_of_view; /* should lines scroll out of the screen */
+    int screen_scroll_step;   /* pixels to advance screen view*/
 
     /* auto bookmark settings */
     int autoloadbookmark;   /* auto load option: 0=off, 1=ask, 2=on */
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index 35b4d87..85d8986 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -53,6 +53,7 @@
 #include "rbunicode.h"
 #include "splash.h"
 #include "yesno.h"
+#include "list.h"
 
 #ifdef HAVE_LCD_BITMAP
 #include "peakmeter.h"
@@ -747,7 +748,6 @@
                    &lcd_scroll_speed, 1, 0, 15, NULL );
 }
 
-
 static bool scroll_delay(void)
 {
     int dummy = global_settings.scroll_delay * (HZ/10);
@@ -759,6 +759,20 @@
 }
 
 #ifdef HAVE_LCD_BITMAP
+static bool screen_scroll(void)
+{
+    bool rc = set_bool( str(LANG_SCREEN_SCROLL_VIEW), &global_settings.offset_out_of_view);
+    gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
+    return rc;
+}
+
+static bool screen_scroll_step(void)
+{
+    return set_int(str(LANG_SCREEN_SCROLL_STEP), "pixels", UNIT_PIXEL,
+                   &global_settings.screen_scroll_step,
+                   &gui_list_screen_scroll_step, 1, 1, LCD_WIDTH, NULL );
+}
+
 static bool scroll_step(void)
 {
     return set_int(str(LANG_SCROLL_STEP_EXAMPLE), "pixels", UNIT_PIXEL,
@@ -1500,15 +1514,19 @@
     bool result;
 
     static const struct menu_item items[] = {
-        { ID2P(LANG_SCROLL_SPEED),     scroll_speed    },
-        { ID2P(LANG_SCROLL_DELAY),    scroll_delay    },  
+        { ID2P(LANG_SCROLL_SPEED),        scroll_speed       },
+        { ID2P(LANG_SCROLL_DELAY),        scroll_delay       },  
 #ifdef HAVE_LCD_BITMAP
-        { ID2P(LANG_SCROLL_STEP),     scroll_step     },  
+        { ID2P(LANG_SCROLL_STEP),         scroll_step        },  
 #endif
-        { ID2P(LANG_BIDIR_SCROLL),    bidir_limit    },
+        { ID2P(LANG_BIDIR_SCROLL),        bidir_limit        },
 #ifdef HAVE_LCD_CHARCELLS
-        { ID2P(LANG_JUMP_SCROLL),    jump_scroll    },
-        { ID2P(LANG_JUMP_SCROLL_DELAY),    jump_scroll_delay    },
+        { ID2P(LANG_JUMP_SCROLL),         jump_scroll        },
+        { ID2P(LANG_JUMP_SCROLL_DELAY),   jump_scroll_delay  },
+#endif
+#ifdef HAVE_LCD_BITMAP
+        { ID2P(LANG_SCREEN_SCROLL_VIEW),  screen_scroll      },
+        { ID2P(LANG_SCREEN_SCROLL_STEP),  screen_scroll_step }, 
 #endif
     };
 
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c
index a2fe63e..a28cd2f 100644
--- a/firmware/drivers/lcd-h100-remote.c
+++ b/firmware/drivers/lcd-h100-remote.c
@@ -1143,6 +1143,17 @@
 
 void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style)
 {
+    lcd_remote_puts_style_offset(x, y, str, style, 0);
+}
+
+void lcd_remote_puts_offset(int x, int y, const unsigned char *str, int offset)
+{
+    lcd_remote_puts_style_offset(x, y, str, STYLE_DEFAULT, offset);
+}
+
+/* put a string at a given char position at a given style and with a given offset */
+void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, int style, int offset)
+{
     int xpos,ypos,w,h;
     int lastmode = drawmode;
 
@@ -1155,7 +1166,7 @@
     lcd_remote_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    lcd_remote_putsxy(xpos, ypos, str);
+    lcd_remote_putsxyofs(xpos, ypos, offset, str);
     drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
     lcd_remote_fillrect(xpos + w, ypos, LCD_REMOTE_WIDTH - (xpos + w), h);
     if (style & STYLE_INVERT)
@@ -1212,6 +1223,17 @@
 
 void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style)
 {
+    lcd_remote_puts_scroll_style_offset(x, y, string, style, 0);
+}
+ 
+void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset)
+{
+     lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset);
+}
+                                                
+void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string,
+                                                int style, int offset)
+{
     struct scrollinfo* s;
     int w, h;
 
@@ -1221,10 +1243,10 @@
     s->invert = false;
     if (style & STYLE_INVERT) {
         s->invert = true;
-        lcd_remote_puts_style(x,y,string,STYLE_INVERT);
+        lcd_remote_puts_style_offset(x,y,string,STYLE_INVERT,offset);
     }
     else
-        lcd_remote_puts(x,y,string);
+        lcd_remote_puts_offset(x,y,string,offset);
 
     lcd_remote_getstringsize(string, &w, &h);
 
@@ -1257,7 +1279,7 @@
         strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2);
 
         s->len = utf8length((char *)string);
-        s->offset = 0;
+        s->offset = offset;
         s->startx = x;
         s->backward = false;
         scrolling_lines |= (1<<y);
@@ -1267,6 +1289,7 @@
         scrolling_lines &= ~(1<<y);
 }
 
+
 static void scroll_thread(void)
 {
     struct font* pf;
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c
index 1199bf0..0df1a3c 100644
--- a/firmware/drivers/lcd-h100.c
+++ b/firmware/drivers/lcd-h100.c
@@ -1057,7 +1057,9 @@
 
 /*** line oriented text output ***/
 
-void lcd_puts_style(int x, int y, const unsigned char *str, int style)
+/* put a string at a given char position at a given style and with a given pixel position */
+void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style,
+                                                                   int offset)
 {
     int xpos,ypos,w,h;
     int lastmode = drawmode;
@@ -1071,7 +1073,7 @@
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    lcd_putsxy(xpos, ypos, str);
+    lcd_putsxyofs(xpos, ypos, offset, str);
     drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
     lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h);
     if (style & STYLE_INVERT)
@@ -1081,6 +1083,16 @@
     }
     drawmode = lastmode;
 }
+void lcd_puts_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_puts_style_offset(x, y, str, style, 0);
+}
+
+/* put a string at a given char position at a given offset mark */
+void lcd_puts_offset(int x, int y, const unsigned char *str, int offset)
+{
+     lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset);
+}
 
 /* put a string at a given char position */
 void lcd_puts(int x, int y, const unsigned char *str)
@@ -1134,6 +1146,17 @@
 
 void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style)
 {
+     lcd_puts_scroll_style_offset(x, y, string, style, 0);
+}
+
+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)
+{
     struct scrollinfo* s;
     int w, h;
 
@@ -1143,10 +1166,10 @@
     s->invert = false;
     if (style & STYLE_INVERT) {
         s->invert = true;
-        lcd_puts_style(x,y,string,STYLE_INVERT);
+        lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset);
     }
     else
-        lcd_puts(x,y,string);
+        lcd_puts_offset(x,y,string,offset);
 
     lcd_getstringsize(string, &w, &h);
 
@@ -1179,7 +1202,7 @@
         strncpy(end, (char *)string, LCD_WIDTH/2);
 
         s->len = utf8length((char *)string);
-        s->offset = 0;
+        s->offset = offset;
         s->startx = x;
         s->backward = false;
         scrolling_lines |= (1<<y);
@@ -1203,7 +1226,7 @@
     while ( 1 ) {
         for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
             /* really scroll? */
-            if ( !(scrolling_lines&(1<<index)) )
+            if ( !(scrolling_lines&(1<<index)))
                 continue;
 
             s = &scroll[index];
@@ -1246,8 +1269,7 @@
             lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
             drawmode = DRMODE_SOLID;
             lcd_putsxyofs(xpos, ypos, s->offset, (unsigned char *)s->line);
-            if (s->invert)
-            {
+            if (s->invert) {
                 drawmode = DRMODE_COMPLEMENT;
                 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
             }
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
index 523e8a1..9f8a2b6 100644
--- a/firmware/drivers/lcd-recorder.c
+++ b/firmware/drivers/lcd-recorder.c
@@ -917,7 +917,9 @@
 
 /*** Line oriented text output ***/
 
-void lcd_puts_style(int x, int y, const unsigned char *str, int style)
+/* put a string at a given char position at a given style and with a given pixel position */
+void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style,
+                                                                   int offset)
 {
     int xpos,ypos,w,h;
     int lastmode = drawmode;
@@ -931,7 +933,7 @@
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length(str);
     ypos = ymargin + y*h;
-    lcd_putsxy(xpos, ypos, str);
+    lcd_putsxyofs(xpos, ypos, offset, str);
     drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
     lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h);
     if (style & STYLE_INVERT)
@@ -942,10 +944,21 @@
     drawmode = lastmode;
 }
 
+void lcd_puts_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_puts_style_offset(x, y, str, style, 0);
+}
+
+/* put a string at a given char position at a given offset mark */
+void lcd_puts_offset(int x, int y, const unsigned char *str, int offset)
+{
+     lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset);
+}
+
 /* put a string at a given char position */
 void lcd_puts(int x, int y, const unsigned char *str)
 {
-    lcd_puts_style(x, y, str, STYLE_DEFAULT);
+    lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, 0);
 }
 
 /*** scrolling ***/
@@ -989,11 +1002,22 @@
 
 void lcd_puts_scroll(int x, int y, const unsigned char *string)
 {
-    lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
+    lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, 0);
 }
 
+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(int x, int y, const unsigned char *string, int style)
 {
+     lcd_puts_scroll_style_offset(x, y, string, style, 0);
+}
+
+void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, 
+                                  int style, int offset)
+{
     struct scrollinfo* s;
     int w, h;
 
@@ -1003,10 +1027,10 @@
     s->invert = false;
     if (style & STYLE_INVERT) {
         s->invert = true;
-        lcd_puts_style(x,y,string,STYLE_INVERT);
+        lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset);
     }
     else
-        lcd_puts(x,y,string);
+        lcd_puts_offset(x,y,string,offset);
 
     lcd_getstringsize(string, &w, &h);
 
@@ -1039,7 +1063,7 @@
         strncpy(end, string, LCD_WIDTH/2);
 
         s->len = utf8length(string);
-        s->offset = 0;
+        s->offset = offset;
         s->startx = x;
         s->backward = false;
         scrolling_lines |= (1<<y);
@@ -1106,8 +1130,7 @@
             lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
             drawmode = DRMODE_SOLID;
             lcd_putsxyofs(xpos, ypos, s->offset, s->line);
-            if (s->invert)
-            {
+            if (s->invert) {
                 drawmode = DRMODE_COMPLEMENT;
                 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
             }
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h
index 491e055..2795c7b 100644
--- a/firmware/export/lcd-remote.h
+++ b/firmware/export/lcd-remote.h
@@ -37,15 +37,23 @@
 extern void lcd_remote_clear_display(void);
 extern void lcd_remote_puts(int x, int y, const unsigned char *string);
 extern void lcd_remote_puts_style(int x, int y, const unsigned char *string,
-                                  int style);
+                                                int style);
+extern void lcd_remote_puts_offset(int x, int y, const unsigned char *str, int offset);
+extern void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, int style, int offset);
+
 extern void lcd_remote_putc(int x, int y, unsigned short ch);
 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* string);
-extern void lcd_remote_puts_scroll_style(int x, int y,
-                                         const unsigned char* string, int style);
-                                                               
+extern void lcd_remote_puts_scroll_style(int x, int y,const unsigned char* string,
+                                                int style);
+extern void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string,
+                                                int offset);
+extern void lcd_remote_puts_scroll_style_offset(int x, int y, 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);
 
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 6bb54f5..7fcae6e 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -203,6 +203,14 @@
 extern void lcd_setfont(int font);
 extern int  lcd_getstringsize(const unsigned char *str, int *w, int *h);
 
+extern void lcd_puts_offset(int x, int y, const unsigned char *str, int offset);
+extern void lcd_puts_style_offset(int x, int y, const unsigned char *str, 
+                                  int style, int offset);
+extern void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
+                                  int offset);
+extern void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
+                                  int style, int offset);                                  
+
 /* low level drawing function pointer arrays */
 extern lcd_pixelfunc_type* const lcd_pixelfuncs[8];
 extern lcd_blockfunc_type* const lcd_blockfuncs[8];