Index: apps/plugins/test_styles.c
===================================================================
--- apps/plugins/test_styles.c	(revision 0)
+++ apps/plugins/test_styles.c	(revision 0)
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: helloworld.c 8349 2006-01-15 18:20:18Z amiconn $
+ *
+ * Copyright (C) 2007 Timo Horstschäfer
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+PLUGIN_HEADER
+
+static struct plugin_api* rb;
+
+struct style {
+    const char *name;
+    int style;
+};
+
+struct style test_styles[] = {
+    { "normal",                     STYLE_DEFAULT },
+    { "bold",                       STYLE_BOLD },
+    { "underline",                  STYLE_UNDERLINE },
+    { "bold + underline",           STYLE_BOLD|STYLE_UNDERLINE },
+    { "shadow",                     STYLE_SHADOW },
+    { "bold + shadow",              STYLE_BOLD|STYLE_SHADOW },
+    { "bold + underline + inverse + shadow", STYLE_BOLD|STYLE_UNDERLINE|STYLE_INVERT|STYLE_SHADOW },
+    { "bold + inverse",             STYLE_BOLD|STYLE_INVERT },
+    { "\33[1mm\33[3mi\33[7mx\33[27me\33[4md\33[22m!", STYLE_INTERPRET },
+};
+
+#define NUM_STYLES ((int) (sizeof test_styles / sizeof (struct style)) )
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+    int i;
+
+    (void)parameter;
+    rb = api;
+
+    for (i = 0; i < NUM_STYLES; i++) {
+        rb->lcd_puts_style(0, i, test_styles[i].name, test_styles[i].style);
+#ifdef HAVE_REMOTE_LCD
+        rb->lcd_remote_puts_style(0, i, test_styles[i].name, test_styles[i].style);
+#endif
+    }
+    rb->lcd_update();
+#ifdef HAVE_REMOTE_LCD
+    rb->lcd_remote_update();
+#endif
+
+    while (!rb->button_get(true))
+        ;
+
+    return PLUGIN_OK;
+}
Index: apps/plugins/SOURCES
===================================================================
--- apps/plugins/SOURCES	(revision 12963)
+++ apps/plugins/SOURCES	(working copy)
@@ -36,6 +36,7 @@
 #ifdef HAVE_LCD_BITMAP             /* Not for the Player */
 mazezam.c
 text_editor.c
+test_styles.c
 
 /* Plugins needing the grayscale lib on low-depth LCDs */
 fire.c
Index: apps/plugin.c
===================================================================
--- apps/plugin.c	(revision 12963)
+++ apps/plugin.c	(working copy)
@@ -71,7 +71,9 @@
     lcd_getstringsize,
     lcd_putsxy,
     lcd_puts,
+    lcd_puts_style,
     lcd_puts_scroll,
+    lcd_puts_scroll_style,
     lcd_stop_scroll,
 #ifdef HAVE_LCD_CHARCELLS
     lcd_define_pattern,
@@ -110,8 +112,6 @@
     bidi_l2v,
     font_get_bits,
     font_load,
-    lcd_puts_style,
-    lcd_puts_scroll_style,
     &lcd_framebuffer[0][0],
     lcd_blit,
     lcd_update,
@@ -129,6 +129,7 @@
     /* remote lcd */
     lcd_remote_set_contrast,
     lcd_remote_clear_display,
+    lcd_remote_setmargins,
     lcd_remote_puts,
     lcd_remote_puts_scroll,
     lcd_remote_stop_scroll,
@@ -487,6 +488,12 @@
     playlist_resume,
     playlist_start,
     &global_status,
+    
+    ansi_escape,
+    lcd_get_last_style,
+#ifdef HAVE_REMOTE_LCD
+    lcd_remote_get_last_style,
+#endif
 
 #if CONFIG_CODEC == SWCODEC
     pcm_get_bytes_waiting,
Index: apps/plugin.h
===================================================================
--- apps/plugin.h	(revision 12963)
+++ apps/plugin.h	(working copy)
@@ -75,6 +75,7 @@
 #include "rbunicode.h"
 #include "list.h"
 #include "tree.h"
+#include "ansi.h"
 
 #ifdef HAVE_REMOTE_LCD
 #include "lcd-remote.h"
@@ -139,7 +140,10 @@
     int  (*lcd_getstringsize)(const unsigned char *str, int *w, int *h);
     void (*lcd_putsxy)(int x, int y, const unsigned char *string);
     void (*lcd_puts)(int x, int y, const unsigned char *string);
+    void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style);
     void (*lcd_puts_scroll)(int x, int y, const unsigned char* string);
+    void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string,
+                                  int style);
     void (*lcd_stop_scroll)(void);
 #ifdef HAVE_LCD_CHARCELLS
     void (*lcd_define_pattern)(unsigned long ucs, const char *pattern);
@@ -185,9 +189,6 @@
     unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation );
     const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
     struct font* (*font_load)(const char *path);
-    void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style);
-    void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string,
-                                  int style);
     fb_data* lcd_framebuffer;
     void (*lcd_blit) (const fb_data* data, int x, int by, int width,
                       int bheight, int stride);
@@ -211,6 +212,7 @@
     /* remote lcd */
     void (*lcd_remote_set_contrast)(int x);
     void (*lcd_remote_clear_display)(void);
+    void (*lcd_remote_setmargins)(int xmargin, int ymargin);
     void (*lcd_remote_puts)(int x, int y, const unsigned char *string);
     void (*lcd_remote_lcd_puts_scroll)(int x, int y, const unsigned char* string);
     void (*lcd_remote_lcd_stop_scroll)(void);
@@ -603,6 +605,12 @@
     int (*playlist_start)(int start_index, int offset);
     struct system_status *global_status;
 
+    int (*ansi_escape)(const char *s, int *style);
+    int (*lcd_get_last_style)(void);
+#ifdef HAVE_REMOTE_LCD
+    int (*lcd_remote_get_last_style)(void);
+#endif
+
 #if CONFIG_CODEC == SWCODEC
     size_t (*pcm_get_bytes_waiting)(void);
 #endif
Index: firmware/export/ansi.h
===================================================================
--- firmware/export/ansi.h	(revision 0)
+++ firmware/export/ansi.h	(revision 0)
@@ -0,0 +1,23 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: lcd.h 12419 2007-02-20 19:31:34Z amiconn $
+ *
+ * Copyright (C) 2007 Timo HorstschÃ¤fer
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "lcd.h"
+
+int ansi_escape(const char *s, int *style);
+int ansi_escape_ucs(const unsigned short *s, int *style);
Index: firmware/export/lcd.h
===================================================================
--- firmware/export/lcd.h	(revision 12963)
+++ firmware/export/lcd.h	(working copy)
@@ -24,8 +24,14 @@
 #include "cpu.h"
 #include "config.h"
 
-#define STYLE_DEFAULT 0
-#define STYLE_INVERT  1
+#define STYLE_DEFAULT   STYLE_NORMAL
+#define STYLE_NORMAL    0x0
+#define STYLE_BOLD      0x1
+#define STYLE_SHADOW    0x2
+#define STYLE_UNDERLINE 0x4
+#define STYLE_INVERT    0x8
+/* allow to control the style using ANSI escape sequences */
+#define STYLE_INTERPRET 0x10
 
 #ifdef SIMULATOR
 #define lcd_icon(x,y) sim_lcd_icon(x,y)
@@ -69,8 +75,8 @@
 extern void lcd_puts(int x, int y, const unsigned char *string);
 extern void lcd_puts_style(int x, int y, const unsigned char *string, int style);
 extern void lcd_puts_offset(int x, int y, const unsigned char *str, int offset);
-extern void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
-                                  int offset);
+extern void lcd_puts_style_offset(int x, int y, const unsigned char *str,
+                                  int style, int offset);
 extern void lcd_putc(int x, int y, unsigned long ucs);
 extern void lcd_stop_scroll(void);
 extern void lcd_bidir_scroll(int threshold);
@@ -79,8 +85,14 @@
 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);
+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);
 extern void lcd_icon(int icon, bool enable);
 
+extern int  lcd_get_last_style(void);
+
 #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,11 +326,6 @@
 extern int  lcd_get_drawmode(void);
 extern void lcd_setfont(int font);
 
-extern void lcd_puts_style_offset(int x, int y, const unsigned char *str,
-                                  int style, 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 */
 #if LCD_DEPTH >= 8
 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs;
@@ -340,6 +347,11 @@
                             int stride, int x, int y, int width, int height);
 extern void lcd_bitmap(const fb_data *src, int x, int y, int width,
                        int height);
+extern void lcd_putsxy(int x, int y, const unsigned char *str);
+extern void lcd_putsxy_style(int x, int y, const unsigned char *str, int style);
+extern void lcd_putsxy_offset(int x, int y, int ofs, const unsigned char *str);
+extern void lcd_putsxy_style_offset(int x, int y, int ofs,
+                                    const unsigned char *str, int style);
 
 extern void lcd_invertscroll(int x, int y);
 extern void lcd_scroll_step(int pixels);
Index: firmware/export/lcd-remote.h
===================================================================
--- firmware/export/lcd-remote.h	(revision 12963)
+++ firmware/export/lcd-remote.h	(working copy)
@@ -43,8 +43,14 @@
 extern struct event_queue remote_scroll_queue;
 #endif
 
-#define STYLE_DEFAULT 0
-#define STYLE_INVERT  1
+#define STYLE_DEFAULT   STYLE_NORMAL
+#define STYLE_NORMAL    0x0
+#define STYLE_BOLD      0x1
+#define STYLE_SHADOW    0x2
+#define STYLE_UNDERLINE 0x4
+#define STYLE_INVERT    0x8
+/* allow to control the style using ANSI escape sequences */
+#define STYLE_INTERPRET 0x10
 
 #if LCD_REMOTE_DEPTH <= 8
 #if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \
@@ -147,6 +153,7 @@
 extern int  lcd_remote_getymargin(void);
 extern void lcd_remote_setfont(int font);
 extern int  lcd_remote_getstringsize(const unsigned char *str, int *w, int *h);
+extern int  lcd_remote_get_last_style(void);
 
 /* low level drawing function pointer arrays */
 #if LCD_REMOTE_DEPTH > 1
@@ -169,6 +176,12 @@
 extern void lcd_remote_bitmap(const fb_remote_data *src, int x, int y,
                               int width, int height);
 extern void lcd_remote_putsxy(int x, int y, const unsigned char *str);
+extern void lcd_remote_putsxy_style(int x, int y, const unsigned char *str,
+                                    int style);
+extern void lcd_remote_putsxy_offset(int x, int y, int ofs,
+                                     const unsigned char *str);
+extern void lcd_remote_putsxy_style_offset(int x, int y, int ofs,
+                                           const unsigned char *str, int style);
 
 extern void lcd_remote_invertscroll(int x, int y);
 extern void lcd_remote_bidir_scroll(int threshold);
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES	(revision 12963)
+++ firmware/SOURCES	(working copy)
@@ -1,3 +1,4 @@
+ansi.c
 ata_idle_notify.c
 backlight.c
 buffer.c
Index: firmware/ansi.c
===================================================================
--- firmware/ansi.c	(revision 0)
+++ firmware/ansi.c	(revision 0)
@@ -0,0 +1,105 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: buffer.c 10958 2006-09-16 16:18:11Z miipekk $
+ *
+ * Copyright (C) 2007 Timo HorstschÃ¤fer
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "ansi.h"
+#include "stdlib.h"
+#include "debug.h"
+
+/**
+ * Handles ANSI escape sequences for SGR.
+ * The sequence begins with 'ESC [' and ends with 'm'.
+ * 
+ * Syntax:
+ *  \033[##m
+ *      where ## is the value.
+ *
+ * Currently supports:
+ *  0   all attributes off
+ *  1   bold:       on
+ *  3   shadow:     on (instead of italic)
+ *  4   underline:  on
+ *  7   invert:     on
+ *  22  bold:       off
+ *  23  shadow      off
+ *  24  underline:  off
+ *  27  invert:     off
+ *
+ *  Example:
+ *      printf("\33[1mAppears bold\33[22m\nAppears normal\n");
+ */
+int ansi_sgr(int code, int style)
+{
+    switch (code) {
+        case 0:
+            style = STYLE_NORMAL;
+            break;
+        case 1:
+            style |= STYLE_BOLD;
+            break;
+        case 3:
+            style |= STYLE_SHADOW;
+            break;
+        case 4:
+            style |= STYLE_UNDERLINE;
+            break;
+        case 7:
+            style |= STYLE_INVERT;
+            break;
+        case 22:
+            style &= ~STYLE_BOLD;
+            break;
+        case 23:
+            style &= ~STYLE_SHADOW;
+            break;
+        case 24:
+            style &= ~STYLE_UNDERLINE;
+            break;
+        case 27:
+            style &= ~STYLE_INVERT;
+            break;
+    }
+
+    return style;
+}
+
+#define TEMPLATE_ANSI_ESCAPE(NAME, T)           \
+int NAME(const T *s, int *style)                \
+{                                               \
+    int code = 0;                               \
+    const T *p;                                 \
+                                                \
+    /* check CSI */                             \
+    if (*s != '\33' || *(s+1) != '[')           \
+        return 0;                               \
+                                                \
+    /* get value */                             \
+    for (p = s+2; *p > '0' && *p < '9'; p++)    \
+    {                                           \
+        if (style)                              \
+            code = code*10 + *p - '0';          \
+    }                                           \
+                                                \
+    if (style && *p == 'm')                     \
+        *style = ansi_sgr(code, *style);        \
+                                                \
+    return p - s + 1;                           \
+}
+
+TEMPLATE_ANSI_ESCAPE(ansi_escape, char)
+TEMPLATE_ANSI_ESCAPE(ansi_escape_ucs, unsigned short)
Index: firmware/drivers/lcd-1bit-vert.c
===================================================================
--- firmware/drivers/lcd-1bit-vert.c	(revision 12963)
+++ firmware/drivers/lcd-1bit-vert.c	(working copy)
@@ -30,6 +30,7 @@
 #include "hwcompat.h"
 #include "rbunicode.h"
 #include "bidi.h"
+#include "ansi.h"
 
 /*** definitions ***/
 
@@ -40,6 +41,7 @@
 unsigned char lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH];
 
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_DEFAULT;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -110,6 +112,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 static void setpixel(int x, int y)
@@ -600,22 +607,43 @@
     lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                             int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode;
+    int l;
 
+    if(!str || !str[0])
+        return;
+
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf,ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -623,15 +651,31 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_fillrect(x, y, width, pf->height);
+
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
         lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
                              pf->height);
-        
+        if (style & STYLE_BOLD) {
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
+
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
+    last_style = style;
 }
+
 /* put a string at a given pixel position */
 void lcd_putsxy(int x, int y, const unsigned char *str)
 {
@@ -673,10 +717,9 @@
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length(str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -801,7 +844,6 @@
     struct scrollinfo* s;
     int index;
     int xpos, ypos;
-    int lastmode;
 
     /* initialize scroll struct array */
     scrolling_lines = 0;
@@ -847,11 +889,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_putsxy_style_offset(xpos, ypos, s->offset, s->line,
+                                           (s->invert) ? STYLE_INVERT : STYLE_DEFAULT);
             lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
         }
 
Index: firmware/drivers/lcd-charcell.c
===================================================================
--- firmware/drivers/lcd-charcell.c	(revision 12963)
+++ firmware/drivers/lcd-charcell.c	(working copy)
@@ -30,6 +30,7 @@
 #include "system.h"
 #include "lcd-charcell.h"
 #include "rbunicode.h"
+#include "ansi.h"
 
 /** definitions **/
 
@@ -137,6 +138,11 @@
     return width;
 }
 
+int lcd_get_last_style(void)
+{
+	return STYLE_DEFAULT;
+}
+
 /** low-level functions **/
 
 static int find_xchar(unsigned long ucs)
@@ -399,9 +405,15 @@
 {
     unsigned short ucs;
     const unsigned char *utf8 = str;
+    int l;
 
     while (*utf8 && x < LCD_WIDTH)
     {
+	l = ansi_escape(utf8, NULL);
+	if (l > 0) {
+		utf8 += l;
+		continue;
+	}
         utf8 = utf8decode(utf8, &ucs);
         
         if (ofs > 0)
@@ -428,6 +440,12 @@
     lcd_puts_offset(x, y, str, 0);
 }
 
+void lcd_puts_style(int x, int y, const unsigned char *string, int style)
+{
+	(void)style;
+	lcd_puts(x, y, string);
+}
+
 /* Put a string at a given char position,  skipping first offset chars */
 void lcd_puts_offset(int x, int y, const unsigned char *str, int offset)
 {
@@ -442,6 +460,13 @@
         lcd_putc(x++, y, ' ');
 }
 
+void lcd_puts_style_offset(int x, int y, const unsigned char *string,
+                           int style, int offset)
+{
+	(void)style;
+	lcd_puts_offset(x, y, string, offset);
+}
+
 /** scrolling **/
 
 void lcd_stop_scroll(void)
@@ -479,6 +504,13 @@
     lcd_puts_scroll_offset(x, y, string, 0);
 }
 
+void lcd_puts_scroll_style(int x, int y, const unsigned char *string,
+			   int style)
+{
+	(void)style;
+	lcd_puts_scroll(x, y, string);
+}
+
 void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
                             int offset)
 {
@@ -531,6 +563,13 @@
         scrolling_lines &= ~(1<<y);
 }
 
+void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
+                                  int style, int offset)
+{
+	(void)style;
+	lcd_puts_scroll_offset(x, y, string, offset);
+}
+
 static void scroll_thread(void)
 {
     struct scrollinfo* s;
Index: firmware/drivers/lcd-2bit-vert.c
===================================================================
--- firmware/drivers/lcd-2bit-vert.c	(revision 12963)
+++ firmware/drivers/lcd-2bit-vert.c	(working copy)
@@ -30,6 +30,7 @@
 #include "font.h"
 #include "rbunicode.h"
 #include "bidi.h"
+#include "ansi.h"
 
 /*** definitions ***/
 
@@ -54,6 +55,7 @@
 static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */
 static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_NORMAL;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -151,6 +153,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 static void setpixel(int x, int y)
@@ -932,22 +939,53 @@
     lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+/*** pixel oriented text output ***/
+
+/* put a string at a given pixel position */
+void lcd_putsxy(int x, int y, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_putsxy_style_offset(x, y, 0, str, STYLE_DEFAULT);
+}
+
+void lcd_putsxy_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_putsxy_style_offset(x, y, 0, str, style);
+}
+
+void lcd_putsxy_offset(int x, int y, int ofs, const unsigned char *str)
+{
+    lcd_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                             int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode, lastcolor;
+    int l;
 
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf,ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -955,20 +993,50 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_fillrect(x, y, width, pf->height);
+
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
+        if (style & STYLE_SHADOW) {
+            if (style & STYLE_INVERT) {
+                lastcolor = lcd_get_background();
+                lcd_set_background(LCD_LIGHTGRAY);
+            } else {
+                lastcolor = lcd_get_foreground();
+                lcd_set_foreground(LCD_LIGHTGRAY);
+            }
+
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x, y+1, width - ofs,
+                                 pf->height);
+            if (style & STYLE_BOLD)
+                lcd_mono_bitmap_part(bits, ofs, 0, width, x+1, y+1, width - ofs,
+                                     pf->height);
+
+            if (style & STYLE_INVERT)
+                lcd_set_background(lastcolor);
+            else
+                lcd_set_foreground(lastcolor);
+        }
         lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
                              pf->height);
-        
+        if (style & STYLE_BOLD) {
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
+
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
-}
 
-/* put a string at a given pixel position */
-void lcd_putsxy(int x, int y, const unsigned char *str)
-{
-    lcd_putsxyofs(x, y, 0, str);
+    last_style = style;
 }
 
 /*** line oriented text output ***/
@@ -1000,16 +1068,18 @@
     /* make sure scrolling is turned off on the line we are updating */
     scrolling_lines &= ~(1 << y);
 
+    /* set style in advance if string is empty */
+    last_style = style;
+
     if(!str || !str[0])
         return;
 
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -1133,7 +1203,6 @@
     struct scrollinfo* s;
     int index;
     int xpos, ypos;
-    int lastmode;
 
     /* initialize scroll struct array */
     scrolling_lines = 0;
@@ -1179,11 +1248,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_putsxy_style_offset(xpos, ypos, s->offset, s->line,
+                        (s->invert) ? STYLE_INVERT : STYLE_DEFAULT);
             lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
         }
 
Index: firmware/drivers/lcd-2bit-horz.c
===================================================================
--- firmware/drivers/lcd-2bit-horz.c	(revision 12963)
+++ firmware/drivers/lcd-2bit-horz.c	(working copy)
@@ -33,6 +33,7 @@
 #include "font.h"
 #include "rbunicode.h"
 #include "bidi.h"
+#include "ansi.h"
 
 #define SCROLLABLE_LINES (((LCD_HEIGHT+4)/5 < 32) ? (LCD_HEIGHT+4)/5 : 32)
 
@@ -50,6 +51,7 @@
 static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */
 static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_NORMAL;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -148,6 +150,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 static void setpixel(int x, int y)
@@ -796,22 +803,56 @@
     lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+/*** pixel oriented text output ***/
+
+/* put a string at a given pixel position */
+void lcd_putsxy(int x, int y, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_putsxy_style_offset(x, y, 0, str, STYLE_DEFAULT);
+}
+
+void lcd_putsxy_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_putsxy_style_offset(x, y, 0, str, style);
+}
+
+void lcd_putsxy_offset(int x, int y, int ofs, const unsigned char *str)
+{
+    lcd_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                          int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode, lastcolor;
+    int l;
 
+    if(!str || !str[0])
+        return;
+
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf,ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -819,22 +860,51 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_fillrect(x, y, width, pf->height);
+
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
+        if (style & STYLE_SHADOW) {
+            if (style & STYLE_INVERT) {
+                lastcolor = lcd_get_background();
+                lcd_set_background(LCD_LIGHTGRAY);
+            } else {
+                lastcolor = lcd_get_foreground();
+                lcd_set_foreground(LCD_LIGHTGRAY);
+            }
+
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x, y+1, width - ofs,
+                                 pf->height);
+            if (style & STYLE_BOLD)
+                lcd_mono_bitmap_part(bits, ofs, 0, width, x+1, y+1, width - ofs,
+                                     pf->height);
+
+            if (style & STYLE_INVERT)
+                lcd_set_background(lastcolor);
+            else
+                lcd_set_foreground(lastcolor);
+        }
         lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
                              pf->height);
-        
+        if (style & STYLE_BOLD) {
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
+
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
+    last_style = style;
 }
 
-/* put a string at a given pixel position */
-void lcd_putsxy(int x, int y, const unsigned char *str)
-{
-    lcd_putsxyofs(x, y, 0, str);
-}
-
 /*** line oriented text output ***/
 
 /* put a string at a given char position */
@@ -870,10 +940,9 @@
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -997,7 +1066,6 @@
     struct scrollinfo* s;
     int index;
     int xpos, ypos;
-    int lastmode;
 
     /* initialize scroll struct array */
     scrolling_lines = 0;
@@ -1043,11 +1111,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_putsxy_style_offset(xpos, ypos, s->offset, s->line, (s->invert) ?
+                                                          STYLE_INVERT : STYLE_DEFAULT);
             lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
         }
 
Index: firmware/drivers/lcd-remote-2bit-vi.c
===================================================================
--- firmware/drivers/lcd-remote-2bit-vi.c	(revision 12963)
+++ firmware/drivers/lcd-remote-2bit-vi.c	(working copy)
@@ -34,6 +34,7 @@
 #include "rbunicode.h"
 #include "bidi.h"
 #include "lcd-remote-target.h"
+#include "ansi.h"
 
 #define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
 
@@ -50,6 +51,7 @@
 static unsigned fg_pattern IDATA_ATTR = 0xFFFF; /* initially black */
 static unsigned bg_pattern IDATA_ATTR = 0x0000; /* initially white */
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_DEFAULT;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -154,6 +156,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_remote_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 static void setpixel(int x, int y)
@@ -934,22 +941,56 @@
     lcd_remote_bitmap_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+/*** pixel oriented text output ***/
+
+/* put a string at a given pixel position */
+void lcd_remote_putsxy(int x, int y, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_remote_putsxy_style_offset(x, y, 0, str, STYLE_DEFAULT);
+}
+
+void lcd_remote_putsxy_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_remote_putsxy_style_offset(x, y, 0, str, style);
+}
+
+void lcd_remote_putsxy_offset(int x, int y, int ofs, const unsigned char *str)
+{
+    lcd_remote_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_remote_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                          int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode;
+    int l;
 
+    if(!str || !str[0])
+        return;
+
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf, ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -957,22 +998,31 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_remote_fillrect(x, y, width, pf->height);
+
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
         lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
-                                    pf->height);
+                             pf->height);
+        if (style & STYLE_BOLD) {
+            lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_remote_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
 
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
+    last_style = style;
 }
 
-/* put a string at a given pixel position */
-void lcd_remote_putsxy(int x, int y, const unsigned char *str)
-{
-    lcd_remote_putsxyofs(x, y, 0, str);
-}
-
 /*** line oriented text output ***/
 
 /* put a string at a given char position */
@@ -1008,10 +1058,9 @@
     lcd_remote_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_remote_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_remote_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -1135,7 +1184,6 @@
     struct scrollinfo* s;
     int index;
     int xpos, ypos;
-    int lastmode;
     long delay = 0;
     long next_tick = current_tick;
 #ifndef SIMULATOR
@@ -1212,11 +1260,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_remote_putsxy_style_offset(xpos, ypos, s->offset, s->line,
+                                           (s->invert) ? STYLE_INVERT : STYLE_DEFAULT);
             lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
         }
 
Index: firmware/drivers/lcd-16bit.c
===================================================================
--- firmware/drivers/lcd-16bit.c	(revision 12963)
+++ firmware/drivers/lcd-16bit.c	(working copy)
@@ -33,6 +33,7 @@
 #include "font.h"
 #include "rbunicode.h"
 #include "bidi.h"
+#include "ansi.h"
 #if defined(TOSHIBA_GIGABEAT_F)
 #define NON_GB_STATIC
 #else
@@ -57,6 +58,7 @@
 NON_GB_STATIC unsigned fg_pattern IDATA_ATTR = LCD_DEFAULT_FG;
 NON_GB_STATIC unsigned bg_pattern IDATA_ATTR = LCD_DEFAULT_BG;
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_NORMAL;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -162,6 +164,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
@@ -756,22 +763,56 @@
     lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+/*** pixel oriented text output ***/
+
+/* put a string at a given pixel position */
+void lcd_putsxy(int x, int y, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_putsxy_style_offset(x, y, 0, str, STYLE_DEFAULT);
+}
+
+void lcd_putsxy_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_putsxy_style_offset(x, y, 0, str, style);
+}
+
+void lcd_putsxy_offset(int x, int y, int ofs, const unsigned char *str)
+{
+    lcd_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                          int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode, lastcolor;
+    int l;
 
+    if(!str || !str[0])
+        return;
+
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf,ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -779,21 +820,51 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
-        lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_fillrect(x, y, width, pf->height);
 
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
+        if (style & STYLE_SHADOW) {
+            if (style & STYLE_INVERT) {
+                lastcolor = lcd_get_background();
+                lcd_set_background(LCD_LIGHTGRAY);
+            } else {
+                lastcolor = lcd_get_foreground();
+                lcd_set_foreground(LCD_LIGHTGRAY);
+            }
+
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x, y+1, width - ofs,
+                                 pf->height);
+            if (style & STYLE_BOLD)
+                lcd_mono_bitmap_part(bits, ofs, 0, width, x+1, y+1, width - ofs,
+                                     pf->height);
+
+            if (style & STYLE_INVERT)
+                lcd_set_background(lastcolor);
+            else
+                lcd_set_foreground(lastcolor);
+        }
+        lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
+                             pf->height);
+        if (style & STYLE_BOLD) {
+            lcd_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
+
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
+    last_style = style;
 }
 
-/* put a string at a given pixel position */
-void lcd_putsxy(int x, int y, const unsigned char *str)
-{
-    lcd_putsxyofs(x, y, 0, str);
-}
-
 /*** line oriented text output ***/
 
 /* put a string at a given char position */
@@ -829,10 +900,9 @@
     lcd_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length(str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -956,7 +1026,6 @@
     struct scrollinfo* s;
     int index;
     int xpos, ypos;
-    int lastmode;
 
     /* initialize scroll struct array */
     scrolling_lines = 0;
@@ -1006,11 +1075,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_putsxy_style_offset(xpos, ypos, s->offset, s->line,
+                                    s->invert ? STYLE_INVERT : STYLE_DEFAULT);
             lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
         }
 
Index: firmware/drivers/lcd-remote-1bit-v.c
===================================================================
--- firmware/drivers/lcd-remote-1bit-v.c	(revision 12963)
+++ firmware/drivers/lcd-remote-1bit-v.c	(working copy)
@@ -31,6 +31,7 @@
 #include "font.h"
 #include "rbunicode.h"
 #include "bidi.h"
+#include "ansi.h"
 
 #define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
 
@@ -40,6 +41,7 @@
                                       IBSS_ATTR;
 
 static int drawmode = DRMODE_SOLID;
+static int last_style = STYLE_DEFAULT;
 static int xmargin = 0;
 static int ymargin = 0;
 static int curfont = FONT_SYSFIXED;
@@ -105,6 +107,11 @@
     return font_getstringsize(str, w, h, curfont);
 }
 
+int lcd_remote_get_last_style(void)
+{
+    return last_style;
+}
+
 /*** low-level drawing functions ***/
 
 static void setpixel(int x, int y)
@@ -598,22 +605,56 @@
     lcd_remote_bitmap_part(src, 0, 0, width, x, y, width, height);
 }
 
-/* put a string at a given pixel position, skipping first ofs pixel columns */
-static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
+/*** pixel oriented text output ***/
+
+/* put a string at a given pixel position */
+void lcd_remote_putsxy(int x, int y, const unsigned char *str)
 {
-    unsigned short ch;
+    lcd_remote_putsxy_style_offset(x, y, 0, str, STYLE_DEFAULT);
+}
+
+void lcd_remote_putsxy_style(int x, int y, const unsigned char *str, int style)
+{
+    lcd_remote_putsxy_style_offset(x, y, 0, str, style);
+}
+
+void lcd_remote_putsxy_offset(int x, int y, int ofs, const unsigned char *str)
+{
+    lcd_remote_putsxy_style_offset(x, y, ofs, str, STYLE_DEFAULT);
+}
+
+/* put a string at a given pixel position, style, and pixel position,
+ * skipping first offset pixel columns */
+void lcd_remote_putsxy_style_offset(int x, int y, int ofs, const unsigned char *str,
+                          int style)
+{
     unsigned short *ucs;
     struct font* pf = font_get(curfont);
+    int *sp;
+    int lastmode = drawmode;
+    int l;
 
+    if(!str || !str[0])
+        return;
+
+    sp = (style & STYLE_INTERPRET) ? &style : NULL;
     ucs = bidi_l2v(str, 1);
 
-    while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH)
+    for (; *ucs != 0; ucs++)
     {
         int width;
         const unsigned char *bits;
 
+        l = ansi_escape_ucs(ucs, sp);
+        if (x > LCD_WIDTH)
+            break;
+        if (l) {
+            ucs += l - 1;
+            continue;
+        }
+
         /* get proportional width and glyph bits */
-        width = font_get_width(pf, ch);
+        width = font_get_width(pf, *ucs);
 
         if (ofs > width)
         {
@@ -621,22 +662,31 @@
             continue;
         }
 
-        bits = font_get_bits(pf, ch);
+        bits = font_get_bits(pf, *ucs);
 
-        lcd_remote_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
-                               pf->height);
+        /* clear background */
+        drawmode ^= (style & STYLE_INVERT) ? 0 : DRMODE_INVERSEVID;
+        lcd_remote_fillrect(x, y, width, pf->height);
 
+        /* compose styles */
+        drawmode = (style & STYLE_INVERT) ?
+                    (DRMODE_BG|DRMODE_INVERSEVID) : DRMODE_FG;
+        lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
+                             pf->height);
+        if (style & STYLE_BOLD) {
+            lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x-1, y, width - ofs,
+                                 pf->height);
+        }
+        if (style & STYLE_UNDERLINE)
+            lcd_remote_drawline(x, y+pf->height-1, x+width, y+pf->height-1);
+
+        drawmode = lastmode;
         x += width - ofs;
         ofs = 0;
     }
+    last_style = style;
 }
 
-/* put a string at a given pixel position */
-void lcd_remote_putsxy(int x, int y, const unsigned char *str)
-{
-    lcd_remote_putsxyofs(x, y, 0, str);
-}
-
 /*** line oriented text output ***/
 
 /* put a string at a given char position */
@@ -672,10 +722,9 @@
     lcd_remote_getstringsize(str, &w, &h);
     xpos = xmargin + x*w / utf8length((char *)str);
     ypos = ymargin + y*h;
-    drawmode = (style & STYLE_INVERT) ?
-               (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-    lcd_remote_putsxyofs(xpos, ypos, offset, str);
-    drawmode ^= DRMODE_INVERSEVID;
+    lcd_remote_putsxy_style_offset(xpos, ypos, offset, str, style);
+    if (~style & STYLE_INVERT)
+        drawmode ^= DRMODE_INVERSEVID;
     xrect = xpos + MAX(w - offset, 0);
     lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h);
     drawmode = lastmode;
@@ -801,7 +850,6 @@
     long delay = 0;
     int index;
     int xpos, ypos;
-    int lastmode;
 #ifndef SIMULATOR
     struct event ev;
 #endif
@@ -875,11 +923,8 @@
                     s->offset %= s->width;
             }
 
-            lastmode = drawmode;
-            drawmode = s->invert ?
-                       (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
-            lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
-            drawmode = lastmode;
+            lcd_remote_putsxy_style_offset(xpos, ypos, s->offset, s->line,
+                                           (s->invert) ? STYLE_INVERT : STYLE_DEFAULT);
             lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
         }
 
