Index: FL/Fl_Browser.H
===================================================================
--- FL/Fl_Browser.H	(revision 9168)
+++ FL/Fl_Browser.H	(working copy)
@@ -100,6 +100,7 @@
   void item_select(void* item, int val);
   int item_height(void* item) const ;
   int item_width(void* item) const ;
+  int item_quick_width(void *item) const;
   void item_draw(void* item, int X, int Y, int W, int H) const ;
   int full_height() const ;
   int incr_height() const ;
Index: FL/Fl_Browser_.H
===================================================================
--- FL/Fl_Browser_.H	(revision 9168)
+++ FL/Fl_Browser_.H	(working copy)
@@ -61,7 +61,6 @@
   int hposition_;	// where user wants it panned to
   int real_hposition_;	// the current horizontal scrolling position
   int offset_;		// how far down top_ item the real_position is
-  int max_width;	// widest object seen so far
   uchar has_scrollbar_;	// which scrollbars are enabled
   Fl_Font textfont_;
   Fl_Fontsize textsize_;
@@ -69,12 +68,14 @@
   void* top_;		// which item scrolling position is in
   void* selection_;	// which is selected (except for FL_MULTI_BROWSER)
   void *redraw1,*redraw2; // minimal update pointers
-  void* max_width_item;	// which item has max_width_
   int scrollbar_size_;	// size of scrollbar trough
 
   void update_top();
 
 protected:
+  int max_width;	// widest object seen so far
+  void* max_width_item;	// which item has max_width_
+  void set_scrollbar_visiblity();
 
   // All of the following must be supplied by the subclass:
   /**
@@ -118,6 +119,7 @@
     \returns The width of the item in pixels.
   */
   virtual int item_width(void *item) const = 0;
+  virtual int item_quick_width(void *item) const;
   virtual int item_quick_height(void *item) const ;
   /**
     This method must be provided by the subclass to draw the \p item
Index: src/Fl_Browser.cxx
===================================================================
--- src/Fl_Browser.cxx	(revision 9168)
+++ src/Fl_Browser.cxx	(working copy)
@@ -42,15 +42,17 @@
 #define NOTDISPLAYED 2
 
 // WARNING:
-//       Fl_File_Chooser.cxx also has a definition of this structure (FL_BLINE).
+//       Fl_File_Browser.cxx also has a definition of this structure (FL_BLINE).
 //       Changes to FL_BLINE *must* be reflected in Fl_File_Chooser.cxx as well.
 //       This hack in Fl_File_Chooser should be solved.
 //
+// NOTE: This is all fixed in STR2756
 struct FL_BLINE {	// data is in a linked list of these
   FL_BLINE* prev;
   FL_BLINE* next;
   void* data;
   Fl_Image* icon;
+  int width;
   short length;		// sizeof(txt)-1, may be longer than string
   char flags;		// selected, displayed
   char txt[1];		// start of allocated array
@@ -292,6 +294,7 @@
   strcpy(t->txt, newtext);
   t->data = d;
   t->icon = 0;
+  t->width=item_width(t);
   insert(line, t);
 }
 
@@ -337,6 +340,7 @@
     t = n;
   }
   strcpy(t->txt, newtext);
+  t->width=item_width(t);
   redraw_line(t);
 }
 
@@ -411,7 +415,16 @@
   return hmax; // previous version returned hmax+2!
 }
 
+
 /**
+  Returns width of item in pixels.
+  */
+
+int Fl_Browser::item_quick_width(void *item) const {
+  return ((FL_BLINE*)item)->width;
+}
+
+/**
   Returns width of \p item in pixels.
   This takes into account embedded \@ codes within the text() label.
   \param[in] item The item whose width is returned.
@@ -745,6 +758,10 @@
   if (t->flags & NOTDISPLAYED) {
     t->flags &= ~NOTDISPLAYED;
     full_height_ += item_height(t);
+    if (t->width > max_width) {
+      max_width=t->width;
+      max_width_item=t;
+    }
     if (Fl_Browser_::displayed(t)) redraw();
   }
 }
@@ -762,6 +779,10 @@
   FL_BLINE* t = find_line(line);
   if (!(t->flags & NOTDISPLAYED)) {
     full_height_ -= item_height(t);
+    if (max_width_item==t) {
+      max_width=0;
+      max_width_item=0;
+    }
     t->flags |= NOTDISPLAYED;
     if (Fl_Browser_::displayed(t)) redraw();
   }
Index: src/Fl_Browser_.cxx
===================================================================
--- src/Fl_Browser_.cxx	(revision 9168)
+++ src/Fl_Browser_.cxx	(working copy)
@@ -247,6 +247,12 @@
   update_top();
   if (item == item_first()) {position(0); return;}
 
+  // make sure scrollbar set properly  so scrolling/centering works
+  // proper, espically for the last line item which could be hidden
+  // by horizontal scrollbar if it's visible (which it would be
+  // prior to the first draw() call).
+  set_scrollbar_visiblity();
+
   int X, Y, W, H, Yp; bbox(X, Y, W, H);
   void* l = top_;
   Y = Yp = -offset_;
@@ -321,74 +327,123 @@
 #endif
 }
 
-// redraw, has side effect of updating top and setting scrollbar:
-/**
-  Draws the list within the normal widget bounding box.
+/***
+ determine if the scrollbars should be visible or not
+ and make adjustment as needed
 */
-void Fl_Browser_::draw() {
-  int drawsquare = 0;
-  update_top();
+void Fl_Browser_::set_scrollbar_visiblity()
+{
   int full_width_ = full_width();
   int full_height_ = full_height();
+
+  // note that the width may be reset to zero once the widest
+  // added item is removed.  at that point we want to scan
+  // all lines for the widest.
+  if (full_width_==0) {
+    max_width=0;
+    for (void* p = item_first(); p; p = item_next(p)) {
+      int ww=item_quick_width(p);
+      if (ww > max_width) {
+        max_width = ww;
+        max_width_item = p;
+      }
+    }
+    full_width_=max_width;
+  }
+
+  // this is here only to catch some new class from allowing
+  // full_height_ to go to zero when it shouldn't be
+  if (full_height_==0) {
+    full_height_=Fl_Browser_::full_height();
+  }
+
+  // save scrollbar visible status before adjustment to minimize
+  // drawing via damage.
+  unsigned int sb_vis=scrollbar.visible();
+  unsigned int hsb_vis=hscrollbar.visible();
+
+  // turn off horizontal so vertical scrollbar can determine if it
+  // needs to turn on without the horizontal scrollbar.
+  hscrollbar.clear_visible();
+
+  // now get area available
   int X, Y, W, H; bbox(X, Y, W, H);
-  int dont_repeat = 0;
-J1:
-  if (damage() & FL_DAMAGE_ALL) { // redraw the box if full redraw
-    Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
-    draw_box(b, x(), y(), w(), h(), color());
-    drawsquare = 1;
-  }
-  // see if scrollbar needs to be switched on/off:
+
+  // setup vertical scrollbar
   if ((has_scrollbar_ & VERTICAL) && (
 	(has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) {
     if (!scrollbar.visible()) {
       scrollbar.set_visible();
-      drawsquare = 1;
       bbox(X, Y, W, H);
     }
-  } else {
-    top_ = item_first(); real_position_ = offset_ = 0;
+  }
+  else {
     if (scrollbar.visible()) {
       scrollbar.clear_visible();
-      clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
+      bbox(X, Y, W, H);
     }
   }
 
+  // setup horizontal scrollbar
   if ((has_scrollbar_ & HORIZONTAL) && (
 	(has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_ > W)) {
-    if (!hscrollbar.visible()) {
+    // horizontal scrollbar needed
       hscrollbar.set_visible();
-      drawsquare = 1;
+    bbox(X, Y, W, H);
+    // check if vertical scrollbar now needed
+    if ((has_scrollbar_ & VERTICAL) && !scrollbar.visible() && full_height_ > H) {
+      scrollbar.set_visible();
       bbox(X, Y, W, H);
     }
-  } else {
-    real_hposition_ = 0;
-    if (hscrollbar.visible()) {
-      hscrollbar.clear_visible();
-      clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
     }
+  else {
+    // already cleared before setup of vertical scrollbar above
   }
 
-  // Check the vertical scrollbar again, just in case it needs to be drawn
-  // because the horizontal one is drawn.  There should be a cleaner way
-  // to do this besides copying the same code...
-  if ((has_scrollbar_ & VERTICAL) && (
-	(has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) {
-    if (!scrollbar.visible()) {
-      scrollbar.set_visible();
-      drawsquare = 1;
-      bbox(X, Y, W, H);
+  // determine how scrollbars may have changed
+  if (sb_vis!=scrollbar.visible()) {
+    // check if it used to be enabled, if so, reset to ensure all
+    // items start at top.
+    if (sb_vis) {
+      top_ = item_first();
+      real_position_ = offset_ = 0;
     }
-  } else {
-    top_ = item_first(); real_position_ = offset_ = 0;
-    if (scrollbar.visible()) {
-      scrollbar.clear_visible();
+    // cause redraw of widget
+    damage(FL_DAMAGE_ALL);
+  }
+
+  if (hsb_vis!=hscrollbar.visible()) {
+    // check if it used to be enabled, if so, clear any damaged
+    // scroll request and ensure at column 0.
+    if (hsb_vis) {
+      real_hposition_ = 0;
       clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL));
     }
+    // cause redraw of widget
+    damage(FL_DAMAGE_ALL);
   }
+}
 
-  bbox(X, Y, W, H);
 
+// redraw, has side effect of updating top and setting scrollbar:
+/**
+  Draws the list within the normal widget bounding box.
+*/
+void Fl_Browser_::draw() {
+  int drawsquare = 0;
+  update_top();
+
+  // enable/disable scrollbar based on items
+  set_scrollbar_visiblity();
+
+  int X, Y, W, H; bbox(X, Y, W, H);
+
+  if (damage() & FL_DAMAGE_ALL) { // redraw the box if full redraw
+    Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+    draw_box(b, x(), y(), w(), h(), color());
+    drawsquare = 1;
+  }
+
   fl_push_clip(X, Y, W, H);
   // for each line, draw it if full redraw or scrolled.  Erase background
   // if not a full redraw or if it is selected:
@@ -411,8 +466,6 @@
 	draw_box(FL_BORDER_FRAME, X, yy+Y, W, hh, color());
 	draw_focus(FL_NO_BOX, X, yy+Y, W+1, hh+1);
       }
-      int ww = item_width(l);
-      if (ww > max_width) {max_width = ww; max_width_item = l;}
     }
     yy += hh;
   }
@@ -425,43 +478,19 @@
   fl_pop_clip();
   redraw1 = redraw2 = 0;
 
-  if (!dont_repeat) {
-    dont_repeat = 1;
-    // see if changes to full_height caused by calls to slow_height
-    // caused scrollbar state to change, in which case we have to redraw:
-    full_height_ = full_height();
-    full_width_ = full_width();
-    if ((has_scrollbar_ & VERTICAL) &&
-	((has_scrollbar_ & ALWAYS_ON) || position_ || full_height_>H)) {
-      if (!scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
-    } else {
-      if (scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
-    }
-    if ((has_scrollbar_ & HORIZONTAL) &&
-	((has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_>W)) {
-      if (!hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
-    } else {
-      if (hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; }
-    }
-  }
-
   // update the scrollbars and redraw them:
   int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
   int dy = top_ ? item_quick_height(top_) : 0; if (dy < 10) dy = 10;
   if (scrollbar.visible()) {
-    scrollbar.damage_resize(
-	scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W,
-	Y, scrollsize, H);
-    scrollbar.value(position_, H, 0, full_height_);
+    scrollbar.damage_resize(scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W, Y, scrollsize, H);
+    scrollbar.value(position_, H, 0, full_height());
     scrollbar.linesize(dy);
     if (drawsquare) draw_child(scrollbar);
     else update_child(scrollbar);
   }
   if (hscrollbar.visible()) {
-    hscrollbar.damage_resize(
-	X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollsize : Y+H,
-	W, scrollsize);
-    hscrollbar.value(hposition_, W, 0, full_width_);
+    hscrollbar.damage_resize(X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollsize : Y+H, W, scrollsize);
+    hscrollbar.value(hposition_, W, 0, full_width());
     hscrollbar.linesize(dy);
     if (drawsquare) draw_child(hscrollbar);
     else update_child(hscrollbar);
@@ -1027,6 +1056,20 @@
 // Default versions of some of the virtual functions:
 
 /**
+  This method may be provided by the subclass to return the width of the
+  \p item, in pixels.
+  Allow for two additional pixels for the list selection box.
+  This method differs from item_width in that it is only called for
+  selection and scrolling operations.
+  The default implementation calls item_width.
+  \param[in] item The item whose width to return.
+  \returns The width, in pixels.
+*/
+int Fl_Browser_::item_quick_width(void* item) const {
+  return item_width(item);
+}
+
+/**
   This method may be provided by the subclass to return the height of the
   \p item, in pixels.  
   Allow for two additional pixels for the list selection box.
Index: src/Fl_File_Browser.cxx
===================================================================
--- src/Fl_File_Browser.cxx	(revision 9168)
+++ src/Fl_File_Browser.cxx	(working copy)
@@ -80,6 +80,7 @@
   FL_BLINE	*next;		// Next item in list
   void		*data;		// Pointer to data (function)
   Fl_Image      *icon;		// Pointer to optional icon
+  int       width;      // width of item
   short		length;		// sizeof(txt)-1, may be longer than string
   char		flags;		// selected, displayed
   char		txt[1];		// start of allocated array
