diff -rN -ubp old-ion-3plus/ioncore/frame.c new-ion-3plus/ioncore/frame.c
--- old-ion-3plus/ioncore/frame.c	2009-03-15 11:57:04.000000000 +0100
+++ new-ion-3plus/ioncore/frame.c	2009-03-15 11:57:04.000000000 +0100
@@ -100,7 +100,8 @@ bool frame_init(WFrame *frame, WWindow *
     frame->brush=NULL;
     frame->bar_brush=NULL;
     frame->mode=mode;
-    frame->tab_min_w=0;
+    frame->float_tab_min_w=0;
+    frame->propor_tab_min_w=0;
     frame->bar_max_width_q=1.0;
     
     gr_stylespec_init(&frame->baseattr);
@@ -282,29 +283,61 @@ int frame_nth_tab_x(WFrame *frame, int n
 }
 
 
+void frame_get_max_width_and_elastic(WFrame * frame,int bar_w,int *maxw,int *elastic,int *minw);//FIXME
+
 static int frame_nth_tab_w_iw(WFrame *frame, int n, bool inner)
 {
     WRectangle bg;
     GrBorderWidths bdw=GR_BORDER_WIDTHS_INIT;
     int m=FRAME_MCOUNT(frame);
+    int maxw,elastic,textw,minw;
     uint w;
+    WRegion *sub;
+    const char * p;
     
-    frame_bar_geom(frame, &bg);
+//fprintf(stderr,"HERE\n");
 
-    if(m==0)
-        m=1;
+    frame_bar_geom(frame, &bg);
 
     if(frame->bar_brush!=NULL)
         grbrush_get_border_widths(frame->bar_brush, &bdw);
     
+    if(m==0){
+	m=1;
+	w=bg.w-bdw.left-bdw.right;
+    }else{
+	frame_get_max_width_and_elastic(frame, bg.w, &maxw, &elastic, &minw);
+	if ((maxw > 0) && (maxw <= frame->propor_tab_min_w)) {
     /* Remove borders */
     w=bg.w-bdw.left-bdw.right-(bdw.tb_ileft+bdw.tb_iright+bdw.spacing)*(m-1);
-    
+//fprintf(stderr,"HEREmin maxw:%i minw:%i totalw:%i pad:%i w:%i (????)\n",maxw,minw,bg.w,elastic,w);
     if(w<=0)
         return 0;
-    
     /* Get n:th tab's portion of free area */
     w=(((n+1)*w)/m-(n*w)/m);
+	}else{
+    
+	    /* Get n:th tab's portion of elastic area */
+	    elastic=(((n+1)*elastic)/m-(n*elastic)/m);
+
+	    sub = mplex_mx_nth((WMPlex*)frame, n);
+	    p=region_displayname(sub);
+	    if(p==NULL)
+		textw=0;
+	    else
+		textw=grbrush_get_text_width(frame->bar_brush,
+					     p, strlen(p));
+	    if (textw<minw)
+		textw=minw;
+	    if (textw<frame->propor_tab_min_w)
+		textw=frame->propor_tab_min_w;
+
+	    if (maxw>0 && (textw>maxw))
+		textw=maxw;
+	    w=elastic+textw;
+//fprintf(stderr,"HEREsub %p maxw:%i minw:%i totalw:%i pad:%i w:%i (%s)\n",(void *)sub,maxw,minw,bg.w,elastic,w,p);
+	}
+    }
     
     /* Add n:th tab's borders back */
     if(!inner){
@@ -312,6 +345,7 @@ static int frame_nth_tab_w_iw(WFrame *fr
         w+=(n==m-1 ? bdw.right : bdw.tb_iright+bdw.spacing);
     }
             
+//fprintf(stderr,"THERE\n");
     return w;
 }
 
diff -rN -ubp old-ion-3plus/ioncore/frame-draw.c new-ion-3plus/ioncore/frame-draw.c
--- old-ion-3plus/ioncore/frame-draw.c	2009-03-15 11:57:04.000000000 +0100
+++ new-ion-3plus/ioncore/frame-draw.c	2009-03-15 11:57:04.000000000 +0100
@@ -225,10 +225,11 @@ void frame_clear_shape(WFrame *frame)
 
 #define CF_TAB_MAX_TEXT_X_OFF 10
 
+void frame_get_max_width_and_elastic(WFrame * frame,int bar_w,int *maxw,int *elastic, int *minw);//FIXME
 
 static void frame_shaped_recalc_bar_size(WFrame *frame, bool complete)
 {
-    int bar_w=0, textw=0, tmaxw=frame->tab_min_w, tmp=0;
+    int bar_w=0, textw, w, tmaxw, tminw, tmp=0;
     WLListIterTmp itmp;
     WRegion *sub;
     const char *p;
@@ -241,43 +242,41 @@ static void frame_shaped_recalc_bar_size
         return;
     
     m=FRAME_MCOUNT(frame);
+    bar_w=frame->bar_max_width_q*REGION_GEOM(frame).w;
     
     if(m>0){
-        grbrush_get_border_widths(frame->bar_brush, &bdw);
-        bdtotal=((m-1)*(bdw.tb_ileft+bdw.tb_iright+bdw.spacing)
-                 +bdw.right+bdw.left);
+
+	frame_get_max_width_and_elastic(frame, bar_w, &tmaxw, &tmp, &tminw);
+//fprintf(stderr," * WID total:%i maxw:%i minw:%i elastic:%i m:%i\n",bar_w,tmaxw,tminw,tmp,m);
+	if ((tmaxw < 0) && (tminw == frame->float_tab_min_w)) {
+	    /* No label truncation needed, good. See how much can be padded. */
+	    w=bar_w-tmp;
 
         FRAME_MX_FOR_ALL(sub, frame, itmp){
             p=region_displayname(sub);
             if(p==NULL)
                 continue;
             
-            textw=grbrush_get_text_width(frame->bar_brush,
-                                         p, strlen(p));
-            if(textw>tmaxw)
-                tmaxw=textw;
+		textw=2*CF_TAB_MAX_TEXT_X_OFF+
+		      grbrush_get_text_width(frame->bar_brush,
+					     p, strlen(p))-
+		      frame->float_tab_min_w;
+//fprintf(stderr," * WID addtextw:%i\n",textw);
+		if (textw>=2*CF_TAB_MAX_TEXT_X_OFF)
+		    w+=2*CF_TAB_MAX_TEXT_X_OFF;
+		else if (textw >=0)
+		    w+=textw;
         }
+	    if (bar_w>w)/*Padded to much*/
+		bar_w=w;
 
-        bar_w=frame->bar_max_width_q*REGION_GEOM(frame).w;
-        if(bar_w<frame->tab_min_w && 
-           REGION_GEOM(frame).w>frame->tab_min_w)
-            bar_w=frame->tab_min_w;
-        
-        tmp=bar_w-bdtotal-m*tmaxw;
-        
-        if(tmp>0){
-            /* No label truncation needed, good. See how much can be padded. */
-            tmp/=m*2;
-            if(tmp>CF_TAB_MAX_TEXT_X_OFF)
-                tmp=CF_TAB_MAX_TEXT_X_OFF;
-            bar_w=(tmaxw+tmp*2)*m+bdtotal;
-        }else{
+	} else {
             /* Some labels must be truncated */
         }
+
     }else{
-        bar_w=frame->tab_min_w;
-        if(bar_w>frame->bar_max_width_q*REGION_GEOM(frame).w)
-            bar_w=frame->bar_max_width_q*REGION_GEOM(frame).w;
+	if(bar_w>frame->float_tab_min_w)
+	    bar_w=frame->float_tab_min_w;
     }
 
     if(complete || frame->bar_w!=bar_w){
@@ -302,9 +301,133 @@ static int init_title(WFrame *frame, int
 }
 
 
+/* Proportional tabs algorithm:
+  * Sort tabs by text sizes.
+  * From smallest to largest do:
+    * Compare current tab width with remaining width (incl. current)
+      divided by no. of remaining tabs (incl. current).
+      * If larger or equal, then set maximum width to the number computed
+	above and set elastic space to zero (resp. to remain after division).
+	(Return.)
+      * If smaller, subctract current width from remaining width and
+	subtract one from no. of remaining tabs. If this is the last
+	tab, then set additional padding to remaining width divided
+	by total number of tabs.
+
+  Do not use w for shaped frames.
+*/
+void frame_get_max_width_and_elastic(WFrame * frame,int bar_w,int *maxw,int *elastic, int *minw){
+    /* Dummy implementation O(n^2), instead of O(n*log(n)) */
+    int textw=0,tmp,tmaxw,tminw=frame->propor_tab_min_w;
+    WLListIterTmp itmp;
+    WRegion *sub;
+    const char *p;
+    GrBorderWidths bdw;
+    //char *title;
+    uint bdtotal,curw,nextw;
+    int i, m, n;
+
+    m=FRAME_MCOUNT(frame);
+    *minw=0;
+    
+//    if(frame->bar_brush==NULL)
+//        *elastic=0;
+//        *maxw=-1;
+//fprintf(stderr,"ZERR\n");
+//        return;
+    if(m>0){
+	grbrush_get_border_widths(frame->bar_brush, &bdw);
+	bdtotal=((m-1)*(bdw.tb_ileft+bdw.tb_iright+bdw.spacing)
+		 +bdw.right+bdw.left);
+	tmp = bar_w - bdtotal;
+//fprintf(stderr,"TMPST:%i barw:%i bdt:%i\n",tmp,bar_w,bdtotal);
+       
+	curw=0;
+	n=m;
+	
+	while (n>0) {
+	    nextw=(uint)-1;/*FIXME: MAXINT*/
+	    if ((signed)curw*n >= tmp) {
+		/*Remainig tabs are too large => equal width.*/
+		*maxw=tmp/n;
+		*elastic=tmp-(*maxw)*n;
+//fprintf(stderr,"TRUNC maxw:%i elastic:%i tmp:%i n:%i\n",*maxw,*elastic,tmp,n);
+		return;
+	    }
+	    FRAME_MX_FOR_ALL(sub, frame, itmp){
+		p=region_displayname(sub);
+		if(p==NULL)
+		    continue;
+		
+		textw=grbrush_get_text_width(frame->bar_brush,
+					     p, strlen(p));
+		if (textw<tminw)
+		    textw=tminw;
+		if((unsigned)textw == curw){
+//fprintf(stderr,"TW:%i (%s)\n",textw,p);
+		    tmp-=textw;
+		    n--;
+		} else if((unsigned)textw>curw){
+		    if ((unsigned)textw<nextw)
+			nextw=textw;
+		}
+	    }
+	    curw = nextw;
+	}
+//fprintf(stderr,"TMP elastic:%i\n",tmp);
+
+	n=0;
+	curw=0;
+	/*We have some padding left. Try to enlarge small tabs*/
+	while (n<m) {
+	    nextw=(uint)-1;/*FIXME: MAXINT*/
+	    FRAME_MX_FOR_ALL(sub, frame, itmp){
+		p=region_displayname(sub);
+		if(p==NULL)
+		    continue;
+		
+		textw=grbrush_get_text_width(frame->bar_brush,
+					     p, strlen(p));
+		if (textw<tminw)
+		    textw=tminw;
+		if((unsigned)textw == curw){
+		    n++;
+		} else if((unsigned)textw>curw){
+		    if ((unsigned)textw<nextw)
+			nextw=textw;
+		}
+	    }
+	    if (nextw>(unsigned)frame->float_tab_min_w)
+	      nextw=frame->float_tab_min_w;
+//fprintf(stderr,"TMP --- tmp:%i n:%i curw:%i nextw:%i min:%i\n",tmp,n,curw,nextw,*minw);
+	    if (n*(nextw-curw)<(unsigned)tmp) {
+		/*we can extend small tabs to 'nextw'*/
+		*minw=nextw;
+		tmp-=n*(nextw-curw);
+//fprintf(stderr,"TMPSUBGO tmp:%i n:%i curw:%i nextw:%i min:%i\n",tmp,n,curw,nextw,*minw);
+	    } else {
+		/*we can extend small tabs only to 'curw+tmp/n'*/
+		*minw+=tmp/n;
+		tmp-=(*minw-curw)*n;
+//fprintf(stderr,"TMPSUBBRK tmp:%i n:%i curw:%i nextw:%i min:%i\n",tmp,n,curw,nextw,*minw);
+		break;
+	    }
+	    if (nextw==(unsigned)frame->float_tab_min_w)
+		break;
+	    curw=nextw;
+	}
+	
+//fprintf(stderr,"TMP elastic:%i min:%i\n",tmp,*minw);
+	*elastic=tmp;
+    } else {
+	*elastic=0;
+    }
+    *maxw=-1;
+}
+
 void frame_recalc_bar(WFrame *frame, bool complete)
 {
-    int textw, i;
+    int textw, i, maxw, padding;
     WLListIterTmp tmp;
     WRegion *sub;
     char *title;
@@ -357,7 +480,8 @@ void frame_draw_bar(const WFrame *frame,
     grbrush_init_attr(frame->bar_brush, &frame->baseattr);
     
     grbrush_draw_textboxes(frame->bar_brush, &geom, frame->titles_n, 
-                           frame->titles, complete);
+			   //frame->titles, complete);
+			   frame->titles, TRUE);
     
     grbrush_end(frame->bar_brush);
 }
@@ -427,14 +551,17 @@ void frame_brushes_updated(WFrame *frame
         frame->bar_h=bdw.top+bdw.bottom+fnte.max_height;
     }
     
+    //FIXME
+    frame->propor_tab_min_w=30;
+
     /* shaped mode stuff */
-    frame->tab_min_w=100;
+    frame->float_tab_min_w=100;
     frame->bar_max_width_q=0.95;
     
     if(grbrush_get_extra(frame->brush, "floatframe_tab_min_w",
-                         'i', &(frame->tab_min_w))){
-        if(frame->tab_min_w<=0)
-            frame->tab_min_w=1;
+			 'i', &(frame->float_tab_min_w))){
+	if(frame->float_tab_min_w<=0)
+	    frame->float_tab_min_w=1;
     }
     
     if(grbrush_get_extra(frame->brush, "floatframe_bar_max_w_q", 
diff -rN -ubp old-ion-3plus/ioncore/frame.h new-ion-3plus/ioncore/frame.h
--- old-ion-3plus/ioncore/frame.h	2009-03-15 11:57:04.000000000 +0100
+++ new-ion-3plus/ioncore/frame.h	2009-03-15 11:57:04.000000000 +0100
@@ -76,7 +76,8 @@ DECLCLASS(WFrame){
     WFrameBarMode barmode;
     int bar_w, bar_h;
     double bar_max_width_q;
-    int tab_min_w;
+    int float_tab_min_w;
+    int propor_tab_min_w;
 };