This commit was generated by cvs2svn to compensate for changes in r5121,
[chise/xemacs-chise.git.1] / lwlib / xlwtabs.c
index 32c282c..e58d6fa 100644 (file)
@@ -1,30 +1,25 @@
  /* Tabs Widget for XEmacs.
     Copyright (C) 1999 Edward A. Falk
-
  This file is part of XEmacs.
-
  XEmacs is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.
-
  XEmacs is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  for more details.
-
  You should have received a copy of the GNU General Public License
  along with XEmacs; see the file COPYING.  If not, write to
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
-
- /* Synched up with: Tabs.c 1.27.  
-
- #### This file contains essential XEmacs related fixes to the original
- verison of the Tabs widget. Be VERY careful about syncing if you ever
- update to a more recent version. In general this is probably now a
- bad idea. */
-
+ /* Synched up with: Tabs.c 1.23 */
  /*
  * Tabs.c - Index Tabs composite widget
  *
@@ -56,8 +51,8 @@
  * the frame.
  */
 
-/*
- * TODO: min child height = tab height
+/* TODO: min child height = tab height
+ *
  */
 
 #include       <config.h>
@@ -66,8 +61,6 @@
 #include       <X11/Xlib.h>
 #include       <X11/IntrinsicP.h>
 #include       <X11/StringDefs.h>
-
-#include       "lwlib-internal.h"
 #include       "../src/xmu.h"
 #include       "xlwtabsP.h"
 #include       "xlwgcs.h"
@@ -129,7 +122,7 @@ static      char    accelTable[] = "        #augment\n\
        <Key>KP_Down:           highlight(down) \n\
        <Key> :                 page(select)    \n\
         " ;
-static XtAccelerators  defaultAccelerators ; /* #### Never used */
+static XtAccelerators  defaultAccelerators ;
 
 #define        offset(field)   XtOffsetOf(TabsRec, tabs.field)
 static XtResource resources[] = {
@@ -196,7 +189,6 @@ static      void    TabsExpose();
 static void    TabsDestroy();
 static void    TabsRealize();
 static Boolean TabsSetValues();
-static Boolean TabsAcceptFocus();
 static XtGeometryResult        TabsQueryGeometry();
 static XtGeometryResult        TabsGeometryManager();
 static void    TabsChangeManaged();
@@ -245,7 +237,6 @@ static      void    TabsDestroy( Widget w) ;
 static void    TabsResize( Widget w) ;
 static void    TabsExpose( Widget w, XEvent *event, Region region) ;
 static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ;
-static Boolean TabsAcceptFocus(Widget, Time *);
 static Boolean TabsConstraintSetValues(Widget, Widget, Widget,
                        ArgList, Cardinal *) ;
 static XtGeometryResult TabsQueryGeometry(Widget,
@@ -269,17 +260,17 @@ static    void    DrawHighlight( TabsWidget tw, Widget child, Bool undraw) ;
 static void    UndrawTab( TabsWidget tw, Widget child) ;
 
 static void    TabWidth( Widget w) ;
-static int     TabLayout( TabsWidget, Dimension wid, Dimension hgt, Dimension *r_hgt,
+static int     TabLayout( TabsWidget, int wid, int hgt, Dimension *r_hgt,
                        Bool query_only) ;
 static void    GetPreferredSizes(TabsWidget) ;
-static void    MaxChild(TabsWidget, Widget except, Dimension, Dimension) ;
+static void    MaxChild(TabsWidget) ;
 static void    TabsShuffleRows( TabsWidget tw) ;
 static int     PreferredSize( TabsWidget,
                        Dimension *reply_width, Dimension *reply_height,
                        Dimension *reply_cw, Dimension *reply_ch) ;
-static int     PreferredSize2( TabsWidget, Dimension cw, Dimension ch,
+static int     PreferredSize2( TabsWidget, int cw, int ch,
                        Dimension *rw, Dimension *rh) ;
-static int     PreferredSize3( TabsWidget, Dimension wid, Dimension hgt,
+static int     PreferredSize3( TabsWidget, int wid, int hgt,
                        Dimension *rw, Dimension *rh) ;
 static void    MakeSizeRequest(TabsWidget) ;
 
@@ -334,13 +325,9 @@ TabsClassRec tabsClassRec = {
     /* num_resources      */    XtNumber(resources),
     /* xrm_class          */    NULLQUARK,
     /* compress_motion   */    TRUE,
-#if XtSpecificationRelease < 6
-    /* compress_exposure  */   XtExposeCompressMaximal,
-#else
-    /* compress_exposure  */   XtExposeCompressMaximal|XtExposeNoRegion,
-#endif
+    /* compress_exposure  */   TRUE,
     /* compress_enterleave*/   TRUE,
-    /* visible_interest   */    TRUE,
+    /* visible_interest   */    FALSE,
     /* destroy            */    TabsDestroy,
     /* resize             */    TabsResize,
     /* expose             */    TabsExpose,
@@ -348,7 +335,7 @@ TabsClassRec tabsClassRec = {
     /* set_values_hook    */   NULL,
     /* set_values_almost  */    XtInheritSetValuesAlmost,
     /* get_values_hook    */   NULL,
-    /* accept_focus       */    TabsAcceptFocus,
+    /* accept_focus       */    NULL,
     /* version            */   XtVersion,
     /* callback_private   */    NULL,
     /* tm_table           */    defaultTranslations,
@@ -394,10 +381,21 @@ TabsClassRec tabsClassRec = {
 
 WidgetClass tabsWidgetClass = (WidgetClass)&tabsClassRec;
 
-#define TabsNumChildren(tw) (((TabsWidget)tw)->composite.num_children)
-#define TabVisible(tab) \
-       (XtIsManaged(tab) && \
-        ((TabsConstraints)((tab)->core.constraints))->tabs.visible)
+
+
+#ifdef DEBUG
+#ifdef __STDC__
+#define        assert(e) \
+         if(!(e)) fprintf(stderr,"yak! %s at %s:%d\n",#e,__FILE__,__LINE__)
+#else
+#define        assert(e) \
+         if(!(e)) fprintf(stderr,"yak! e at %s:%d\n",__FILE__,__LINE__)
+#endif
+#else
+#define        assert(e)
+#endif
+
+
 \f
 
 /****************************************************************
@@ -426,7 +424,7 @@ TabsInit(Widget request, Widget new, ArgList args, Cardinal *num_args)
     TabsWidget newTw = (TabsWidget)new;
 
     newTw->tabs.numRows = 0 ;
-    newTw->tabs.realRows = 0;
+    newTw->tabs.displayChildren = 0;
 
     GetPreferredSizes(newTw) ;
 
@@ -462,7 +460,7 @@ TabsInit(Widget request, Widget new, ArgList args, Cardinal *num_args)
     newTw->tabs.grey50 = None ;
 
     newTw->tabs.needs_layout = False ;
-
+    
     newTw->tabs.hilight = NULL ;
 
 #ifdef NEED_MOTIF
@@ -482,7 +480,7 @@ TabsConstraintInitialize(Widget request, Widget new,
 {
        TabsConstraints tab = (TabsConstraints) new->core.constraints ;
        tab->tabs.greyAlloc = False ;   /* defer allocation of pixel */
-       tab->tabs.visible = False ;
+       tab->tabs.queried = False ;     /* defer size query */
 
        getBitmapInfo((TabsWidget)XtParent(new), tab) ;
        TabWidth(new) ;
@@ -527,7 +525,7 @@ TabsResize(Widget w)
        int             i ;
        int             num_children = tw->composite.num_children ;
        Widget          *childP ;
-       TabsConstraints tab ; /* #### unused */
+       TabsConstraints tab ;
        Dimension       cw,ch,bw ;
 
        /* Our size has now been dictated by the parent.  Lay out the
@@ -541,13 +539,11 @@ TabsResize(Widget w)
         * to the bottom row.
         */
 
-       tw->tabs.needs_layout = False ;
-
        if( num_children > 0 && tw->composite.children != NULL )
        {
          /* Loop through the tabs and assign rows & x positions */
          (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ;
-         num_children = TabsNumChildren (tw);
+         num_children = tw->tabs.displayChildren;
 
          /* assign a top widget, bring it to bottom row. */
          TabsShuffleRows(tw) ;
@@ -558,29 +554,24 @@ TabsResize(Widget w)
 
          tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ;
          tw->tabs.child_height = ch =
-           tw->core.height < (tw->tabs.tab_total + 2 * SHADWID) ? 0 :
-           tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
+                       tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
+
 
          for(i=0, childP=tw->composite.children;
-               i < num_children;
+               i < num_children;
                ++i, ++childP)
            if( XtIsManaged(*childP) )
            {
              tab = (TabsConstraints) (*childP)->core.constraints ;
-             bw = (*childP)->core.border_width ;
-             /* Don't do anything if we can't see any of the child. */
-             if (ch >= bw*2 && ch > 0 && cw >= bw*2 && cw > 0)
-               XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
-                                 cw-bw*2,ch-bw*2, bw) ;
+             bw = tab->tabs.bwid ;
+             XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
+                         cw-bw*2,ch-bw*2, bw) ;
            }
-         if( XtIsRealized(w) ) {
+         if( XtIsRealized(w) )
            XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
-           /* should not be necessary to explicitly repaint after a
-            * resize, but XEmacs folks tell me it is.
-            */
-           XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
-         }
        }
+
+       tw->tabs.needs_layout = False ;
 } /* Resize */
 
 
@@ -638,8 +629,7 @@ TabsSetValues(Widget current, Widget request, Widget new,
        /* TODO: if any color changes, need to recompute GCs and redraw */
 
        if( tw->core.background_pixel != curtw->core.background_pixel ||
-           tw->core.background_pixmap != curtw->core.background_pixmap ||
-           tw->tabs.font != curtw->tabs.font )
+           tw->core.background_pixmap != curtw->core.background_pixmap )
          if( XtIsRealized(new) )
          {
            TabsFreeGCs(tw) ;
@@ -655,7 +645,6 @@ TabsSetValues(Widget current, Widget request, Widget new,
         */
 
        if( tw->tabs.topWidget != curtw->tabs.topWidget )
-       {
          if( XtIsRealized(tw->tabs.topWidget) )
          {
            Widget              w = tw->tabs.topWidget ;
@@ -674,7 +663,6 @@ TabsSetValues(Widget current, Widget request, Widget new,
          }
          else
            tw->tabs.needs_layout = True ;
-       }
 
        return needRedraw ;
 }
@@ -736,27 +724,11 @@ TabsConstraintSetValues(Widget current, Widget request, Widget new,
 }
 
 
-static Boolean
-TabsAcceptFocus(Widget w, Time *t)
-{
-       if( !w->core.being_destroyed && XtIsRealized(w) &&
-           XtIsSensitive(w) && XtIsManaged(w) && w->core.visible )
-       {
-         Widget p ;
-         for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ;
-         XtSetKeyboardFocus(p,w) ;
-         return True ;
-       }
-       else
-         return False ;
-}
-
-
 
 /*
  * Return preferred size.  Happily accept anything >= our preferred size.
  * (TODO: is that the right thing to do?  Should we always return "almost"
- * if offered more than we need?)
+ * if offerred more than we need?)
  */
 
 static XtGeometryResult
@@ -773,9 +745,11 @@ TabsQueryGeometry(Widget w,
         (!(mode & CWHeight) || intended->height == w->core.height) )
       return XtGeometryNo ;
 
+#ifdef COMMENT
     if( (!(mode & CWWidth) || intended->width >= preferred->width)  &&
        (!(mode & CWHeight) || intended->height >= preferred->height) )
       return XtGeometryYes;
+#endif /* COMMENT */
 
     return XtGeometryAlmost;
 }
@@ -793,7 +767,6 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
        Dimension               s = SHADWID ;
        TabsConstraints         tab = (TabsConstraints)w->core.constraints;
        XtGeometryResult        result ;
-       Dimension               rw, rh ;
 
        /* Position request always denied */
 
@@ -815,11 +788,11 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
            req->border_width == w->core.border_width )
          return XtGeometryNo ;
 
-       rw = req->width + 2 * req->border_width ;
-       rh = req->height + 2 * req->border_width ;
-
-       /* find out how big the children want to be now */
-       MaxChild(tw, w, rw, rh) ;
+       /* updated cached preferred size of the child */
+       tab->tabs.bwid = req->border_width ;
+       tab->tabs.wid = req->width + req->border_width * 2 ;
+       tab->tabs.hgt = req->height + req->border_width * 2 ;
+       MaxChild(tw) ;
 
 
        /* Size changes must see if the new size can be accommodated.
@@ -827,9 +800,7 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
         * size.  A request to shrink will be accepted only if the
         * new size is still big enough for all other children.  A
         * request to shrink that is not big enough for all children
-        * returns an "almost" response with the new proposed size
-        * or a "no" response if unable to shrink at all.
-        *
+        * returns an "almost" response with the new proposed size.
         * A request to grow will be accepted only if the Tabs parent can
         * grow to accommodate.
         *
@@ -841,19 +812,23 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
 
        if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth))
        {
+         Dimension     rw,rh ;         /* child's requested width, height */
          Dimension     cw,ch ;         /* children's preferred size */
          Dimension     aw,ah ;         /* available size we can give child */
          Dimension     th ;            /* space used by tabs */
          Dimension     wid,hgt ;       /* Tabs widget size */
 
-         cw = tw->tabs.max_cw ;
-         ch = tw->tabs.max_ch ;
+         rw = tab->tabs.wid ;
+         rh = tab->tabs.hgt ;
 
-         /* find out what *my* resulting preferred size would be */
+         /* find out what the resulting preferred size would be */
 
-         PreferredSize2(tw, cw, ch, &wid, &hgt) ;
+#ifdef COMMENT
+         MaxChild(tw, &cw, &ch) ;
+#endif /* COMMENT */
+         PreferredSize2(tw, tw->tabs.max_cw,tw->tabs.max_ch, &wid, &hgt) ;
 
-         /* Would my size change?  If so, ask to be resized. */
+         /* Ask to be resized to accommodate. */
 
          if( wid != tw->core.width || hgt != tw->core.height )
          {
@@ -863,8 +838,7 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
            myrequest.width = wid ;
            myrequest.height = hgt ;
            myrequest.request_mode = CWWidth | CWHeight ;
-           
-           assert (wid > 0 && hgt > 0);
+
            /* If child is only querying, or if we're going to have to
             * offer the child a compromise, then make this a query only.
             */
@@ -874,7 +848,7 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
 
            result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
 
-           /* !$@# Athena Box widget changes the core size even if QueryOnly
+           /* !$@# Box widget changes the core size even if QueryOnly
             * is set.  I'm convinced this is a bug.  At any rate, to work
             * around the bug, we need to restore the core size after every
             * query geometry request.  This is only partly effective,
@@ -892,7 +866,6 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
            switch( result ) {
              case XtGeometryYes:
              case XtGeometryDone:
-               tw->tabs.needs_layout = True ;
                break ;
 
              case XtGeometryNo:
@@ -903,8 +876,6 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
              case XtGeometryAlmost:
                wid = myreply.width ;
                hgt = myreply.height ;
-               tw->tabs.needs_layout = True ;
-               break ;
            }
          }
 
@@ -932,8 +903,8 @@ TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
              Widget    *childP = tw->composite.children ;
              int       i,bw ;
              w->core.border_width = req->border_width ;
-             for(i=TabsNumChildren (tw); --i >= 0; ++childP)
-               if( TabVisible(*childP) )
+             for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
+               if( XtIsManaged(*childP) )
                {
                  bw = (*childP)->core.border_width ;
                  XtConfigureWidget(*childP, s,tw->tabs.tab_total+s,
@@ -980,12 +951,6 @@ TabsChangeManaged(Widget w)
          tw->tabs.topWidget->core.being_destroyed ) )
       tw->tabs.topWidget = NULL ;
 
-    /* Check whether the highlight tab is still valid. */
-    if( tw->tabs.hilight != NULL &&
-        ( !XtIsManaged(tw->tabs.hilight) ||
-         tw->tabs.hilight->core.being_destroyed ) )
-      tw->tabs.hilight = NULL ;
-
     GetPreferredSizes(tw) ;
     MakeSizeRequest(tw) ;
 
@@ -1001,7 +966,7 @@ TabsChangeManaged(Widget w)
        */
       if( tw->tabs.topWidget != NULL && XtIsRealized(tw->tabs.topWidget) )
       {
-       for(i=TabsNumChildren (tw); --i >= 0; ++childP)
+       for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
          if( !XtIsRealized(*childP) )
            XtRealizeWidget(*childP) ;
 
@@ -1022,6 +987,9 @@ TabsChangeManaged(Widget w)
     if( tw->tabs.topWidget != NULL )
       XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ;
 #endif
+
+
+
 }
 
 
@@ -1066,9 +1034,9 @@ TabsSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
         * widget to be top of stacking order with XawTabsSetTop().
         */
        for(i=0, childP=tw->composite.children;
-             i < TabsNumChildren (tw);
+             i < tw->tabs.displayChildren;
              ++i, ++childP)
-         if( TabVisible(*childP) )
+         if( XtIsManaged(*childP) )
          {
            TabsConstraints tab = (TabsConstraints)(*childP)->core.constraints;
            if( x > tab->tabs.x  &&  x < tab->tabs.x + tab->tabs.width  &&
@@ -1089,10 +1057,11 @@ static  void
 TabsPage(Widget w, XEvent *event, String *params, Cardinal *num_params)
 {
        TabsWidget      tw = (TabsWidget) w ;
-       Widget          newtop = NULL;
+       Widget          newtop ;
        Widget          *childP ;
        int             idx ;
-       int             nc = TabsNumChildren (tw) ;
+       int             i ;
+       int             nc = tw->composite.num_children ;
 
        if( nc <= 0 )
          return ;
@@ -1113,9 +1082,9 @@ TabsPage(Widget w, XEvent *event, String *params, Cardinal *num_params)
        switch( params[0][0] ) {
          case 'u':             /* up */
          case 'U':
-           if( --idx < 0 )
-             idx = nc-1 ;
-           newtop = tw->composite.children[idx] ;
+           if( idx == 0 )
+             idx = nc ;
+           newtop = tw->composite.children[idx-1] ;
            break ;
 
          case 'd':             /* down */
@@ -1127,7 +1096,6 @@ TabsPage(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
          case 'h':
          case 'H':
-         default:
              newtop = tw->composite.children[0] ;
              break ;
 
@@ -1153,10 +1121,11 @@ static  void
 TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
 {
        TabsWidget      tw = (TabsWidget) w ;
-       Widget          newhl = NULL;
+       Widget          newhl ;
        Widget          *childP ;
        int             idx ;
-       int             nc = TabsNumChildren (tw) ;
+       int             i ;
+       int             nc = tw->composite.num_children ;
 
        if( nc <= 0 )
          return ;
@@ -1173,7 +1142,6 @@ TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
        else
        {
-         /* find index of currently highlit child */
          for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
            if( tw->tabs.hilight == *childP )
              break ;
@@ -1181,9 +1149,9 @@ TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
          switch( params[0][0] ) {
            case 'u':           /* up */
            case 'U':
-             if( --idx < 0 )
-               idx = nc-1 ;
-             newhl = tw->composite.children[idx] ;
+             if( idx == 0 )
+               idx = nc ;
+             newhl = tw->composite.children[idx-1] ;
              break ;
 
            case 'd':           /* down */
@@ -1202,10 +1170,6 @@ TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
            case 'E':
                newhl = tw->composite.children[nc-1] ;
                break ;
-
-           default:
-               newhl = tw->tabs.hilight ;
-               break ;
          }
        }
 
@@ -1248,20 +1212,19 @@ XawTabsSetTop(Widget w, Bool callCallbacks)
 
        if( !XtIsSubclass(w->core.parent, tabsWidgetClass) )
        {
-         char line[256] ;
-         sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ;
+         char line[1024] ;
+         sprintf(line, "XawTabsSetTop: widget \"%s\" is not the child of a tabs widget.", XtName(w)) ;
          XtAppWarning(XtWidgetToApplicationContext(w), line) ;
          return ;
        }
 
        if( callCallbacks )
          XtCallCallbackList(w, tw->tabs.popdownCallbacks,
-               (XtPointer)tw->tabs.topWidget) ;
+               (XtPointer)tw->tabs.topWidget) ;
 
        if( !XtIsRealized(w) ) {
          tw->tabs.topWidget = w ;
          tw->tabs.needs_layout = True ;
-         tw->tabs.hilight = NULL; /* The highlight tab might disappear. */
          return ;
        }
 
@@ -1272,14 +1235,6 @@ XawTabsSetTop(Widget w, Bool callCallbacks)
 #endif
 
        tab = (TabsConstraints) w->core.constraints ;
-
-       /* Unhighlight before we start messing with the stacking order. */
-       if( tw->tabs.hilight != NULL )
-         {
-           DrawHighlight(tw, tw->tabs.hilight, True) ;
-           tw->tabs.hilight = NULL;
-         }
-
        if( tab->tabs.row == 0 )
        {
          /* Easy case; undraw current top, undraw new top, assign new
@@ -1316,12 +1271,16 @@ void
 XawTabsSetHighlight(Widget t, Widget w)
 {
        TabsWidget      tw = (TabsWidget)t ;
+       TabsConstraints tab ;
+       Widget          oldtop = tw->tabs.topWidget ;
 
        if( !XtIsSubclass(t, tabsWidgetClass) )
          return ;
 
        if( XtIsRealized(t) && w != tw->tabs.hilight )
        {
+         if( tw->tabs.hilight != NULL )
+           DrawHighlight(tw, tw->tabs.hilight, True) ;
          if( w != NULL )
            DrawHighlight(tw, w, False) ;
        }
@@ -1385,7 +1344,7 @@ DrawTabs(TabsWidget tw, Bool labels)
 
        if( !XtIsRealized((Widget)tw))
          return ;
-
        /* draw tabs and frames by row except for the top tab, which
         * is drawn last.  (This is inefficiently written, but should not
         * be too slow as long as there are not a lot of rows.)
@@ -1394,9 +1353,9 @@ DrawTabs(TabsWidget tw, Bool labels)
        y = tw->tabs.numRows == 1 ? TABDELTA : 0 ;
        for(i=0; i<tw->tabs.numRows; ++i, y += th)
        {
-         for( j=TabsNumChildren (tw), childP=tw->composite.children;
+         for( j=tw->tabs.displayChildren, childP=tw->composite.children;
              --j >= 0; ++childP )
-           if( TabVisible(*childP) )
+           if( XtIsManaged(*childP) )
            {
              tab = (TabsConstraints)(*childP)->core.constraints;
              if( tab->tabs.row == i && *childP != tw->tabs.topWidget )
@@ -1468,11 +1427,11 @@ DrawTab(TabsWidget tw, Widget child, Bool labels)
          {
            if( tab->tabs.lbm_depth == 1 )
              XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
-               0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
+               0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
                x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ;
            else
              XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
-               0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
+               0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
                x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ;
          }
 
@@ -1496,26 +1455,8 @@ DrawFrame(TabsWidget tw)
        GC              botgc = tw->tabs.botGC ;
        Dimension       s = SHADWID ;
        Dimension       ch = tw->tabs.child_height ;
-       if (ch > 0)
-         Draw3dBox((Widget)tw, 0,tw->tabs.tab_total,
-                   tw->core.width, ch+2*s, s, topgc, botgc) ;
-       else
-         {
-           Widget              w = tw->tabs.topWidget ;
-           if (w != NULL)
-             {
-               TabsConstraints tab = (TabsConstraints) w->core.constraints ;
-               Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
-                         tab->tabs.x, 2*s, s, topgc, botgc);
-               Draw3dBox((Widget)tw, tab->tabs.x + tab->tabs.width, 
-                         tw->core.height - 2*s,
-                         tw->core.width - tab->tabs.x - tab->tabs.width, 2*s, s, 
-                         topgc, botgc);
-             }
-           else
-             Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
-                       tw->core.width, 2*s, s, topgc, botgc) ;
-         }
+       Draw3dBox((Widget)tw, 0,tw->tabs.tab_total,
+               tw->core.width, ch+2*s, s, topgc, botgc) ;
 }
 
 
@@ -1649,27 +1590,8 @@ UndrawTab(TabsWidget tw, Widget child)
 \f
        /* GEOMETRY UTILITIES */
 
-       /* Overview:
-        *
-        *  MaxChild(): ask all children (except possibly one) their
-        *  preferred sizes, set max_cw, max_ch accordingly.
-        *
-        *  GetPreferredSizes(): ask all children their preferred sizes,
-        *  set max_cw, max_ch accordingly.
-        *
-        *  PreferredSize(): given max_cw, max_ch, return tabs widget
-        *  preferred size.  Iterate with other widths in order to get
-        *  a reasonable aspect ratio.
-        *
-        *  PreferredSize2(): Given child dimensions, return Tabs
-        *  widget dimensions.
-        *
-        *  PreferredSize3(): Same, except given child dimensions plus
-        *  shadow.
-        */
 
-
-       /* Compute the width of one child's tab.  Positions will be computed
+       /* Compute the size of one child's tab.  Positions will be computed
         * elsewhere.
         *
         *      height: font height + vertical_space*2 + shadowWid*2
@@ -1702,7 +1624,7 @@ TabWidth(Widget w)
        {
          tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ;
          tab->tabs.l_y = (tw->tabs.tab_height +
-                tw->tabs.font->max_bounds.ascent -
+                tw->tabs.font->max_bounds.ascent -
                 tw->tabs.font->max_bounds.descent)/2 ;
        }
 }
@@ -1721,18 +1643,18 @@ TabWidth(Widget w)
         */
 
 static int
-TabLayout(TabsWidget tw, 
-         Dimension wid, 
-         Dimension hgt, 
-         Dimension *reply_height, Bool query_only)
+TabLayout(TabsWidget tw, int wid, int hgt, Dimension *reply_height, Bool query_only)
 {
-       int             i, row, done = 0, display_rows = 0 ;
+       int             i, row ;
        int             num_children = tw->composite.num_children ;
        Widget          *childP ;
        Dimension       w ;
        Position        x,y ;
        TabsConstraints tab ;
 
+       if (!query_only)
+         tw->tabs.displayChildren = 0;
+
        /* Algorithm: loop through children, assign X positions.  If a tab
         * would extend beyond the right edge, start a new row.  After all
         * rows are assigned, make a second pass and assign Y positions.
@@ -1751,14 +1673,10 @@ TabLayout(TabsWidget tw,
            {
              tab = (TabsConstraints) (*childP)->core.constraints ;
              w = tab->tabs.width ;
-
              if( x + w > wid ) {                       /* new row */
-               if (y + tw->tabs.tab_height > hgt && !done)
-                 {
-                   display_rows = row;
-                   done = 1;
-                 }
-               ++row;
+               if (y + tw->tabs.tab_height > hgt)
+                 break;
+               ++row ;
                x = INDENT ;
                y += tw->tabs.tab_height ;
              }
@@ -1768,14 +1686,12 @@ TabLayout(TabsWidget tw,
                tab->tabs.row = row ;
              }
              x += w + SPACING ;
-             if (!query_only && !done)
-               tab->tabs.visible = 1;
-
+             if (!query_only)
+               tw->tabs.displayChildren++;
            }
-         /* If there was only one row, increase the height by TABDELTA */
-         if( ++display_rows == 1 )
+         /* If there was only one row, increse the height by TABDELTA */
+         if( ++row == 1 )
          {
-           row++;
            y = TABDELTA ;
            if( !query_only )
              for(i=num_children, childP=tw->composite.children;
@@ -1789,51 +1705,75 @@ TabLayout(TabsWidget tw,
          y += tw->tabs.tab_height ;
        }
        else
-         display_rows = row = y = 0 ;
+         row = y = 0 ;
 
        if( !query_only ) {
          tw->tabs.tab_total = y ;
-         tw->tabs.numRows = display_rows ;
-         tw->tabs.realRows = row;
+         tw->tabs.numRows = row ;
        }
 
        if( reply_height != NULL )
          *reply_height = y ;
 
-       return display_rows ;
+       return row ;
 }
 
 
 
        /* Find max preferred child size.  Returned sizes include child
-        * border widths.
+        * border widths.  We only ever ask a child its preferred
+        * size once.  After that, the preferred size is updated only
+        * if the child makes a geometry request.
         */
 
 static void
 GetPreferredSizes(TabsWidget tw)
 {
-       MaxChild(tw, NULL, 0,0) ;
+       int                     i ;
+       Widget                  *childP = tw->composite.children ;
+       XtWidgetGeometry        preferred ;
+       TabsConstraints         tab ;
+       Dimension               cw = 0, ch = 0 ;
+
+       for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
+         if( XtIsManaged(*childP) )
+         {
+           tab = (TabsConstraints) (*childP)->core.constraints ;
+           if( !tab->tabs.queried ) {
+             (void) XtQueryGeometry(*childP, NULL, &preferred) ;
+             tab->tabs.bwid = preferred.border_width ;
+             tab->tabs.wid = preferred.width + preferred.border_width * 2 ;
+             tab->tabs.hgt = preferred.height + preferred.border_width * 2 ;
+             tab->tabs.queried = True ;
+           }
+           cw = Max(cw, tab->tabs.wid ) ;
+           ch = Max(ch, tab->tabs.hgt ) ;
+         }
+       tw->tabs.max_cw = cw ;
+       tw->tabs.max_ch = ch ;
 }
 
 
 
        /* Find max preferred child size.  Returned sizes include child
-        * border widths.  If except is non-null, don't ask that one.
-        */
+        * border widths. */
 
 static void
-MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
+MaxChild(TabsWidget tw)
 {
-       int                     i ;
-       Widget                  *childP = tw->composite.children ;
-       XtWidgetGeometry        preferred ;
+       Dimension       cw,ch ; /* child width, height */
+       int             i ;
+       Widget          *childP = tw->composite.children ;
+       TabsConstraints tab ;
+
+       cw = ch = 0 ;
 
        for(i=tw->composite.num_children; --i >=0; ++childP)
-         if( TabVisible (*childP) /*XtIsManaged(*childP)*/  &&  *childP != except )
+         if( XtIsManaged(*childP) )
          {
-           (void) XtQueryGeometry(*childP, NULL, &preferred) ;
-           cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
-           ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
+           tab = (TabsConstraints) (*childP)->core.constraints ;
+           cw = Max(cw, tab->tabs.wid ) ;
+           ch = Max(ch, tab->tabs.hgt ) ;
          }
 
        tw->tabs.max_cw = cw ;
@@ -1851,7 +1791,7 @@ TabsShuffleRows(TabsWidget tw)
 {
        TabsConstraints tab ;
        int             move ;
-       int             real_rows, display_rows ;
+       int             nrows ;
        Widget          *childP ;
        Dimension       th = tw->tabs.tab_height ;
        Position        bottom ;
@@ -1859,7 +1799,7 @@ TabsShuffleRows(TabsWidget tw)
 
        /* There must be a top widget.  If not, assign one. */
        if( tw->tabs.topWidget == NULL && tw->composite.children != NULL )
-         for(i=TabsNumChildren (tw), childP=tw->composite.children;
+         for(i=tw->composite.num_children, childP=tw->composite.children;
              --i >= 0;
              ++childP)
            if( XtIsManaged(*childP) ) {
@@ -1869,44 +1809,38 @@ TabsShuffleRows(TabsWidget tw)
 
        if( tw->tabs.topWidget != NULL )
        {
-         display_rows = tw->tabs.numRows ;
-         real_rows = tw->tabs.realRows ;
-         assert( display_rows <= real_rows ) ;
+         nrows = tw->tabs.numRows ;
+         assert( nrows > 0 ) ;
 
-         if( real_rows > 1 )
+         if( nrows > 1 )
          {
            tab = (TabsConstraints) tw->tabs.topWidget->core.constraints ;
            assert( tab != NULL ) ;
 
-           /* How far to move top row. The selected tab must be on
-              the bottom row of the *visible* rows. */
-           move = (real_rows + 1 - display_rows) - tab->tabs.row ;
-           if (move < 0) 
-             move = real_rows - move;
+           /* how far to move top row */
+           move = nrows - tab->tabs.row ;
            bottom = tw->tabs.tab_total - th ;
 
-           for(i=tw->composite.num_children, childP=tw->composite.children;
+           for(i=tw->tabs.displayChildren, childP=tw->composite.children;
                  --i >= 0;
                  ++childP)
              if( XtIsManaged(*childP) )
              {
                tab = (TabsConstraints) (*childP)->core.constraints ;
-               tab->tabs.row = (tab->tabs.row + move) % real_rows ;
+               tab->tabs.row = (tab->tabs.row + move) % nrows ;
                tab->tabs.y = bottom - tab->tabs.row * th ;
-               tab->tabs.visible = (tab->tabs.row < display_rows);
              }
          }
        }
 }
 
 
-       /* Find preferred size.  Ask children, find size of largest,
+       /* find preferred size.  Ask children, find size of largest,
         * add room for tabs & return.  This can get a little involved,
         * as we don't want to have too many rows of tabs; we may widen
         * the widget to reduce # of rows.
-        *
-        * This function requires that max_cw, max_ch already be set.
         */
+
 static int
 PreferredSize(
        TabsWidget      tw,
@@ -1920,6 +1854,12 @@ PreferredSize(
        Dimension       rwid,rhgt ;
        int             nrow ;
 
+
+       /* find max desired child height */
+#ifdef COMMENT
+       MaxChild(tw, &cw, &ch) ;
+#endif /* COMMENT */
+
        wid = cw = tw->tabs.max_cw ;
        hgt = ch = tw->tabs.max_ch ;
 
@@ -1933,7 +1873,6 @@ PreferredSize(
        if( nrow > 2 && rhgt > rwid )
        {
          Dimension w0, w1 ;
-         int maxloop = 20 ;
 
          /* step 1: start doubling size until it's too big */
          do {
@@ -1946,7 +1885,7 @@ PreferredSize(
          /* step 2: use Newton's method to find ideal size.  Stop within
           * 8 pixels.
           */
-         while( --maxloop > 0 && w1 > w0 + 8 )
+         while( w1 > w0 + 8 )
          {
            wid = (w0+w1)/2 ;
            nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
@@ -1971,22 +1910,18 @@ PreferredSize(
 static int
 PreferredSize2(
        TabsWidget      tw,
-       Dimension       cw,             /* child width, height */
-       Dimension       ch,
+       int             cw,             /* child width, height */
+       int             ch,
        Dimension       *reply_width,   /* total widget size */
        Dimension       *reply_height)
 {
        Dimension       s = SHADWID ;
-       int ret;
 
        /* make room for shadow frame */
        cw += s*2 ;
        ch += s*2 ;
 
-       ret = PreferredSize3(tw, cw, ch, reply_width, reply_height) ;
-
-       assert (*reply_width > 0 && *reply_height > 0);
-       return ret;
+       return PreferredSize3(tw, cw, ch, reply_width, reply_height) ;
 }
 
 
@@ -1995,8 +1930,8 @@ PreferredSize2(
 static int
 PreferredSize3(
        TabsWidget      tw,
-       Dimension       wid,            /* child width, height */
-       Dimension       hgt,
+       int             wid,            /* child width, height */
+       int             hgt,
        Dimension       *reply_width,   /* total widget size */
        Dimension       *reply_height)
 {
@@ -2068,7 +2003,7 @@ getBitmapInfo(TabsWidget tw, TabsConstraints tab)
 
        if( tab->tabs.left_bitmap == None  ||
            !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y,
-               &tab->tabs.lbm_width, &tab->tabs.lbm_height,
+               &tab->tabs.lbm_width, &tab->tabs.lbm_height,
                &bw, &tab->tabs.lbm_depth) )
          tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ;
 }