Index: FL/Fl_Browser_.H
===================================================================
--- FL/Fl_Browser_.H	(revision 9205)
+++ FL/Fl_Browser_.H	(working copy)
@@ -71,7 +71,13 @@
   void *redraw1,*redraw2; // minimal update pointers
   void* max_width_item;	// which item has max_width_
   int scrollbar_size_;	// size of scrollbar trough
+  int flags_ex_;  // extended flags for class
 
+
+
+
+  static const int FLAG_EX_FULL_KB_SELECT=8;     // change selection bar on pgup/pgdn/home/end
+
   void update_top();
 
 protected:
@@ -360,6 +366,15 @@
   */
   void scrollbar_left() { scrollbar.align(FL_ALIGN_LEFT); }
   void sort(int flags=0);
+
+ /**
+   enable or disable support for changing selection bar when keyboard
+   pgup/pgdn/home/end are used.
+  */
+  void enable_full_kb_select() { flags_ex_|=FLAG_EX_FULL_KB_SELECT; };
+  void disable_full_kb_select() { flags_ex_&=~FLAG_EX_FULL_KB_SELECT; };
+  bool using_full_kb_select() { return (flags_ex_ & FLAG_EX_FULL_KB_SELECT)!=0; };
+
 };
 
 #endif
Index: src/Fl_Browser.cxx
===================================================================
--- src/Fl_Browser.cxx	(revision 9205)
+++ src/Fl_Browser.cxx	(working copy)
@@ -76,7 +76,7 @@
   \returns The next item after \p item, or NULL if there are none after this one.
   \see item_first(), item_last(), item_next(), item_prev()
 */
-void* Fl_Browser::item_next(void* item) const {return ((FL_BLINE*)item)->next;}
+void* Fl_Browser::item_next(void* item) const {return  item ? ((FL_BLINE*)item)->next : item_first();}
 
 /**
   Returns the previous item before \p item.
@@ -84,7 +84,7 @@
   \returns The previous item before \p item, or NULL if there none before this one.
   \see item_first(), item_last(), item_next(), item_prev()
 */
-void* Fl_Browser::item_prev(void* item) const {return ((FL_BLINE*)item)->prev;}
+void* Fl_Browser::item_prev(void* item) const {return item ? ((FL_BLINE*)item)->prev : item_last();}
 
 /**
   Returns the very last item in the list.
Index: src/Fl_Browser_.cxx
===================================================================
--- src/Fl_Browser_.cxx	(revision 9205)
+++ src/Fl_Browser_.cxx	(working copy)
@@ -704,25 +704,73 @@
 
   // must do shortcuts first or the scrollbar will get them...
   if (event == FL_ENTER || event == FL_LEAVE) return 1;
+  int X, Y, W, H; bbox(X, Y, W, H);
   if (event == FL_KEYBOARD && type() >= FL_HOLD_BROWSER) {
-    void* l1 = selection_;
-    void* l = l1; if (!l) l = top_; if (!l) l = item_first();
+    void* ls = selection_;
+    void* l = ls; if (!l) l = top_; if (!l) l = item_first();
     if (l) {
       if (type()==FL_HOLD_BROWSER) {
         switch (Fl::event_key()) {
         case FL_Down:
-          while ((l = item_next(l)))
-            if (item_height(l)>0) {select_only(l, when()); break;}
+          while ((ls = item_next(ls)))
+            if (item_height(ls)>0) {select_only(ls, when()); break;}
             return 1;
         case FL_Up:
-          while ((l = item_prev(l))) {
-	    if (item_height(l)>0) {
-	      select_only(l, when());
+          while ((ls = item_prev(ls))) {
+            if (item_height(ls)>0) {
+              select_only(ls, when());
 	      break; // no need to test wp (return 1)
 	    }
 	  }
           return 1;
+        // check if class should handle moving selection bar when
+        // using the keyboard for home/end/pgup/pgdn.
+        if (using_full_kb_select() && ls) {
+          switch (Fl::event_key()) {
+            case FL_Home:
+              if (selection_!=item_first()) {
+                select_only(item_first(), when());
+              }
+              // allow scrollbar to adjust
+              break;
+            case FL_End:
+              for (void *nl;(nl=item_next(ls));ls=nl);
+              if (selection_!=ls) {
+                select_only(ls, when());
+              }
+              // allow scrollbar to adjust
+              break;
+            case FL_Page_Down:
+            case FL_Page_Up:
+              // figure out entries per box (assumes all items are same height)
+              int itemheight=item_height(item_first());
+              int linesperbox=(H+itemheight-1)/itemheight;
+              // adjust one less for proper paging
+              // (first(pgup)/last(pgdn) item of previous page becomes last(pgup)/first(pgdn) item)
+              linesperbox--;
+              // determine if we prevent scrollbar from getting key press
+              bool eatkey=!displayed(ls);
+              // find the line to highlight
+              while (linesperbox>0) {
+                void *nl=(Fl::event_key()==FL_Page_Down) ? item_next(ls) : item_prev(ls);
+                if (!nl) break;
+                ls=nl;
+                if (item_height(ls)>0) {
+                  linesperbox--;
+                }
+              }
+              if (selection_!=ls) {
+                select_only(ls, when());
+              }
+              // abort if we had to bring this selection into view
+              if (eatkey) {
+                return 1;
+              }
+              // allow scrollbar to adjust
+              break;
+          }
         } 
+
       } else  {
         switch (Fl::event_key()) {
         case FL_Enter:
@@ -741,7 +789,7 @@
         case FL_Down:
           while ((l = item_next(l))) {
             if (Fl::event_state(FL_SHIFT|FL_CTRL))
-              select(l, l1 ? item_selected(l1) : 1, when());
+              select(l, ls ? item_selected(ls) : 1, when());
 	    if (wp.deleted()) return 1;
             if (item_height(l)>0) goto J1;
           }
@@ -749,7 +797,7 @@
         case FL_Up:
           while ((l = item_prev(l))) {
             if (Fl::event_state(FL_SHIFT|FL_CTRL))
-              select(l, l1 ? item_selected(l1) : 1, when());
+              select(l, ls ? item_selected(ls) : 1, when());
 	    if (wp.deleted()) return 1;
             if (item_height(l)>0) goto J1;
           }
@@ -767,7 +815,6 @@
   if (Fl_Group::handle(event)) return 1;
   if (wp.deleted()) return 1;
 
-  int X, Y, W, H; bbox(X, Y, W, H);
   int my;
 // NOTE:
 // instead of:
@@ -974,6 +1021,7 @@
   max_width_item = 0;
   scrollbar_size_ = 0;
   redraw1 = redraw2 = 0;
+  flags_ex_= 0;
   end();
 }
 
Index: src/Fl_Check_Browser.cxx
===================================================================
--- src/Fl_Check_Browser.cxx	(revision 9205)
+++ src/Fl_Check_Browser.cxx	(working copy)
@@ -90,11 +90,11 @@
 }
 
 void *Fl_Check_Browser::item_next(void *l) const {
-	return ((cb_item *)l)->next;
+  return l ? ((cb_item *)l)->next : item_first();
 }
 
 void *Fl_Check_Browser::item_prev(void *l) const {
-	return ((cb_item *)l)->prev;
+  return l ? ((cb_item *)l)->prev : item_last();
 }
 
 int Fl_Check_Browser::item_height(void *) const {
