Index: apps/gui/list.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/list.c,v
retrieving revision 1.21
diff -u -r1.21 list.c
--- apps/gui/list.c	4 Jun 2006 17:14:17 -0000	1.21
+++ apps/gui/list.c	24 Jun 2006 07:39:14 -0000
@@ -29,7 +29,7 @@
 #include "list.h"
 #include "scrollbar.h"
 #include "statusbar.h"
-#include "textarea.h"
+#include "textarea.h"
 
 #ifdef HAVE_LCD_CHARCELLS
 #define SCROLL_LIMIT 1
@@ -43,7 +43,7 @@
 static bool offset_out_of_view = false;
 #endif
 
-
+static struct gui_list* last_list_displayed = 0 ;
 
 void gui_list_init(struct gui_list * gui_list,
     list_get_name callback_get_item_name,
@@ -61,7 +61,11 @@
     gui_list->cursor_flash_state=false;
 #ifdef HAVE_LCD_BITMAP
     gui_list->offset_position = 0;
-#endif
+#endif
+    gui_list->last_displayed_selected_item = -1 ;
+    gui_list->last_displayed_start_item = -1 ;
+    gui_list->old_cursor_x = -1 ;
+    gui_list->old_cursor_y = -1 ;
 }
 
 void gui_list_set_display(struct gui_list * gui_list, struct screen * display)
@@ -173,12 +177,53 @@
         text_pos = 1;
 #endif
 
-    gui_textarea_clear(display);
+    //gui_textarea_clear(display);
 #ifdef HAVE_LCD_BITMAP
     screen_set_xmargin(display, text_pos);
 #endif
-
-    for(i = 0;i < display->nb_lines;i++)
+
+
+    
+    unsigned long start = current_tick ; // remove in production code
+    bool optimize = false ; // remove in production code
+    int fontheight ; // remove in production code
+    int nsi = gui_list->start_item ;
+    int n ;
+    /* tagcache is sneaky, and reuses the same gui_list for all its lists;
+      * this complicates our pointer check, 
+      * and necessitates the default case on the button switch in gui_synclist_do_button
+      */
+    if( gui_list == last_list_displayed && nsi == gui_list->last_displayed_start_item ) {    
+        optimize = true ; // remove in production code
+        n = gui_list->last_displayed_selected_item - nsi ;
+        int m = gui_list->selected_item - nsi ;
+        if( m < n ) {
+            i = m ;
+            ++n ;
+        } else { //if( n > m ) {
+            i = n ;
+            n = m + 1 ;
+        }
+        //~ } else {
+            //~ return ;
+        //~ }
+        
+        int old_cursor_x = gui_list->old_cursor_x ;
+        if(  old_cursor_x != -1 ) {
+            screen_put_cursorxy(display, old_cursor_x, gui_list->old_cursor_y, false);
+        }
+    } else {
+        gui_textarea_clear(display);
+        i = 0 ;
+        n = display->nb_lines ;
+        gui_list->last_displayed_start_item = nsi ;
+        last_list_displayed = gui_list ;
+    }
+    
+    gui_list->last_displayed_selected_item = gui_list->selected_item ;
+    
+    int oi = i ;
+    for( ; i < n ; ++i )
     {
         char entry_buffer[MAX_PATH];
         unsigned char *entry_name;
@@ -190,12 +235,14 @@
             break;
         entry_name = gui_list->callback_get_item_name(current_item,
                                                       gui_list->data,
-                                                      entry_buffer);
+                                                      entry_buffer);
+        
 #ifdef HAVE_LCD_BITMAP
         /* position the string at the correct offset place */
         int item_offset;
         int item_width,h;
-        display->getstringsize(entry_name, &item_width, &h);
+        display->getstringsize(entry_name, &item_width, &h);
+        fontheight = h ;
 
         if (offset_out_of_view)
             item_offset = gui_list->offset_position;
@@ -232,8 +279,13 @@
                 display->puts_scroll(text_pos, i, entry_name);
 #endif
 
-            if(draw_cursor)
-                screen_put_cursorxy(display, cursor_pos, i, true);
+            if(draw_cursor) {
+                screen_put_cursorxy(display, cursor_pos, i, true);
+                gui_list->old_cursor_x = cursor_pos ;
+                gui_list->old_cursor_y = i ;
+            } else {
+                gui_list->old_cursor_x = -1 ;
+            }
         }
         else
         {/* normal item */
@@ -253,7 +305,13 @@
             if(icon)
                 screen_put_iconxy(display, icon_pos, i, icon);
         }
-    }
+    }
+    
+#ifdef ROCKBOX_HAS_LOGF
+    unsigned long end = current_tick ; // remove in production code
+    logf( "ld %s %d", optimize ? "o" : "n", end - start ) ; // remove in production code
+#endif 
+    
 #ifdef HAVE_LCD_BITMAP
     /* Draw the scrollbar if needed*/
     if(draw_scrollbar)
@@ -626,7 +684,6 @@
 
         case LIST_NEXT | BUTTON_REPEAT:
 #ifdef LIST_RC_NEXT
-
         case LIST_RC_NEXT | BUTTON_REPEAT:
 #endif
             gui_synclist_select_next(lists);
@@ -699,7 +756,15 @@
             gui_synclist_draw(lists);
             yield();
             return LIST_PREV;
-#endif
-    }
+#endif
+        
+        case BUTTON_NONE:
+            return 0 ;
+        
+        default:
+            last_list_displayed = 0 ;
+            return 0 ;
+    }
+    
     return 0;
 }
Index: apps/gui/list.h
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/list.h,v
retrieving revision 1.19
diff -u -r1.19 list.h
--- apps/gui/list.h	22 Jun 2006 06:38:57 -0000	1.19
+++ apps/gui/list.h	24 Jun 2006 07:39:15 -0000
@@ -5,7 +5,7 @@
  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  *                     \/            \/     \/    \/            \/
- * $Id: list.h,v 1.19 2006-06-22 06:38:57 amiconn Exp $
+ * $Id: list.h,v 1.18 2006-04-03 08:51:08 bger Exp $
  *
  * Copyright (C) 2005 by Kevin Ferrare
  *
@@ -53,15 +53,19 @@
 #define LIST_PGRIGHT   (BUTTON_ON | BUTTON_RIGHT)
 #define LIST_PGLEFT    (BUTTON_ON | BUTTON_LEFT)
 
+#ifdef CONFIG_REMOTE_KEYPAD
 #define LIST_RC_NEXT   BUTTON_RC_RIGHT
 #define LIST_RC_PREV   BUTTON_RC_LEFT
+#endif /* CONFIG_REMOTE_KEYPAD */
 
 #elif CONFIG_KEYPAD == PLAYER_PAD
 #define LIST_NEXT      BUTTON_RIGHT
 #define LIST_PREV      BUTTON_LEFT
 
+#ifdef CONFIG_REMOTE_KEYPAD
 #define LIST_RC_NEXT   BUTTON_RC_RIGHT
 #define LIST_RC_PREV   BUTTON_RC_LEFT
+#endif /* CONFIG_REMOTE_KEYPAD */
 
 #elif CONFIG_KEYPAD == ONDIO_PAD
 #define LIST_NEXT      BUTTON_DOWN
@@ -148,7 +152,11 @@
      * or should continue (by going to bottom/top) */
     bool limit_scroll;
     /* The data that will be passed to the callback function YOU implement */
-    void * data;
+    void * data;
+    int last_displayed_selected_item ;
+    int last_displayed_start_item ;
+    int old_cursor_x ;
+    int old_cursor_y ;
 };
 
 /*
