Added status bar to file browser and wps


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1582 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/playlist.c b/apps/playlist.c
index 44d1e34..48c66db 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -30,6 +30,13 @@
 #include "lcd.h"
 #include "kernel.h"
 #include "settings.h"
+#include "status.h"
+
+#ifdef HAVE_LCD_BITMAP
+#define LINE_Y      (global_settings.statusbar&&statusbar_enabled?1:0) /* Y position the entry-list starts at */
+#else /* HAVE_LCD_BITMAP */
+#define LINE_Y      0 /* Y position the entry-list starts at */
+#endif /* HAVE_LCD_BITMAP */
 
 playlist_info_t playlist;
 
@@ -165,7 +172,8 @@
     /* If file is NULL, the list is in RAM */
     if(file) {
         lcd_clear_display();
-        lcd_puts(0,0,"Loading...");
+        lcd_puts(0,LINE_Y,"Loading...");
+        status_draw();
         lcd_update();
         playlist.in_ram = false;
     } else {
@@ -194,14 +202,16 @@
     
     if(global_settings.playlist_shuffle) {
         if(!playlist.in_ram) {
-            lcd_puts(0,0,"Shuffling...");
+            lcd_puts(0,LINE_Y,"Shuffling...");
+            status_draw();
             lcd_update();
         }
         randomise_playlist( current_tick );
     }
 
     if(!playlist.in_ram) {
-        lcd_puts(0,0,"Playing...  ");
+        lcd_puts(0,LINE_Y,"Playing...  ");
+        status_draw();
         lcd_update();
     }
     /* also make the first song get playing */
@@ -287,7 +297,8 @@
                         next_tick = current_tick + HZ;
                         snprintf(line, sizeof line, "%d files",
                                  playlist.amount);
-                        lcd_puts(0,1,line);
+                        lcd_puts(0,LINE_Y+1,line);
+                        status_draw();
                         lcd_update();
                     }
                 }
@@ -301,7 +312,8 @@
     }
     if(!playlist.in_ram) {
         snprintf(line, sizeof line, "%d files", playlist.amount);
-        lcd_puts(0,1,line);
+        lcd_puts(0,LINE_Y+1,line);
+        status_draw();
         lcd_update();
         close(fd);
     }
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c
index 50475eb..482c764 100644
--- a/apps/recorder/icons.c
+++ b/apps/recorder/icons.c
@@ -19,6 +19,12 @@
 #include <lcd.h>
 
 #include "icons.h"
+#ifndef SIMULATOR
+#include "sprintf.h"
+#endif
+#ifdef HAVE_RTC
+#include "rtc.h"
+#endif
 
 #ifdef HAVE_LCD_BITMAP
 
@@ -34,6 +40,12 @@
     0x7c, 0x28, 0x28, 0x28, 0x28, 0x38
 };
 
+static unsigned char bitmap_icon_5x8[][5] =
+{
+    /* Lock */
+    {0x78,0x7f,0x49,0x7f,0x78}
+};
+
 unsigned char bitmap_icons_6x8[LastIcon][6] =
 {
     /* Box_Filled */
@@ -58,6 +70,36 @@
     { 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00 },
 };
 
+static unsigned char bitmap_icon_7x8[][7] =
+{
+    /* Power plug */
+    {0x08,0x1c,0x1c,0x3e,0x3e,0x14,0x14},
+    /* Speaker */
+    {0x00,0x1c,0x1c,0x3e,0x7f,0x00,0x00},
+    /* Speaker mute */
+    {0x01,0x1e,0x1c,0x3e,0x7f,0x20,0x40},
+    /* Play */
+    {0x00,0x7f,0x7f,0x3e,0x1c,0x08,0x00},
+    /* Stop */
+    {0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f},
+    /* Pause */
+    {0x00,0x7f,0x7f,0x00,0x7f,0x7f,0x00},
+    /* Fast forward */
+    {0x7f,0x3e,0x1c,0x7f,0x3e,0x1c,0x08},
+    /* Fast backward */
+    {0x08,0x1c,0x3e,0x7f,0x1c,0x3e,0x7f},
+    /* Record */
+    {0x1c,0x3e,0x7f,0x7f,0x7f,0x3e,0x1c},
+    /* Record pause */
+    {0x1c,0x3e,0x7f,0x00,0x7f,0x3e,0x1c},
+    /* Normal playmode */
+    {0x08,0x08,0x08,0x08,0x3e,0x1c,0x08},
+    /* Repeat playmode */
+    {0x38,0x44,0x44,0x4e,0x5f,0x44,0x38},
+    /* Shuffle playmode (dice) */
+    {0x3e,0x41,0x51,0x41,0x45,0x41,0x3e}
+};
+
 unsigned char rockbox112x37[]={
  0x00, 0x00, 0x02, 0xff, 0x02, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
  0xf8, 0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x80, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc,
@@ -111,4 +153,131 @@
 
 };
 
+/*
+ * Wipe statusbar
+ */
+void statusbar_wipe(void)
+{
+    int x;
+
+    for (x = 0; x < LCD_WIDTH; x++)
+        lcd_framebuffer[x][STATUSBAR_Y_POS/8]=0x00; 
+}
+
+/*
+ * Print battery icon to status bar
+ */
+void statusbar_icon_battery(int percent, bool charging)
+{
+    int i,j;
+    int fill;
+
+    /* draw battery */
+    for(i=0;i<17;i++) {
+        DRAW_PIXEL((ICON_BATTERY_X_POS+i),STATUSBAR_Y_POS);
+        DRAW_PIXEL((ICON_BATTERY_X_POS+i),(STATUSBAR_Y_POS+6));
+    }
+    for(i=1;i<6;i++) {
+        DRAW_PIXEL(ICON_BATTERY_X_POS,(STATUSBAR_Y_POS+i));
+        DRAW_PIXEL((ICON_BATTERY_X_POS+16),(STATUSBAR_Y_POS+i));
+    }
+    for(i=2;i<5;i++)
+        DRAW_PIXEL((ICON_BATTERY_X_POS+17),(STATUSBAR_Y_POS+i));
+
+    /* fill battery */
+    fill=percent;
+    if(fill<0)
+        fill=0;
+    if(fill>100)
+        fill=100;
+    fill=fill*15/100;
+
+    for(i=1;i<=fill;i++)
+        for(j=1;j<6;j++)
+            DRAW_PIXEL((ICON_BATTERY_X_POS+i),(STATUSBAR_Y_POS+j));
+
+    if(charging)
+        lcd_bitmap(bitmap_icon_7x8[Icon_Plug], ICON_PLUG_X_POS, STATUSBAR_Y_POS, ICON_PLUG_WIDTH, STATUSBAR_HEIGHT, false);
+};
+
+/*
+ * Print volume gauge to status bar
+ */
+void statusbar_icon_volume(int percent)
+{
+    int i,j;
+    int volume;
+    int step=0;
+
+    volume=percent;
+    if(volume<0)
+        volume=0;
+    if(volume>100)
+        volume=100;
+
+    if(volume==0)
+        lcd_bitmap(bitmap_icon_7x8[Icon_Mute], ICON_VOLUME_X_POS+ICON_VOLUME_WIDTH/2-4, STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT, false);
+    else {
+        volume=volume*14/100;
+        for(i=0;i<volume;i++) {
+            if(i%2 == 0)
+                step++;
+            for(j=1;j<=step;j++)
+                DRAW_PIXEL((ICON_VOLUME_X_POS+i),(STATUSBAR_Y_POS+7-j));
+        }
+    }
+}
+
+/*
+ * Print play state to status bar
+ */
+void statusbar_icon_play_state(int state)
+{
+    lcd_bitmap(bitmap_icon_7x8[state], ICON_PLAY_STATE_X_POS, STATUSBAR_Y_POS, ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT, false);
+}
+
+/*
+ * Print play mode to status bar
+ */
+void statusbar_icon_play_mode(int mode)
+{
+    lcd_bitmap(bitmap_icon_7x8[mode], ICON_PLAY_MODE_X_POS, STATUSBAR_Y_POS, ICON_PLAY_MODE_WIDTH, STATUSBAR_HEIGHT, false);
+}
+
+/*
+ * Print shuffle mode to status bar
+ */
+void statusbar_icon_shuffle(void)
+{
+    lcd_bitmap(bitmap_icon_7x8[Icon_Shuffle], ICON_SHUFFLE_X_POS, STATUSBAR_Y_POS, ICON_SHUFFLE_WIDTH, STATUSBAR_HEIGHT, false);
+}
+
+/*
+ * Print lock when keys are locked
+ */
+void statusbar_icon_lock(void)
+{
+    lcd_bitmap(bitmap_icon_5x8[Icon_Lock], LOCK_X_POS, STATUSBAR_Y_POS, 5, 8, false);
+}
+
+#ifdef HAVE_RTC
+/*
+ * Print time to status bar
+ */
+void statusbar_time(void)
+{
+    int hour,minute;
+    unsigned char buffer[6];
+
+    hour = rtc_read(0x03);
+    minute = rtc_read(0x02);
+
+    snprintf(buffer, sizeof(buffer), "%d%d:%d%d",
+             (hour & 0x30) >> 4,
+             hour & 0x0f,
+             (minute & 0xf0) >> 4,
+             minute & 0x0f);
+    lcd_putsxy(TIME_X_POS, STATUSBAR_Y_POS, buffer, 0);
+}
+#endif
 #endif
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h
index 866e488..da94c22 100644
--- a/apps/recorder/icons.h
+++ b/apps/recorder/icons.h
@@ -36,9 +36,56 @@
 
 extern unsigned char slider_bar[];
 
+#define STATUSBAR_X_POS       0
+#define STATUSBAR_Y_POS       0 // MUST be a multiple of 8
+#define STATUSBAR_HEIGHT      8
+#define STATUSBAR_WIDTH       LCD_WIDTH
+#define ICON_BATTERY_X_POS    0
+#define ICON_BATTERY_WIDTH    18
+#define ICON_PLUG_X_POS       STATUSBAR_X_POS+ICON_BATTERY_WIDTH+2
+#define ICON_PLUG_WIDTH       7
+#define ICON_VOLUME_X_POS     STATUSBAR_X_POS+ICON_BATTERY_WIDTH+ICON_PLUG_WIDTH+2+2
+#define ICON_VOLUME_WIDTH     14
+#define ICON_PLAY_STATE_X_POS STATUSBAR_X_POS+ICON_BATTERY_WIDTH+ICON_PLUG_WIDTH+ICON_VOLUME_WIDTH+2+2+2
+#define ICON_PLAY_STATE_WIDTH 7
+#define ICON_PLAY_MODE_X_POS  STATUSBAR_X_POS+ICON_BATTERY_WIDTH+ICON_PLUG_WIDTH+ICON_VOLUME_WIDTH+ICON_PLAY_STATE_WIDTH+2+2+2+2
+#define ICON_PLAY_MODE_WIDTH  7
+#define ICON_SHUFFLE_X_POS    STATUSBAR_X_POS+ICON_BATTERY_WIDTH+ICON_PLUG_WIDTH+ICON_VOLUME_WIDTH+ICON_PLAY_STATE_WIDTH+ICON_PLAY_MODE_WIDTH+2+2+2+2+2
+#define ICON_SHUFFLE_WIDTH    7
+#define LOCK_X_POS            STATUSBAR_X_POS+ICON_BATTERY_WIDTH+ICON_PLUG_WIDTH+ICON_VOLUME_WIDTH+ICON_PLAY_STATE_WIDTH+ICON_PLAY_MODE_WIDTH+ICON_SHUFFLE_WIDTH+2+2+2+2+2+2
+#define LOCK_WIDTH            5
+#define TIME_X_POS            STATUSBAR_WIDTH-5*6-1
+
+/* Symbolic names for icons */
+enum
+{
+    Icon_Lock = 0
+};
+enum
+{
+    Icon_Plug = 0,
+    Icon_Speaker,
+    Icon_Mute,
+    Icon_Play,
+    Icon_Stop,
+    Icon_Pause,
+    Icon_FastForward,
+    Icon_FastBackward,
+    Icon_Record,
+    Icon_RecPause,
+    Icon_Normal,
+    Icon_Repeat,
+    Icon_Shuffle
+};
+
+extern void statusbar_wipe(void);
+extern void statusbar_icon_battery(int percent, bool charging);
+extern void statusbar_icon_volume(int percent);
+extern void statusbar_icon_play_state(int state);
+extern void statusbar_icon_play_mode(int mode);
+extern void statusbar_icon_shuffle(void);
+extern void statusbar_icon_lock(void);
+#ifdef HAVE_RTC
+extern void statusbar_time(void);
+#endif
 #endif /* End HAVE_LCD_BITMAP */
-
-
-
-
-
diff --git a/apps/recorder/widgets.c b/apps/recorder/widgets.c
new file mode 100644
index 0000000..1c3f0b1
--- /dev/null
+++ b/apps/recorder/widgets.c
@@ -0,0 +1,161 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: not checked in
+ *
+ * Copyright (C) 2002 Markus Braun
+ *
+ * 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>
+
+#include "widgets.h"
+
+#ifdef HAVE_LCD_BITMAP
+/*
+ * Print a progress bar
+ */
+void progressbar(int x, int y, int width, int height, int percent, int direction)
+{
+    int pos;
+    int i,j;
+
+    /* draw horizontal lines */
+    for(i=x+1;i<=x+width-2;i++) {
+        DRAW_PIXEL(i,y);
+        DRAW_PIXEL(i,(y+height-1));
+    }
+
+    /* draw vertical lines */
+    for(i=1;i<height;i++) {
+        DRAW_PIXEL(x,(y+i));
+        DRAW_PIXEL((x+width-1),(y+i));
+    }
+
+    /* clear edge pixels */
+    CLEAR_PIXEL(x,y);
+    CLEAR_PIXEL((x+width-1),y);
+    CLEAR_PIXEL(x,(y+height-1));
+    CLEAR_PIXEL((x+width-1),(y+height-1));
+
+    /* clear pixels in progress bar */
+    for(i=1;i<=width-2;i++) {
+        for(j=1;j<=height-2;j++) {
+            CLEAR_PIXEL((x+i),(y+j));
+            CLEAR_PIXEL((x+i),(y+j));
+        }
+    }
+
+    /* draw bar */
+    pos=percent;
+    if(pos<0)
+        pos=0;
+    if(pos>100)
+        pos=100;
+
+    switch (direction)
+    {
+        case Grow_Right:
+            pos=(width-2)*pos/100;
+            for(i=1;i<=pos;i++)
+                for(j=1;j<height-1;j++)
+                    DRAW_PIXEL((x+i),(y+j));
+            break;
+        case Grow_Left:
+            pos=(width-2)*(100-pos)/100;
+            for(i=pos+1;i<=width-2;i++)
+                for(j=1;j<height-1;j++)
+                    DRAW_PIXEL((x+i),(y+j));
+            break;
+        case Grow_Down:
+            pos=(height-2)*pos/100;
+            for(i=1;i<=pos;i++)
+                for(j=1;j<width-1;j++)
+                    DRAW_PIXEL((x+j),(y+i));
+            break;
+        case Grow_Up:
+            pos=(height-2)*(100-pos)/100;
+            for(i=pos+1;i<=height-2;i++)
+                for(j=1;j<width-1;j++)
+                    DRAW_PIXEL((x+j),(y+i));
+            break;
+    }
+
+}
+
+
+/*
+ * Print a slidebar bar
+ */
+void slidebar(int x, int y, int width, int height, int percent, int direction)
+{
+    int pos;
+    int i,j;
+
+    /* draw horizontal lines */
+    for(i=x+1;i<=x+width-2;i++) {
+        DRAW_PIXEL(i,y);
+        DRAW_PIXEL(i,(y+height-1));
+    }
+
+    /* draw vertical lines */
+    for(i=1;i<height;i++) {
+        DRAW_PIXEL(x,(y+i));
+        DRAW_PIXEL((x+width-1),(y+i));
+    }
+
+    /* clear edge pixels */
+    CLEAR_PIXEL(x,y);
+    CLEAR_PIXEL((x+width-1),y);
+    CLEAR_PIXEL(x,(y+height-1));
+    CLEAR_PIXEL((x+width-1),(y+height-1));
+
+    /* clear pixels in progress bar */
+    for(i=1;i<=width-2;i++)
+        for(j=1;j<=height-2;j++) {
+            CLEAR_PIXEL((x+i),(y+j));
+            CLEAR_PIXEL((x+i),(y+j));
+        }
+
+    /* draw point */
+    pos=percent;
+    if(pos<0)
+        pos=0;
+    if(pos>100)
+        pos=100;
+
+    switch (direction)
+    {
+        case Grow_Right:
+            pos=(width-height-1)*pos/100;
+            break;
+        case Grow_Left:
+            pos=(width-height-1)*(100-pos)/100;
+            break;
+        case Grow_Down:
+            pos=(height-width-1)*pos/100;
+            break;
+        case Grow_Up:
+            pos=(height-width-1)*(100-pos)/100;
+            break;
+    }
+
+    if(direction == Grow_Left || direction == Grow_Right)
+        for(i=1;i<height;i++)
+            for(j=1;j<height;j++)
+                DRAW_PIXEL((x+pos+i),(y+j));
+    else
+        for(i=1;i<width;i++)
+            for(j=1;j<width;j++)
+                DRAW_PIXEL((x+i),(y+pos+j));
+}
+#endif
diff --git a/apps/recorder/widgets.h b/apps/recorder/widgets.h
new file mode 100644
index 0000000..bae9f39
--- /dev/null
+++ b/apps/recorder/widgets.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: not checked in
+ *
+ * Copyright (C) 2002 Markus Braun
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef __WIDGETS_H__
+#define __WIDGETS_H__
+#include <lcd.h>
+
+#ifdef HAVE_LCD_BITMAP
+/* Directions for progressbar and scrollbar */
+enum
+{
+    Grow_Right = 0,
+    Grow_Left,
+    Grow_Down,
+    Grow_Up
+};
+
+extern void progressbar(int x, int y, int width, int height, int percent, int direction);
+extern void slidebar(int x, int y, int width, int height, int percent, int direction);
+#endif /* HAVE_LCD_BITMAP */
+#endif /* __WIDGETS_H__ */
diff --git a/apps/settings.c b/apps/settings.c
index 4160721..f3e7e55 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -275,6 +275,9 @@
     
     rtc_config_block[0x11] = (unsigned char)global_settings.avc;
     
+    rtc_config_block[0x12] = (unsigned char)
+        ((global_settings.statusbar & 1));
+
     memcpy(&rtc_config_block[0x24], &global_settings.total_uptime, 4);
     
     if(save_config_buffer())
@@ -347,6 +350,10 @@
         
         if (rtc_config_block[0x11] != 0xFF)
             global_settings.avc = rtc_config_block[0x11];
+
+        if (rtc_config_block[0x12] != 0xFF) {
+            global_settings.statusbar = rtc_config_block[0x12] & 1;
+        }
     
         if (rtc_config_block[0x24] != 0xFF)
             memcpy(&global_settings.total_uptime, &rtc_config_block[0x24], 4);
@@ -378,6 +385,7 @@
     global_settings.wps_display = DEFAULT_WPS_DISPLAY;
     global_settings.mp3filter   = true;
     global_settings.sort_case   = false;
+    global_settings.statusbar   = true;
     global_settings.playlist_shuffle = false;
     global_settings.discharge    = 0;
     global_settings.total_uptime = 0;
diff --git a/apps/settings.h b/apps/settings.h
index b39ac73..e66bf8f 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -62,6 +62,9 @@
 
     /* while playing screen settings  */
     int wps_display;   /* 0=id3, 1=file, 2=parse */
+
+    /* show status bar */
+    bool statusbar;    /* 0=hide, 1=show */
     
     /* geeky persistent statistics */
     unsigned int total_uptime; /* total uptime since rockbox was first booted */
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index 98c47b7..7ab1b04 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -76,6 +76,13 @@
 }
 #endif
 
+#ifdef HAVE_LCD_BITMAP
+static void statusbar(void)
+{
+    set_bool( "[Show status bar]", &global_settings.statusbar );
+}
+#endif
+
 void settings_menu(void)
 {
     int m;
@@ -89,6 +96,9 @@
 #ifdef HAVE_CHARGE_CTRL
         { "Deep discharge",  deep_discharge  },
 #endif
+#ifdef HAVE_LCD_BITMAP
+        { "Status bar",      statusbar       },
+#endif
     };
     bool old_shuffle = global_settings.playlist_shuffle;
     
diff --git a/apps/status.c b/apps/status.c
index fde7146..c4bd958 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -24,8 +24,18 @@
 #include "settings.h"
 #include "status.h"
 #include "mpeg.h"
+#include "wps.h"
+#ifdef HAVE_LCD_BITMAP
+#include "icons.h"
+#endif
+#include "power.h"
+
 static enum playmode current_mode;
 
+#ifdef HAVE_LCD_BITMAP
+bool statusbar_enabled = true;
+#endif
+
 void status_init(void)
 {
     status_set_playmode(STATUS_STOP);
@@ -36,6 +46,22 @@
     current_mode = mode;
 }
 
+#ifdef HAVE_LCD_BITMAP
+bool statusbar(bool state)
+{
+    bool laststate=statusbar_enabled;
+
+    statusbar_enabled=state;
+
+    return(laststate);
+}
+
+void statusbar_toggle(void)
+{
+    statusbar_enabled=!statusbar_enabled;
+}
+#endif
+
 void status_draw(void)
 {
 #if defined(HAVE_LCD_CHARCELLS) && !defined(SIMULATOR)
@@ -97,4 +123,28 @@
             break;
     }
 #endif
+#ifdef HAVE_LCD_BITMAP
+    int battlevel = battery_level();
+    int volume = mpeg_val2phys(SOUND_VOLUME, global_settings.volume);
+
+    if(global_settings.statusbar && statusbar_enabled) {
+        statusbar_wipe();
+#ifdef HAVE_CHARGE_CTRL
+        statusbar_icon_battery(battlevel,charger_enabled);
+#else
+        statusbar_icon_battery(battlevel,false);
+#endif
+        statusbar_icon_volume(volume);
+        statusbar_icon_play_state(current_mode+Icon_Play);
+        if (global_settings.loop_playlist)
+            statusbar_icon_play_mode(Icon_Repeat);
+        else
+            statusbar_icon_play_mode(Icon_Normal);
+        if(global_settings.playlist_shuffle) statusbar_icon_shuffle();
+        if (keys_locked) statusbar_icon_lock();
+#ifdef HAVE_RTC
+        statusbar_time();
+#endif
+    }
+#endif
 }
diff --git a/apps/status.h b/apps/status.h
index 344d12f..41251be 100644
--- a/apps/status.h
+++ b/apps/status.h
@@ -23,11 +23,20 @@
 {
     STATUS_PLAY,
     STATUS_STOP,
-    STATUS_PAUSE
+    STATUS_PAUSE,
+    STATUS_FASTFORWARD,
+    STATUS_FASTBACKWARD,
+    STATUS_RECORD,
+    STATUS_RECORD_PAUSE
 };
 
 void status_init(void);
 void status_set_playmode(enum playmode mode);
+#ifdef HAVE_LCD_BITMAP
+extern bool statusbar_enabled;
+bool statusbar(bool state);
+void statusbar_toggle(void);
+#endif
 void status_draw(void);
 
 #endif
diff --git a/apps/tree.c b/apps/tree.c
index 733545a..68b893c 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -65,12 +65,12 @@
 
 #ifdef HAVE_LCD_BITMAP
 
-#define TREE_MAX_ON_SCREEN   ((LCD_HEIGHT-MARGIN_Y)/LINE_HEIGTH)
+#define TREE_MAX_ON_SCREEN   ((LCD_HEIGHT-MARGIN_Y)/LINE_HEIGTH-LINE_Y)
 #define TREE_MAX_LEN_DISPLAY 16 /* max length that fits on screen */
  
 #define MARGIN_Y      0  /* Y pixel margin */
 #define MARGIN_X      12 /* X pixel margin */
-#define LINE_Y      0 /* Y position the entry-list starts at */
+#define LINE_Y      (global_settings.statusbar&&statusbar_enabled?1:0) /* Y position the entry-list starts at */
 #define LINE_X      2 /* X position the entry-list starts at */
 #define LINE_HEIGTH 8 /* pixels for each text line */
 
@@ -226,7 +226,7 @@
                 icon_type = File;
         }
         lcd_bitmap(bitmap_icons_6x8[icon_type], 
-                   6, MARGIN_Y+(i-start)*LINE_HEIGTH, 6, 8, true);
+                   6, MARGIN_Y+(LINE_Y+i-start)*LINE_HEIGTH, 6, 8, true);
 #endif
 
         /* if MP3 filter is on, cut off the extension */
@@ -264,6 +264,7 @@
 {
     char buf[MAX_PATH];
     int i;
+    int lasti=-1;
     int rc;
     int button;
     int browse_speed = 0;
@@ -274,33 +275,12 @@
     if (numentries == -1) 
         return -1;  /* root is not a directory */
 
-    put_cursorxy(0, CURSOR_Y + dircursor, true);
+    put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor, true);
 
     while(1) {
         bool restore = false;
 
-        if ( numentries ) {
-            i = start+dircursor;
-            
-            /* if MP3 filter is on, cut off the extension */
-            if (global_settings.mp3filter && 
-                (dircacheptr[i]->attr &
-                 (TREE_ATTR_M3U|TREE_ATTR_MP3)))
-            {
-                int len = strlen(dircacheptr[i]->name);
-                char temp = dircacheptr[i]->name[len-4];
-                dircacheptr[i]->name[len-4] = 0;
-                lcd_puts_scroll(LINE_X, LINE_Y+dircursor, 
-                                dircacheptr[i]->name);
-                dircacheptr[i]->name[len-4] = temp;
-            }
-            else
-                lcd_puts_scroll(LINE_X, LINE_Y+dircursor,
-                                dircacheptr[i]->name);
-        }
-        lcd_update();
-
-        button = button_get(true);
+        button = button_get_w_tmo(HZ/5);
         switch ( button ) {
             case TREE_EXIT:
                 i=strlen(currdir);
@@ -327,6 +307,8 @@
             case BUTTON_OFF:
                 mpeg_stop();
                 status_set_playmode(STATUS_STOP);
+                status_draw();
+                restore = true;
                 break;
 #endif
 
@@ -389,7 +371,7 @@
                         if (browse_speed < TREE_MAX_ON_SCREEN - 1) {
                             /* moving the cursor up through a full screen */
                             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor,
-                                        false);
+                                         false);
                             dircursor--;
                             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor, true);
                         }
@@ -489,7 +471,7 @@
                                 dircursor=7;
                                 put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor, true);
                             }
-                            
+
                         } 
                         else {
                             /* leaving the cursor at bottom line and moving screen up */
@@ -561,9 +543,15 @@
             case TREE_MENU: {
                 bool lastfilter = global_settings.mp3filter;
                 bool lastsortcase = global_settings.sort_case;
+#ifdef HAVE_LCD_BITMAP
+                bool laststate=statusbar(false);
+#endif
                 browse_speed = 0;
                 lcd_stop_scroll();
                 main_menu();
+#ifdef HAVE_LCD_BITMAP
+                statusbar(laststate);
+#endif
                 /* do we need to rescan dir? */
                 if ( lastfilter != global_settings.mp3filter ||
                      lastsortcase != global_settings.sort_case)
@@ -591,8 +579,26 @@
                 }
                 break;
 
+#ifdef HAVE_RECORDER_KEYPAD
+            case BUTTON_F3:
+#endif
+#ifdef HAVE_LCD_BITMAP
+                if(global_settings.statusbar) {
+                    statusbar_toggle();
+                    if(CURSOR_Y+LINE_Y+dircursor>TREE_MAX_ON_SCREEN) {
+                        start++;
+                        dircursor--;
+                    }
+                    restore = true;
+                }
+#endif
+                break;
+
 #ifndef SIMULATOR
-            case SYS_USB_CONNECTED:
+            case SYS_USB_CONNECTED: {
+#ifdef HAVE_LCD_BITMAP
+                bool laststate=statusbar(false);
+#endif
                 /* Tell the USB thread that we are safe */
                 DEBUGF("dirbrowse got SYS_USB_CONNECTED\n");
                 usb_acknowledge(SYS_USB_CONNECTED_ACK);
@@ -607,7 +613,11 @@
                 dirlevel = 0;
                 dircursor = 0;
                 start = 0;
-                break;
+#ifdef HAVE_LCD_BITMAP
+                statusbar(laststate);
+#endif
+            }
+            break;
 #endif
         }
 
@@ -617,7 +627,32 @@
             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor, true);
         }
 
-        lcd_stop_scroll();
+        if ( numentries ) {
+            i = start+dircursor;
+
+            /* if MP3 filter is on, cut off the extension */
+            if(lasti!=i || restore) {
+                lasti=i;
+                lcd_stop_scroll();
+                if (global_settings.mp3filter && 
+                    (dircacheptr[i]->attr &
+                     (TREE_ATTR_M3U|TREE_ATTR_MP3)))
+                {
+                    int len = strlen(dircacheptr[i]->name);
+                    char temp = dircacheptr[i]->name[len-4];
+                    dircacheptr[i]->name[len-4] = 0;
+                    lcd_puts_scroll(LINE_X, LINE_Y+dircursor, 
+                                    dircacheptr[i]->name);
+                    dircacheptr[i]->name[len-4] = temp;
+                }
+                else
+                    lcd_puts_scroll(LINE_X, LINE_Y+dircursor,
+                                    dircacheptr[i]->name);
+            }
+        }
+        status_draw();
+        lcd_update();
+
     }
 
     return false;
diff --git a/apps/wps.c b/apps/wps.c
index c3398e2..db97a3c 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -34,8 +34,16 @@
 #include "power.h"
 #include "status.h"
 #include "main_menu.h"
+#ifdef HAVE_LCD_BITMAP
+#include "icons.h"
+#include "widgets.h"
+#endif
 
-#define LINE_Y      1 /* initial line */
+#ifdef HAVE_LCD_BITMAP
+#define LINE_Y      (global_settings.statusbar&&statusbar_enabled?1:0) /* Y position the entry-list starts at */
+#else /* HAVE_LCD_BITMAP */
+#define LINE_Y      0 /* Y position the entry-list starts at */
+#endif /* HAVE_LCD_BITMAP */
 
 #define PLAY_DISPLAY_DEFAULT         0 
 #define PLAY_DISPLAY_FILENAME_SCROLL 1 
@@ -47,6 +55,8 @@
 #define RELEASE_MASK (BUTTON_MENU | BUTTON_STOP)
 #endif
 
+bool keys_locked = false;
+
 static void draw_screen(struct mp3entry* id3)
 {
     lcd_clear_display();
@@ -83,14 +93,14 @@
                 strncpy(szArtist,szTok,sizeof(szArtist));
                 szArtist[sizeof(szArtist)-1] = 0;
                 szDelimit = strrchr(id3->path, ch);
-                lcd_puts(0,0, szArtist?szArtist:"<nothing>");
+                lcd_puts(0,LINE_Y, szArtist?szArtist:"<nothing>");
 
                 // removes the .mp3 from the end of the display buffer
                 szPeriod = strrchr(szDelimit, '.');
                 if (szPeriod != NULL)
                     *szPeriod = 0;
 
-                lcd_puts_scroll(0,LINE_Y,(++szDelimit));
+                lcd_puts_scroll(0,LINE_Y+1,(++szDelimit));
                 break;
             }
             case PLAY_DISPLAY_FILENAME_SCROLL:
@@ -99,14 +109,14 @@
                 char* szLast = strrchr(id3->path, ch);
 
                 if (szLast)
-                    lcd_puts_scroll(0,0, (++szLast));
+                    lcd_puts_scroll(0,LINE_Y, (++szLast));
                 else
-                    lcd_puts_scroll(0,0, id3->path);
+                    lcd_puts_scroll(0,LINE_Y, id3->path);
                 break;
             }
             case PLAY_DISPLAY_DEFAULT:
             {
-                int l = 0;
+                int l = LINE_Y;
 #ifdef HAVE_LCD_BITMAP
                 char buffer[64];
 
@@ -115,16 +125,28 @@
                 lcd_puts(0, l++, id3->album?id3->album:"");
                 lcd_puts(0, l++, id3->artist?id3->artist:"");
 
-                if(id3->vbr)
-                    snprintf(buffer, sizeof(buffer), "%d kbit (avg)",
-                             id3->bitrate);
-                else
-                    snprintf(buffer, sizeof(buffer), "%d kbit", id3->bitrate);
+                if(LINE_Y==0) {
+                    if(id3->vbr)
+                        snprintf(buffer, sizeof(buffer), "%d kbit (avg)",
+                                 id3->bitrate);
+                    else
+                        snprintf(buffer, sizeof(buffer), "%d kbit", id3->bitrate);
 
-                lcd_puts(0, l++, buffer);
+                    lcd_puts(0, l++, buffer);
 
-                snprintf(buffer,sizeof(buffer), "%d Hz", id3->frequency);
-                lcd_puts(0, l++, buffer);
+                    snprintf(buffer,sizeof(buffer), "%d Hz", id3->frequency);
+                    lcd_puts(0, l++, buffer);
+                }
+                else {
+                    if(id3->vbr)
+                        snprintf(buffer, sizeof(buffer), "%dkbit(a) %dHz",
+                                 id3->bitrate, id3->frequency);
+                    else
+                        snprintf(buffer, sizeof(buffer), "%dkbit    %dHz",
+                                 id3->bitrate, id3->frequency);
+
+                    lcd_puts(0, l++, buffer);
+                }
 #else
 
                 lcd_puts(0, l++, id3->artist?id3->artist:"<no artist>");
@@ -166,7 +188,6 @@
 int wps_show(void)
 {
     struct mp3entry* id3 = NULL;
-    bool keys_locked = false;
     bool dont_go_to_menu = false;
     bool menu_button_is_down = false;
     bool pending_keylock = true; /* Keylock will go ON next time */
@@ -364,9 +385,15 @@
 #endif
                 if(!keys_locked && !dont_go_to_menu && menu_button_is_down)
                 {
+#ifdef HAVE_LCD_BITMAP
+                        bool laststate=statusbar(false);
+#endif
                     lcd_stop_scroll();
                     button_set_release(old_release_mask);
                     main_menu();
+#ifdef HAVE_LCD_BITMAP
+                        statusbar(laststate);
+#endif
                     old_release_mask = button_set_release(RELEASE_MASK);
                     id3 = mpeg_current_track();
                     draw_screen(id3);
@@ -379,6 +406,17 @@
                 break;
 
 #ifdef HAVE_RECORDER_KEYPAD
+                case BUTTON_F3:
+#ifdef HAVE_LCD_BITMAP
+                    if(global_settings.statusbar) {
+                        statusbar_toggle();
+                        draw_screen(id3);
+                    }
+#endif
+                    break;
+#endif
+
+#ifdef HAVE_RECORDER_KEYPAD
             case BUTTON_OFF:
 #else
             case BUTTON_STOP:
@@ -396,7 +434,10 @@
                 return 0;
                     
 #ifndef SIMULATOR
-            case SYS_USB_CONNECTED:
+            case SYS_USB_CONNECTED: {
+#ifdef HAVE_LCD_BITMAP
+                bool laststate=statusbar(false);
+#endif
                 /* Tell the USB thread that we are safe */
                 DEBUGF("wps got SYS_USB_CONNECTED\n");
                 usb_acknowledge(SYS_USB_CONNECTED_ACK);
@@ -404,16 +445,20 @@
                 /* Wait until the USB cable is extracted again */
                 usb_wait_for_disconnect(&button_queue);
 
+#ifdef HAVE_LCD_BITMAP
+                        statusbar(laststate);
+#endif
                 /* Signal to our caller that we have been in USB mode */
                 return SYS_USB_CONNECTED;
                 break;
+                }
 #endif
             case BUTTON_NONE: /* Timeout */
                 if (mpeg_is_playing() && id3)
                 {
 #ifdef HAVE_LCD_BITMAP
                     snprintf(buffer,sizeof(buffer),
-                             "Time: %d:%02d / %d:%02d",
+                                     "Time:%3d:%02d/%d:%02d",
                              id3->elapsed / 60000,
                              id3->elapsed % 60000 / 1000,
                              id3->length / 60000,
@@ -421,9 +466,9 @@
                         
                     lcd_puts(0, 6, buffer);
                         
-                    lcd_slidebar(1, LCD_HEIGHT-7, LCD_WIDTH-2, 5,
+                            slidebar(0, LCD_HEIGHT-6, LCD_WIDTH, 6,
                                  id3->elapsed*100/id3->length,
-                                 BAR_RIGHT);
+                                     Grow_Right);
                         
                     lcd_update();
 #else
@@ -432,7 +477,7 @@
                     if (global_settings.wps_display ==
                         PLAY_DISPLAY_FILENAME_SCROLL)
                     { 
-                        snprintf(buffer,sizeof(buffer), "%d:%02d/%d:%02d",
+                                snprintf(buffer,sizeof(buffer), "Time:%3d:%02d/%d:%02d",
                                  id3->elapsed / 60000,
                                  id3->elapsed % 60000 / 1000,
                                  id3->length / 60000,
@@ -445,12 +490,6 @@
                 }
                 
                 status_draw();
-#ifdef HAVE_LCD_BITMAP
-                /* draw battery indicator line */
-                lcd_clearline(0,LCD_HEIGHT-1,LCD_WIDTH-1, LCD_HEIGHT-1);
-                lcd_drawline(0,LCD_HEIGHT-1,battery_level() *
-                             (LCD_WIDTH-1) / 100, LCD_HEIGHT-1);
-#endif
                 break;
         }
     }
diff --git a/apps/wps.h b/apps/wps.h
index 4b4e63e..b067315 100644
--- a/apps/wps.h
+++ b/apps/wps.h
@@ -21,6 +21,8 @@
 #include "id3.h"
 #include "playlist.h" 
 
+extern bool keys_locked;
+
 int wps_show(void);
 
 #endif
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c
index 5e86647..fe1e13a 100644
--- a/firmware/drivers/lcd.c
+++ b/firmware/drivers/lcd.c
@@ -529,7 +529,7 @@
  *
  * Memory copy of display bitmap
  */
-unsigned char display[LCD_WIDTH][LCD_HEIGHT/8] __attribute__ ((section (".idata")));
+unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8] __attribute__ ((section (".idata")));
 
 static int font=0;
 static int xmargin=0;
@@ -590,7 +590,7 @@
         lcd_write (true, LCD_CNTL_LOWCOL);
 
         for (x = 0; x < LCD_WIDTH; x++)
-            lcd_write (false, display[x][y]);
+            lcd_write (false, lcd_framebuffer[x][y]);
     }
 }
 
@@ -601,7 +601,7 @@
  */
 void lcd_clear_display (void)
 {
-    memset (display, 0, sizeof display);
+    memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
 #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
     /* this function is being used when simulating a charcell LCD and
        then we update immediately */
@@ -791,7 +791,7 @@
         ny = LCD_HEIGHT - y;      
 
     shift = y & 7;
-    dst2 = &display[x][y/8];
+    dst2 = &lcd_framebuffer[x][y/8];
     ny += shift;
 
     /* Calculate bit masks */
@@ -881,9 +881,6 @@
         lcd_bitmap (ones, x+i, y, 1, ny, false);
 }
 
-#define DRAW_PIXEL(x,y) display[x][y/8] |= (1<<(y&7))
-#define CLEAR_PIXEL(x,y) display[x][y/8] &= ~(1<<(y&7))
-
 void lcd_drawline( int x1, int y1, int x2, int y2 )
 {
     int numpixels;
@@ -1051,144 +1048,6 @@
     }
 }
 
-/*
- * Print a progress bar
- */
-void lcd_progressbar(int x, int y, int width, int height, int percent, int direction)
-{
-    int pos;
-    int i,j;
-
-    /* draw horizontal lines */
-    for(i=x+1;i<=x+width-2;i++) {
-        DRAW_PIXEL(i,y);
-        DRAW_PIXEL(i,(y+height-1));
-    }
-
-    /* draw vertical lines */
-    for(i=1;i<height;i++) {
-        DRAW_PIXEL(x,(y+i));
-        DRAW_PIXEL((x+width-1),(y+i));
-    }
-
-    /* clear edge pixels */
-    CLEAR_PIXEL(x,y);
-    CLEAR_PIXEL((x+width-1),y);
-    CLEAR_PIXEL(x,(y+height-1));
-    CLEAR_PIXEL((x+width-1),(y+height-1));
-
-    /* clear pixels in progress bar */
-    for(i=1;i<=width-2;i++) {
-        for(j=1;j<=height-2;j++) {
-            CLEAR_PIXEL((x+i),(y+j));
-            CLEAR_PIXEL((x+i),(y+j));
-        }
-    }
-
-    /* draw bar */
-    pos=percent;
-    if(pos<0)
-        pos=0;
-    if(pos>100)
-        pos=100;
-
-    switch (direction)
-    {
-        case BAR_RIGHT:
-            pos=(width-2)*pos/100;
-            for(i=1;i<=pos;i++)
-                for(j=1;j<height-1;j++)
-                    DRAW_PIXEL((x+i),(y+j));
-            break;
-        case BAR_LEFT:
-            pos=(width-2)*(100-pos)/100;
-            for(i=pos+1;i<=width-2;i++)
-                for(j=1;j<height-1;j++)
-                    DRAW_PIXEL((x+i),(y+j));
-            break;
-        case BAR_DOWN:
-            pos=(height-2)*pos/100;
-            for(i=1;i<=pos;i++)
-                for(j=1;j<width-1;j++)
-                    DRAW_PIXEL((x+j),(y+i));
-            break;
-        case BAR_UP:
-            pos=(height-2)*(100-pos)/100;
-            for(i=pos+1;i<=height-2;i++)
-                for(j=1;j<width-1;j++)
-                    DRAW_PIXEL((x+j),(y+i));
-            break;
-    }
-
-}
-
-
-/*
- * Print a slidebar bar
- */
-void lcd_slidebar(int x, int y, int width, int height, int percent, int direction)
-{
-    int pos;
-    int i,j;
-
-    /* draw horizontal lines */
-    for(i=x+1;i<=x+width-2;i++) {
-        DRAW_PIXEL(i,y);
-        DRAW_PIXEL(i,(y+height-1));
-    }
-
-    /* draw vertical lines */
-    for(i=1;i<height;i++) {
-        DRAW_PIXEL(x,(y+i));
-        DRAW_PIXEL((x+width-1),(y+i));
-    }
-
-    /* clear edge pixels */
-    CLEAR_PIXEL(x,y);
-    CLEAR_PIXEL((x+width-1),y);
-    CLEAR_PIXEL(x,(y+height-1));
-    CLEAR_PIXEL((x+width-1),(y+height-1));
-
-    /* clear pixels in progress bar */
-    for(i=1;i<=width-2;i++)
-        for(j=1;j<=height-2;j++) {
-            CLEAR_PIXEL((x+i),(y+j));
-            CLEAR_PIXEL((x+i),(y+j));
-        }
-
-    /* draw point */
-    pos=percent;
-    if(pos<0)
-        pos=0;
-    if(pos>100)
-        pos=100;
-
-    switch (direction)
-    {
-        case BAR_RIGHT:
-            pos=(width-height-1)*pos/100;
-            break;
-        case BAR_LEFT:
-            pos=(width-height-1)*(100-pos)/100;
-            break;
-        case BAR_DOWN:
-            pos=(height-width-1)*pos/100;
-            break;
-        case BAR_UP:
-            pos=(height-width-1)*(100-pos)/100;
-            break;
-    }
-
-    if(direction == BAR_LEFT || direction == BAR_RIGHT)
-        for(i=1;i<height;i++)
-            for(j=1;j<height;j++)
-                DRAW_PIXEL((x+pos+i),(y+j));
-    else
-        for(i=1;i<width;i++)
-            for(j=1;j<width;j++)
-                DRAW_PIXEL((x+i),(y+pos+j));
-}
-
 #else
 /* no LCD defined, no code to use */
 #endif
diff --git a/firmware/drivers/lcd.h b/firmware/drivers/lcd.h
index c985cb0..23e3332 100644
--- a/firmware/drivers/lcd.h
+++ b/firmware/drivers/lcd.h
@@ -74,14 +74,13 @@
 #define LCD_WIDTH       112   /* Display width in pixels */
 #define LCD_HEIGHT      64    /* Display height in pixels */
 
-/* Directions for progressbar and scrollbar */
-enum
-{
-    BAR_RIGHT = 0,
-    BAR_LEFT,
-    BAR_DOWN,
-    BAR_UP
-};
+#define DRAW_PIXEL(x,y) lcd_framebuffer[x][y/8] |= (1<<(y&7))
+#define CLEAR_PIXEL(x,y) lcd_framebuffer[x][y/8] &= ~(1<<(y&7))
+
+/*
+ * Memory copy of display bitmap
+ */
+extern unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8] __attribute__ ((section (".idata")));
 
 extern void lcd_putsxy(int x, int y, unsigned char *string, int font);
 extern void lcd_setfont(int font);
@@ -97,8 +96,6 @@
 extern void lcd_clearline( int x1, int y1, int x2, int y2 );
 extern void lcd_drawpixel(int x, int y);
 extern void lcd_clearpixel(int x, int y);
-extern void lcd_progressbar(int x, int y, int width, int height, int percent, int direction);
-extern void lcd_slidebar(int x, int y, int width, int height, int percent, int direction);
 
 #endif /* CHARCELLS / BITMAP */
 
diff --git a/uisimulator/win32/Makefile b/uisimulator/win32/Makefile
index 3a84a2d..4cdcef3 100644
--- a/uisimulator/win32/Makefile
+++ b/uisimulator/win32/Makefile
@@ -68,7 +68,7 @@
 MENUS = games_menu.c screensavers_menu.c settings_menu.c sound_menu.c
 
 ifeq ($(DISPLAY),-DHAVE_LCD_BITMAP)
-   APPS += tetris.c sokoban.c bounce.c boxes.c icons.c bmp.c
+   APPS += tetris.c sokoban.c bounce.c boxes.c icons.c bmp.c widgets.c
 endif
 
 SRCS = button.c dir-win32.c lcd-win32.c panic-win32.c thread-win32.c \
@@ -116,6 +116,9 @@
 $(OBJDIR)/icons.o: $(RECDIR)/icons.c
 	$(CC) $(APPCFLAGS) -c $< -o $@
 
+$(OBJDIR)/widgets.o: $(RECDIR)/widgets.c
+	$(CC) $(APPCFLAGS) -c $< -o $@
+
 $(OBJDIR)/tetris.o: $(RECDIR)/tetris.c
 	$(CC) $(APPCFLAGS) -c $< -o $@
 
diff --git a/uisimulator/win32/lcd-win32.c b/uisimulator/win32/lcd-win32.c
index 510117e..102e262 100644
--- a/uisimulator/win32/lcd-win32.c
+++ b/uisimulator/win32/lcd-win32.c
@@ -27,7 +27,7 @@
 //
 
 // varaibles
-unsigned char       display[LCD_WIDTH][LCD_HEIGHT/8]; // the display
+unsigned char       lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; // the display
 char                bitmap[LCD_HEIGHT][LCD_WIDTH]; // the ui display
 
 BITMAPINFO2 bmi =
@@ -54,7 +54,7 @@
 
 	for (x = 0; x < LCD_WIDTH; x++)
 		for (y = 0; y < LCD_HEIGHT; y++)
-            bitmap[y][x] = ((display[x][y/8] >> (y & 7)) & 1);
+            bitmap[y][x] = ((lcd_framebuffer[x][y/8] >> (y & 7)) & 1);
 
 	InvalidateRect (hGUIWnd, NULL, FALSE);
 
diff --git a/uisimulator/x11/Makefile b/uisimulator/x11/Makefile
index 3d40303..e327a1c 100644
--- a/uisimulator/x11/Makefile
+++ b/uisimulator/x11/Makefile
@@ -81,7 +81,7 @@
 MENUS = games_menu.c screensavers_menu.c settings_menu.c sound_menu.c
 
 ifeq ($(DISPLAY),-DHAVE_LCD_BITMAP)
-   APPS += tetris.c sokoban.c bounce.c boxes.c icons.c bmp.c
+   APPS += tetris.c sokoban.c bounce.c boxes.c icons.c bmp.c widgets.c
 endif
 
 SRCS = screenhack.c uibasic.c resources.c visual.c lcd-x11.c stubs.c \
@@ -167,6 +167,9 @@
 $(OBJDIR)/icons.o: $(RECDIR)/icons.c
 	$(CC) $(APPCFLAGS) -c $< -o $@
 
+$(OBJDIR)/widgets.o: $(RECDIR)/widgets.c
+	$(CC) $(APPCFLAGS) -c $< -o $@
+
 $(OBJDIR)/tetris.o: $(RECDIR)/tetris.c
 	$(CC) $(APPCFLAGS) -c $< -o $@
 
diff --git a/uisimulator/x11/lcd-x11.c b/uisimulator/x11/lcd-x11.c
index 96ce800..e1d1953 100644
--- a/uisimulator/x11/lcd-x11.c
+++ b/uisimulator/x11/lcd-x11.c
@@ -38,11 +38,11 @@
 
 #include "lcd-x11.h"
 
-extern unsigned char display[LCD_WIDTH][LCD_HEIGHT/8];
+extern unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
 extern void screen_resized(int width, int height);
 extern Display *dpy;
 
-unsigned char display_copy[LCD_WIDTH][LCD_HEIGHT/8];
+unsigned char lcd_framebuffer_copy[LCD_WIDTH][LCD_HEIGHT/8];
 
 /* this is in uibasic.c */
 extern void drawdots(int color, XPoint *points, int count);
@@ -61,10 +61,10 @@
 
     for(y=0; y<LCD_HEIGHT; y+=8) {
         for(x=0; x<LCD_WIDTH; x++) {
-            if(display[x][y/8]) {
+            if(lcd_framebuffer[x][y/8]) {
                 /* one or more bits/pixels are set */
                 for(bit=0; bit<8; bit++) {
-                    if(display[x][y/8]&(1<<bit)) {
+                    if(lcd_framebuffer[x][y/8]&(1<<bit)) {
                         points[p].x = x + MARGIN_X;
                         points[p].y = y+bit + MARGIN_Y;
                         p++; /* increase the point counter */
@@ -76,13 +76,13 @@
 #else
     for(y=0; y<LCD_HEIGHT; y+=8) {
         for(x=0; x<LCD_WIDTH; x++) {
-            if(display[x][y/8] || display_copy[x][y/8]) {
+            if(lcd_framebuffer[x][y/8] || lcd_framebuffer_copy[x][y/8]) {
                 /* one or more bits/pixels are changed */
                 unsigned char diff =
-                  display[x][y/8] ^ display_copy[x][y/8];
+                  lcd_framebuffer[x][y/8] ^ lcd_framebuffer_copy[x][y/8];
 
                 for(bit=0; bit<8; bit++) {
-                    if(display[x][y/8]&(1<<bit)) {
+                    if(lcd_framebuffer[x][y/8]&(1<<bit)) {
                         /* set a dot */
                         points[p].x = x + MARGIN_X;
                         points[p].y = y+bit + MARGIN_Y;
@@ -100,7 +100,7 @@
     }
 
     /* copy a huge block */
-    memcpy(display_copy, display, sizeof(display));
+    memcpy(lcd_framebuffer_copy, lcd_framebuffer, sizeof(lcd_framebuffer));
 
 #endif