LCOV - code coverage report
Current view: top level - gdraw - gtabset.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 634 0.0 %
Date: 2017-08-04 Functions: 0 39 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "gdraw.h"
      28             : #include "gresource.h"
      29             : #include "ggadgetP.h"
      30             : #include "gwidget.h"
      31             : #include "ustring.h"
      32             : #include "gkeysym.h"
      33             : 
      34             : static GBox gtabset_box = GBOX_EMPTY; /* Don't initialize here */
      35             : static GBox gvtabset_box = GBOX_EMPTY; /* Don't initialize here */
      36             : static FontInstance *gtabset_font = NULL;
      37             : static int gtabset_inited = false;
      38             : 
      39             : static GResInfo gtabset_ri, gvtabset_ri;
      40             : 
      41             : static GResInfo gtabset_ri = {
      42             :     &gvtabset_ri, &ggadget_ri, &gvtabset_ri, NULL,
      43             :     &gtabset_box,
      44             :     NULL,
      45             :     NULL,
      46             :     NULL,
      47             :     N_("TabSet"),
      48             :     N_("Tab Set"),
      49             :     "GTabSet",
      50             :     "Gdraw",
      51             :     false,
      52             :     omf_border_width|omf_border_shape,
      53             :     NULL,
      54             :     GBOX_EMPTY,
      55             :     NULL,
      56             :     NULL,
      57             :     NULL
      58             : };
      59             : 
      60             : /* Dummy gadget for styling vertical layout */
      61             : static GResInfo gvtabset_ri = {
      62             :     NULL, &gtabset_ri, &gtabset_ri, NULL,
      63             :     &gvtabset_box,
      64             :     NULL,
      65             :     NULL,
      66             :     NULL,
      67             :     N_("VerticalTabSet"),
      68             :     N_("Vertical Tab Set"),
      69             :     "GVTabSet",
      70             :     "Gdraw",
      71             :     false,
      72             :     0,
      73             :     NULL,
      74             :     GBOX_EMPTY,
      75             :     NULL,
      76             :     NULL,
      77             :     NULL
      78             : };
      79             : #define NEST_INDENT     4
      80             : 
      81           0 : static void GTabSetInit() {
      82             : 
      83           0 :     if ( gtabset_inited )
      84           0 : return;
      85             : 
      86           0 :     GGadgetInit();
      87             : 
      88           0 :     _GGadgetCopyDefaultBox(&gtabset_box);
      89           0 :     gtabset_box.border_width = 1; gtabset_box.border_shape = bs_rect;
      90             :     /*gtabset_box.flags = 0;*/
      91           0 :     gtabset_font = _GGadgetInitDefaultBox("GTabSet.",&gtabset_box,NULL);
      92             : 
      93           0 :     gvtabset_box = gtabset_box; /* needs this to figure inheritance */
      94           0 :     _GGadgetInitDefaultBox("GVTabSet.",&gvtabset_box,NULL);
      95             : 
      96           0 :     gtabset_inited = true;
      97             : }
      98             : 
      99           0 : static void GTabSetChanged(GTabSet *gts,int oldsel) {
     100             :     GEvent e;
     101             : 
     102           0 :     e.type = et_controlevent;
     103           0 :     e.w = gts->g.base;
     104           0 :     e.u.control.subtype = et_radiochanged;
     105           0 :     e.u.control.g = &gts->g;
     106           0 :     if ( gts->g.handle_controlevent != NULL )
     107           0 :         (gts->g.handle_controlevent)(&gts->g,&e);
     108             :     else
     109           0 :         GDrawPostEvent(&e);
     110           0 : }
     111             : 
     112           0 : static int DrawLeftArrowTab(GWindow pixmap, GTabSet *gts, int x, int y ) {
     113           0 :     Color fg = gts->g.box->main_foreground;
     114             :     GPoint pts[5];
     115           0 :     int retx = x + gts->arrow_width, cnt;
     116             : 
     117           0 :     if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     118           0 :     GBoxDrawTabOutline(pixmap,&gts->g,x,y,gts->arrow_width,gts->rowh,false);
     119           0 :     gts->haslarrow = true;
     120           0 :         y += (gts->rowh-gts->arrow_size)/2;
     121           0 :         x += (gts->arrow_width-gts->arrow_size/2)/2;
     122           0 :         cnt = 4;
     123           0 :         pts[0].y = (y+(gts->arrow_size-1)/2);        pts[0].x = x;
     124           0 :         pts[1].y = y;                           pts[1].x = x + (gts->arrow_size-1)/2;
     125           0 :         pts[2].y = y+gts->arrow_size-1;      pts[2].x = pts[1].x;
     126           0 :         pts[3] = pts[0];
     127           0 :         if ( !(gts->arrow_size&1 )) {
     128           0 :             ++pts[3].y;
     129           0 :             pts[4] = pts[0];
     130           0 :             cnt = 5;
     131             :         }
     132           0 :         GDrawFillPoly(pixmap,pts,cnt,fg);
     133           0 : return( retx );
     134             : }
     135             : 
     136           0 : static int DrawRightArrowTab(GWindow pixmap, GTabSet *gts, int x, int y ) {
     137           0 :     Color fg = gts->g.box->main_foreground;
     138             :     GPoint pts[5];
     139           0 :     int retx = x + gts->arrow_width, cnt;
     140             : 
     141           0 :     if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     142           0 :     GBoxDrawTabOutline(pixmap,&gts->g,x,y,gts->arrow_width,gts->rowh,false);
     143           0 :     gts->hasrarrow = true;
     144           0 :         y += (gts->rowh-gts->arrow_size)/2;
     145           0 :         x += (gts->arrow_width-gts->arrow_size/2)/2;
     146           0 :         cnt = 4;
     147           0 :         pts[0].y = (y+(gts->arrow_size-1)/2);        pts[0].x = x + (gts->arrow_size-1)/2;
     148           0 :         pts[1].y = y;                           pts[1].x = x;
     149           0 :         pts[2].y = y+gts->arrow_size-1;      pts[2].x = pts[1].x;
     150           0 :         pts[3] = pts[0];
     151           0 :         if ( !(gts->arrow_size&1 )) {
     152           0 :             ++pts[3].y;
     153           0 :             pts[4] = pts[0];
     154           0 :             cnt = 5;
     155             :         }
     156           0 :         GDrawFillPoly(pixmap,pts,cnt,fg);
     157           0 : return( retx );
     158             : }
     159             : 
     160           0 : static int DrawTab(GWindow pixmap, GTabSet *gts, int i, int x, int y ) {
     161           0 :     Color fg = gts->tabs[i].disabled?gts->g.box->disabled_foreground:gts->g.box->main_foreground;
     162             : 
     163           0 :     if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     164           0 :     GBoxDrawTabOutline(pixmap,&gts->g,x,y,gts->tabs[i].width,gts->rowh,i==gts->sel);
     165             : 
     166           0 :     if ( (i==gts->sel) && (gts->g.box->flags&box_active_border_inner) ) {
     167             :         GRect r;
     168           0 :         r.x = x+2;
     169           0 :         r.y = y+1;
     170           0 :         r.width = gts->tabs[i].width-4;
     171           0 :         r.height = gts->rowh-2;
     172           0 :         GDrawFillRect(pixmap,&r,gts->g.box->active_border);
     173             :     }
     174             : 
     175           0 :     GDrawDrawText(pixmap,x+(gts->tabs[i].width-gts->tabs[i].tw)/2,y+gts->rowh-gts->ds,
     176           0 :             gts->tabs[i].name,-1,fg);
     177           0 :     gts->tabs[i].x = x;
     178           0 :     x += gts->tabs[i].width;
     179           0 : return( x );
     180             : }
     181             : 
     182           0 : static int gtabset_expose(GWindow pixmap, GGadget *g, GEvent *event) {
     183           0 :     GTabSet *gts = (GTabSet *) g;
     184             :     int x,y,i,rd, dsel;
     185             :     GRect old1, bounds;
     186           0 :     int bw = GBoxBorderWidth(pixmap,g->box);
     187           0 :     int yoff = ( gts->rcnt==1 ? bw : 0 );
     188             :     Color fg;
     189           0 :     int ni = GDrawPointsToPixels(pixmap,NEST_INDENT);
     190             : 
     191           0 :     if ( g->state == gs_invisible )
     192           0 : return( false );
     193             : 
     194           0 :     GDrawPushClip(pixmap,&g->r,&old1);
     195             : 
     196           0 :     GBoxDrawBackground(pixmap,&g->r,g->box,g->state,false);
     197           0 :     bounds = g->r;
     198             : 
     199           0 :     if ( !gts->vertical ) {
     200             :         /* make room for tabs */
     201           0 :         bounds.y += gts->rcnt*gts->rowh+yoff-1;
     202           0 :         bounds.height -= gts->rcnt*gts->rowh+yoff-1;
     203             :         /* draw border around horizontal tabs only */
     204           0 :         GBoxDrawBorder(pixmap,&bounds,g->box,g->state,false);
     205             :     }
     206           0 :     else if ( g->state==gs_enabled ) {
     207             :         /* background for labels */
     208           0 :         GRect old2, vertListRect = g->r;
     209           0 :         vertListRect.width = gts->vert_list_width+bw-1;
     210           0 :         GDrawPushClip(pixmap,&vertListRect,&old2);
     211           0 :         GBoxDrawBackground(pixmap,&g->r,g->box,gs_pressedactive,false);
     212           0 :         GDrawPopClip(pixmap,&old2);
     213             :     }
     214             : 
     215           0 :     GDrawSetFont(pixmap,gts->font);
     216             : 
     217           0 :     if ( gts->vertical ) {
     218           0 :         x = g->r.x + bw + 3;
     219           0 :         y = g->r.y + bw + 3;
     220           0 :         for ( i=gts->offtop; i<gts->tabcnt; ++i ) {
     221           0 :             fg = gts->tabs[i].disabled?gts->g.box->disabled_foreground:gts->g.box->main_foreground;
     222           0 :             if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     223           0 :             if ( i==gts->sel ) {
     224             :                 GRect r;
     225           0 :                 r.x = x; r.y = y;
     226           0 :                 r.width = gts->vert_list_width-10; r.height = gts->fh;
     227           0 :                 GDrawFillRect(pixmap,&r,gts->g.box->active_border);
     228             :             }
     229           0 :             GDrawDrawText(pixmap,x+gts->tabs[i].nesting*ni,y + gts->as,gts->tabs[i].name,-1,fg);
     230           0 :             y += gts->fh;
     231             :         }
     232           0 :         fg = gts->g.box->main_foreground;
     233           0 :         if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     234           0 :         GDrawDrawLine(pixmap,x + gts->vert_list_width-4, g->r.y + bw,
     235           0 :                              x + gts->vert_list_width-4, g->r.y + g->r.height - (bw+1),
     236             :                              fg);
     237           0 :         if ( gts->vsb != NULL )
     238           0 :             gts->vsb->funcs->handle_expose(pixmap,gts->vsb,event);
     239             :     } else {
     240           0 :         gts->haslarrow = gts->hasrarrow = false;
     241           0 :         if ( gts->scrolled ) {
     242           0 :             x = g->r.x + GBoxBorderWidth(pixmap,gts->g.box);
     243           0 :             y = g->r.y+yoff;
     244           0 :             dsel = 0;
     245           0 :             if ( gts->toff!=0 )
     246           0 :                 x = DrawLeftArrowTab(pixmap,gts,x,y);
     247           0 :             for ( i=gts->toff;
     248           0 :                     (i==gts->tabcnt-1 && x+gts->tabs[i].width < g->r.width) ||
     249           0 :                     (i<gts->tabcnt-1 && x+gts->tabs[i].width < g->r.width-gts->arrow_width ) ;
     250           0 :                     ++i ) {
     251           0 :                 if ( i!=gts->sel )
     252           0 :                     x = DrawTab(pixmap,gts,i,x,y);
     253             :                 else {
     254           0 :                     gts->tabs[i].x = x;
     255           0 :                     x += gts->tabs[i].width;
     256           0 :                     dsel = 1;
     257             :                 }
     258             :             }
     259           0 :             if ( i!=gts->tabcnt ) {
     260           0 :                 int p = gts->g.inner.x+gts->g.inner.width - gts->arrow_width;
     261           0 :                 if ( p>x ) x=p;
     262           0 :                 x = DrawRightArrowTab(pixmap,gts,x,y);
     263           0 :                 gts->tabs[i].x = 0x7fff;
     264             :             }
     265             :             /* This one draws on top of the others, must come last */
     266           0 :             if ( dsel )
     267           0 :                 DrawTab(pixmap,gts,gts->sel,gts->tabs[gts->sel].x, g->r.y + (gts->rcnt-1) * gts->rowh + yoff );
     268             :         } else {
     269             :             /* r is real row, rd is drawn pos */
     270             :             /* rd is 0 at the top of the ggadget */
     271             :             /* r is 0 when it contains tabs[0], (the index in the rowstarts array) */
     272           0 :             for ( rd = 0; rd<gts->rcnt; ++rd ) {
     273           0 :                 int r = (gts->rcnt-1-rd+gts->active_row)%gts->rcnt;
     274           0 :                 y = g->r.y + rd * gts->rowh + yoff;
     275           0 :                 x = g->r.x + (gts->rcnt-1-rd) * gts->offset_per_row + GBoxBorderWidth(pixmap,gts->g.box);
     276           0 :                 for ( i = gts->rowstarts[r]; i<gts->rowstarts[r+1]; ++i )
     277           0 :                     if ( i==gts->sel ) {
     278           0 :                         gts->tabs[i].x = x;
     279           0 :                         x += gts->tabs[i].width;
     280             :                     } else
     281           0 :                         x = DrawTab(pixmap,gts,i,x,y);
     282             :             }
     283             :             /* This one draws on top of the others, must come last */
     284           0 :             DrawTab(pixmap,gts,gts->sel,gts->tabs[gts->sel].x, g->r.y + (gts->rcnt-1) * gts->rowh + yoff );
     285             :         }
     286             :     }
     287           0 :     if ( gts->nested_expose )
     288           0 :         (gts->nested_expose)(pixmap,g,event);
     289           0 :     GDrawPopClip(pixmap,&old1);
     290           0 : return( true );
     291             : }
     292             : 
     293           0 : static int GTabSetRCnt(GTabSet *gts, int totwidth) {
     294             :     int i, off, r, width;
     295           0 :     int bp = GBoxBorderWidth(gts->g.base,gts->g.box) + GDrawPointsToPixels(gts->g.base,5);
     296             : 
     297           0 :     width = totwidth;
     298           0 :     for ( i = off = r = 0; i<gts->tabcnt; ++i ) {
     299           0 :         if ( off!=0 && width-(gts->tabs[i].tw+2*bp)< 0 ) {
     300           0 :             off = 0; ++r;
     301           0 :             width = totwidth;
     302             :         }
     303           0 :         width -= gts->tabs[i].width;
     304           0 :         gts->tabs[i].x = off;
     305           0 :         off ++;
     306             :     }
     307           0 : return( r+1 );
     308             : }
     309             : 
     310           0 : static int GTabSetGetLineWidth(GTabSet *gts,int r) {
     311           0 :     int i, width = 0;
     312             : 
     313           0 :     for ( i=gts->rowstarts[r]; i<gts->rowstarts[r+1]; ++i )
     314           0 :         width += gts->tabs[i].width;
     315           0 : return( width );
     316             : }
     317             : 
     318           0 : static void GTabSetDistributePixels(GTabSet *gts,int r, int widthdiff) {
     319             :     int diff, off, i;
     320             : 
     321           0 :     diff = widthdiff/(gts->rowstarts[r+1]-gts->rowstarts[r]);
     322           0 :     off = widthdiff-diff*(gts->rowstarts[r+1]-gts->rowstarts[r]);
     323           0 :     for ( i=gts->rowstarts[r]; i<gts->rowstarts[r+1]; ++i ) {
     324           0 :         gts->tabs[i].width += diff;
     325           0 :         if ( off ) {
     326           0 :             ++gts->tabs[i].width;
     327           0 :             --off;
     328             :         }
     329             :     }
     330           0 : }
     331             : 
     332             : /* We have rearranged the rows of tabs. We want to make sure that each row */
     333             : /*  row is at least as wide as the row above it */
     334           0 : static void GTabSetFigureWidths(GTabSet *gts) {
     335           0 :     int bp = GBoxBorderWidth(gts->g.base,gts->g.box) + GDrawPointsToPixels(gts->g.base,5);
     336             :     int i, rd;
     337           0 :     int oldwidth=0, width;
     338             : 
     339             :     /* set all row widths to default values */
     340           0 :     for ( i=0; i<gts->tabcnt; ++i ) {
     341           0 :         gts->tabs[i].width = gts->tabs[i].tw + 2*bp;
     342             :     }
     343             :     /* r is real row, rd is drawn pos */
     344             :     /* rd is 0 at the top of the ggadget */
     345             :     /* r is 0 when it contains tabs[0], (the index in the rowstarts array) */
     346           0 :     if ( ( gts->filllines && gts->rcnt>1 ) || (gts->fill1line && gts->rcnt==1) ) {
     347           0 :         for ( rd = 0; rd<gts->rcnt; ++rd ) {
     348           0 :             int r = (rd+gts->rcnt-1-gts->active_row)%gts->rcnt;
     349           0 :             int totwidth = gts->g.r.width-2*GBoxBorderWidth(gts->g.base,gts->g.box) -
     350           0 :                     (gts->rcnt-1-rd)*gts->offset_per_row;
     351           0 :             width = GTabSetGetLineWidth(gts,r);
     352           0 :             GTabSetDistributePixels(gts,r,totwidth-width);
     353             :         }
     354             :     } else {
     355           0 :         for ( rd = 0; rd<gts->rcnt; ++rd ) {              /* r is real row, rd is drawn pos */
     356           0 :             int r = (rd+gts->rcnt-1-gts->active_row)%gts->rcnt;
     357           0 :             width = GTabSetGetLineWidth(gts,r) + (gts->rcnt-1-rd)*gts->offset_per_row;
     358           0 :             if ( rd==0 )
     359           0 :                 oldwidth = width;
     360           0 :             else if ( oldwidth>width )
     361           0 :                 GTabSetDistributePixels(gts,r,oldwidth-width);
     362             :             else
     363           0 :                 oldwidth = width;
     364             :         }
     365             :     }
     366           0 : }
     367             : 
     368             : /* Something happened which would change how many things fit on a line */
     369             : /*  (initialization, change of font, addition or removal of tab, etc.) */
     370             : /* Figure out how many rows we need and then how best to divide the tabs */
     371             : /*  between those rows, and then the widths of each tab */
     372           0 : static void GTabSet_Remetric(GTabSet *gts) {
     373           0 :     int bbp = GBoxBorderWidth(gts->g.base,gts->g.box);
     374           0 :     int bp = bbp + GDrawPointsToPixels(gts->g.base,5);
     375             :     int r, r2, width, i;
     376             :     int as, ds, ld;
     377           0 :     int ni = GDrawPointsToPixels(gts->g.base,NEST_INDENT), in;
     378             : 
     379           0 :     GDrawSetFont(gts->g.base,gts->font);
     380           0 :     GDrawWindowFontMetrics(gts->g.base,gts->font,&as,&ds,&ld);
     381           0 :     gts->as = as; gts->fh = as+ds;
     382           0 :     gts->rowh = as+ds + bbp+GDrawPointsToPixels(gts->g.base,3);
     383           0 :     gts->ds = ds + bbp+GDrawPointsToPixels(gts->g.base,1);
     384           0 :     gts->arrow_size = as+ds;
     385           0 :     gts->arrow_width = gts->arrow_size + 2*GBoxBorderWidth(gts->g.base,gts->g.box);
     386           0 :     gts->vert_list_width = 0;
     387             : 
     388           0 :     for ( i=0; i<gts->tabcnt; ++i ) {
     389           0 :         gts->tabs[i].tw = GDrawGetTextWidth(gts->g.base,gts->tabs[i].name,-1);
     390           0 :         gts->tabs[i].width = gts->tabs[i].tw + 2*bp;
     391           0 :         in = gts->tabs[i].nesting*ni;
     392           0 :         if ( gts->tabs[i].tw+in > gts->vert_list_width )
     393           0 :             gts->vert_list_width = gts->tabs[i].tw+in;
     394             :     }
     395           0 :     if ( gts->vsb ) {
     396           0 :         gts->vert_list_width += gts->vsb->r.width;
     397           0 :         if ( gts->g.inner.height>26 ) {
     398           0 :             int bp = GBoxBorderWidth(gts->g.base,gts->g.box);
     399           0 :             GScrollBarSetBounds(gts->vsb,0,gts->tabcnt,(gts->g.r.height-2*bp-6)/gts->fh);
     400             :         }
     401             :     }
     402           0 :     gts->vert_list_width += 8;
     403             : 
     404           0 :     if ( gts->vertical ) {
     405             :         /* Nothing much to do */
     406           0 :     } else if ( gts->scrolled ) {
     407           0 :         free(gts->rowstarts);
     408           0 :         gts->rowstarts = malloc(2*sizeof(int16));
     409           0 :         gts->rowstarts[0] = 0; gts->rowstarts[1] = gts->tabcnt;
     410           0 :         gts->rcnt = 1;
     411             :     } else {
     412           0 :         width = gts->g.r.width-2*GBoxBorderWidth(gts->g.base,gts->g.box);
     413           0 :         r = GTabSetRCnt(gts,width);
     414           0 :         if ( gts->offset_per_row!=0 && r>1 )
     415           0 :             while ( (r2 = GTabSetRCnt(gts,width-(r-1)*gts->offset_per_row))!=r )
     416           0 :                 r = r2;
     417           0 :         free(gts->rowstarts);
     418           0 :         gts->rowstarts = malloc((r+1)*sizeof(int16));
     419           0 :         gts->rcnt = r;
     420           0 :         gts->rowstarts[r] = gts->tabcnt;
     421           0 :         for ( i=r=0; i<gts->tabcnt; ++i ) {
     422           0 :             if ( gts->tabs[i].x==0 ) 
     423           0 :                 gts->rowstarts[r++] = i;
     424             :         }
     425             :         /* if there is a single tab on the last line and there are more on */
     426             :         /*  the previous line, then things look nicer if we move one of the */
     427             :         /*  tabs from the previous line onto the last line */
     428             :         /*  Providing it fits, of course */
     429           0 :         if ( gts->rowstarts[r]-gts->rowstarts[r-1]==1 && r>1 &&
     430           0 :                 gts->rowstarts[r-1]-gts->rowstarts[r-2]>1 &&
     431           0 :                 gts->tabs[i-1].width+gts->tabs[i-2].width < width-(r-1)*gts->offset_per_row )
     432           0 :             --gts->rowstarts[r-1];
     433             : 
     434           0 :         GTabSetFigureWidths(gts);
     435             :     }
     436           0 : }
     437             : 
     438           0 : static void GTabSetChangeSel(GTabSet *gts, int sel,int sendevent) {
     439             :     int i, width;
     440           0 :     int oldsel = gts->sel;
     441             : 
     442           0 :     if ( sel==-2 )              /* left arrow */
     443           0 :         --gts->toff;
     444           0 :     else if ( sel==-3 )
     445           0 :         ++gts->toff;
     446           0 :     else if ( sel<0 || sel>=gts->tabcnt || gts->tabs[sel].disabled )
     447           0 : return;
     448             :     else {
     449           0 :         if ( gts->vertical )
     450           0 :             gts->sel = sel;
     451             :         else {
     452           0 :             for ( i=0; i<gts->rcnt && sel>=gts->rowstarts[i+1]; ++i );
     453           0 :             if ( gts->active_row != i ) {
     454           0 :                 gts->active_row = i;
     455           0 :                 if ( gts->rcnt>1 && (!gts->filllines || gts->offset_per_row!=0))
     456           0 :                     GTabSetFigureWidths(gts);
     457             :             }
     458           0 :             gts->sel = sel;
     459           0 :             if ( sel<gts->toff )
     460           0 :                 gts->toff = sel;
     461           0 :             else if ( gts->scrolled ) {
     462           0 :                 for ( i=gts->toff; i<sel && gts->tabs[i].x!=0x7fff; ++i );
     463           0 :                 if ( gts->tabs[i].x==0x7fff ) {
     464           0 :                     width = gts->g.r.width-2*gts->arrow_width;    /* it will have a left arrow */
     465           0 :                     if ( sel!=gts->tabcnt )
     466           0 :                         width -= gts->arrow_width;           /* it might have a right arrow */
     467           0 :                     for ( i=sel; i>=0 && width-gts->tabs[i].width>=0; --i )
     468           0 :                         width -= gts->tabs[i].width;
     469           0 :                     if ( ++i>sel ) i = sel;
     470           0 :                     gts->toff = i;
     471             :                 }
     472             :             }
     473             :         }
     474           0 :         if ( oldsel!=sel ) {
     475           0 :             if ( sendevent )
     476           0 :                 GTabSetChanged(gts,oldsel);
     477           0 :             if ( gts->tabs[oldsel].w!=NULL )
     478           0 :                 GDrawSetVisible(gts->tabs[oldsel].w,false);
     479           0 :             if ( gts->tabs[gts->sel].w!=NULL )
     480           0 :                 GDrawSetVisible(gts->tabs[gts->sel].w,true);
     481             :         }
     482             :     }
     483           0 :     _ggadget_redraw(&gts->g);
     484             : }
     485             : 
     486           0 : static int gtabset_mouse(GGadget *g, GEvent *event) {
     487           0 :     GTabSet *gts = (GTabSet *) g;
     488             : 
     489           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused ))
     490           0 : return( false );
     491           0 :     if ( gts->nested_mouse!=NULL )
     492           0 :         if ( (gts->nested_mouse)(g,event))
     493           0 : return( true );
     494             : 
     495           0 :     if ( event->type == et_crossing ) {
     496           0 : return( true );
     497           0 :     } else if ( event->type == et_mousemove ) {
     498           0 : return( true );
     499             :     } else {
     500           0 :         int i, sel= -1, l;
     501           0 :         if ( event->u.mouse.y < gts->g.r.y ||
     502           0 :                 ( !gts->vertical && event->u.mouse.y >= gts->g.inner.y ) ||
     503           0 :                 ( gts->vertical && event->u.mouse.x >= gts->g.inner.x ))
     504           0 : return( false );
     505           0 :         else if ( gts->vertical ) {
     506           0 :             int y = g->r.y + GBoxBorderWidth(g->base,g->box) + 5;
     507           0 :             sel = (event->u.mouse.y-y)/gts->fh + gts->offtop;
     508           0 :             if ( sel<0 || sel>=gts->tabcnt )
     509           0 : return(false);
     510           0 :         } else if ( gts->scrolled ) {
     511           0 :             if ( gts->haslarrow && event->u.mouse.x<gts->tabs[gts->toff].x )
     512           0 :                 sel = -2;       /* left arrow */
     513             :             else {
     514           0 :                 for ( i=gts->toff;
     515           0 :                         i<gts->tabcnt && event->u.mouse.x>=gts->tabs[i].x+gts->tabs[i].width;
     516           0 :                         ++i );
     517           0 :                 if ( gts->hasrarrow && gts->tabs[i].x==0x7fff &&
     518           0 :                         event->u.mouse.x>=gts->tabs[i-1].x+gts->tabs[i-1].width )
     519           0 :                     sel = -3;
     520             :                 else
     521           0 :                     sel = i;
     522             :             }
     523             :         } else {
     524           0 :             l = (event->u.mouse.y-gts->g.r.y)/gts->rowh;       /* screen row */
     525           0 :             if ( l>=gts->rcnt ) l = gts->rcnt-1;               /* can happen on single line tabsets (there's extra space then) */
     526           0 :             l = (gts->rcnt-1-l+gts->active_row)%gts->rcnt;     /* internal row number */
     527           0 :             if ( event->u.mouse.x<gts->tabs[gts->rowstarts[l]].x )
     528           0 :                 sel = -1;
     529           0 :             else if ( event->u.mouse.x>=gts->tabs[gts->rowstarts[l+1]-1].x+gts->tabs[gts->rowstarts[l+1]-1].width )
     530           0 :                 sel = -1;
     531             :             else {
     532           0 :                 for ( i=gts->rowstarts[l]; i<gts->rowstarts[l+1] &&
     533           0 :                         event->u.mouse.x>=gts->tabs[i].x+gts->tabs[i].width; ++i );
     534           0 :                 sel = i;
     535             :             }
     536             :         }
     537           0 :         if ( event->type==et_mousedown ) {
     538           0 :             gts->pressed = true;
     539           0 :             gts->pressed_sel = sel;
     540             :         } else {
     541           0 :             if ( gts->pressed && gts->pressed_sel == sel )
     542           0 :                 GTabSetChangeSel(gts,sel,true);
     543           0 :             gts->pressed = false;
     544           0 :             gts->pressed_sel = -1;
     545             :         }
     546             :     }
     547           0 : return( true );
     548             : }
     549             : 
     550           0 : static int gtabset_key(GGadget *g, GEvent *event) {
     551           0 :     GTabSet *gts = (GTabSet *) g;
     552             :     int i;
     553             : 
     554           0 :     if ( !g->takes_input || !g->takes_keyboard || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused ))
     555           0 : return(false);
     556           0 :     if ( event->type == et_charup )
     557           0 : return( true );
     558             : 
     559           0 :     if (event->u.chr.keysym == GK_Left || event->u.chr.keysym == GK_KP_Left ||
     560           0 :             (event->u.chr.keysym == GK_Tab && (event->u.chr.state&ksm_shift)) ||
     561           0 :             event->u.chr.keysym == GK_BackTab ||
     562           0 :             event->u.chr.keysym == GK_Up || event->u.chr.keysym == GK_KP_Up ) {
     563           0 :         for ( i = gts->sel-1; i>0 && gts->tabs[i].disabled; --i );
     564           0 :         GTabSetChangeSel(gts,i,true);
     565           0 : return( true );
     566           0 :     } else if (event->u.chr.keysym == GK_Right || event->u.chr.keysym == GK_KP_Right ||
     567           0 :             event->u.chr.keysym == GK_Tab ||
     568           0 :             event->u.chr.keysym == GK_Down || event->u.chr.keysym == GK_KP_Down ) {
     569           0 :         for ( i = gts->sel+1; i<gts->tabcnt-1 && gts->tabs[i].disabled; ++i );
     570           0 :         GTabSetChangeSel(gts,i,true);
     571           0 : return( true );
     572             :     }
     573           0 : return( false );
     574             : }
     575             : 
     576           0 : static int gtabset_focus(GGadget *g, GEvent *UNUSED(event)) {
     577             : 
     578           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active ))
     579           0 : return(false);
     580             : 
     581           0 : return( true );
     582             : }
     583             : 
     584           0 : static void gtabset_destroy(GGadget *g) {
     585           0 :     GTabSet *gts = (GTabSet *) g;
     586             :     int i;
     587             : 
     588           0 :     if ( gts==NULL )
     589           0 : return;
     590           0 :     free(gts->rowstarts);
     591           0 :     for ( i=0; i<gts->tabcnt; ++i ) {
     592           0 :         free(gts->tabs[i].name);
     593             : /* This has already been done */
     594             : /*      if ( gts->tabs[i].w!=NULL ) */
     595             : /*          GDrawDestroyWindow(gts->tabs[i].w); */
     596             :     }
     597           0 :     free(gts->tabs);
     598           0 :     _ggadget_destroy(g);
     599             : }
     600             : 
     601           0 : static void GTabSetSetFont(GGadget *g,FontInstance *new) {
     602           0 :     GTabSet *gts = (GTabSet *) g;
     603           0 :     gts->font = new;
     604           0 :     GTabSet_Remetric(gts);
     605           0 : }
     606             : 
     607           0 : static FontInstance *GTabSetGetFont(GGadget *g) {
     608           0 :     GTabSet *gts = (GTabSet *) g;
     609           0 : return( gts->font );
     610             : }
     611             : 
     612           0 : static void _gtabset_redraw(GGadget *g) {
     613           0 :     GTabSet *gts = (GTabSet *) g;
     614             :     int i;
     615             : 
     616           0 :     GDrawRequestExpose(g->base, &g->r, false);
     617           0 :     i = gts->sel;
     618           0 :     if ( gts->tabs[i].w!=NULL )
     619           0 :         GDrawRequestExpose(gts->tabs[i].w, NULL, false);
     620           0 : }
     621             : 
     622           0 : static void _gtabset_move(GGadget *g, int32 x, int32 y ) {
     623           0 :     GTabSet *gts = (GTabSet *) g;
     624             :     int i;
     625           0 :     int32 nx = x+g->inner.x-g->r.x, ny = y+g->inner.y-g->r.y;
     626             : 
     627           0 :     for ( i=0; i<gts->tabcnt; ++i ) if ( gts->tabs[i].w!=NULL )
     628           0 :         GDrawMove(gts->tabs[i].w,nx,ny);
     629           0 :     _ggadget_move(g,x,y);
     630           0 :     if ( gts->vsb!=NULL ) {
     631           0 :         int bp = GBoxBorderWidth(gts->g.base,gts->g.box);
     632           0 :         GGadgetMove(gts->vsb,g->r.x +bp+ gts->vert_list_width - gts->vsb->r.width,
     633           0 :                     gts->g.r.y+bp);
     634             :     }
     635           0 : }
     636             : 
     637           0 : static void _gtabset_resize(GGadget *g, int32 width, int32 height ) {
     638           0 :     GTabSet *gts = (GTabSet *) g;
     639             :     int i;
     640             : 
     641           0 :     _ggadget_resize(g,width,height);
     642           0 :     for ( i=0; i<gts->tabcnt; ++i ) if ( gts->tabs[i].w!=NULL )
     643           0 :         GDrawResize(gts->tabs[i].w,g->inner.width,g->inner.height);
     644           0 :     if ( gts->vsb!=NULL ) {
     645           0 :         int off = gts->offtop;
     646           0 :         int bp = GBoxBorderWidth(gts->g.base,gts->g.box);
     647           0 :         GGadgetResize(gts->vsb,gts->vsb->r.width, gts->g.r.height-2*bp);
     648           0 :         GScrollBarSetBounds(gts->vsb,0,gts->tabcnt,(gts->g.r.height-2*bp-6)/gts->fh);
     649           0 :         if ( gts->offtop + (gts->g.r.height-2*bp-6)/gts->fh > gts->tabcnt )
     650           0 :             off = gts->tabcnt - (gts->g.r.height-2*bp-6)/gts->fh;
     651           0 :         if ( off<0 )
     652           0 :             off = 0;
     653           0 :         if ( off!=gts->offtop ) {
     654           0 :             gts->offtop = off;
     655           0 :             GScrollBarSetPos(gts->vsb, off );
     656           0 :             GGadgetRedraw(&gts->g);
     657             :         }
     658             :     }
     659           0 : }
     660             : 
     661           0 : static void _gtabset_setvisible(GGadget *g,int visible) {
     662           0 :     GTabSet *gts = (GTabSet *) g;
     663             : 
     664           0 :     _ggadget_setvisible(g,visible);
     665           0 :     if ( gts->tabs[gts->sel].w!=NULL )
     666           0 :         GDrawSetVisible(gts->tabs[gts->sel].w, visible);
     667           0 :     if ( gts->vsb!=NULL )
     668           0 :         GGadgetSetVisible(gts->vsb,visible);
     669           0 : }
     670             : 
     671           0 : static int gtabset_FillsWindow(GGadget *g) {
     672           0 : return( g->prev==NULL && _GWidgetGetGadgets(g->base)==g );
     673             : }
     674             : 
     675           0 : static void gtabset_GetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
     676           0 :     GTabSet *gts = (GTabSet *) g;
     677           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     678             :     GRect nested, test;
     679             :     int i;
     680             : 
     681           0 :     memset(&nested,0,sizeof(nested));
     682           0 :     for ( i=0; i<gts->tabcnt; ++i ) {
     683           0 :         GGadget *last = _GWidgetGetGadgets(gts->tabs[i].w);
     684           0 :         if ( last!=NULL ) {
     685           0 :             while ( last->prev!=NULL )
     686           0 :                 last=last->prev;
     687           0 :             GGadgetGetDesiredSize(last,&test,NULL);
     688           0 :             if ( GGadgetFillsWindow(last)) {
     689           0 :                 test.width += 2*last->r.x;
     690           0 :                 test.height += 2*last->r.y;
     691             :             }
     692           0 :             if ( test.width>nested.width ) nested.width = test.width;
     693           0 :             if ( test.height>nested.height ) nested.height = test.height;
     694             :         }
     695             :     }
     696           0 :     if ( gts->vertical ) {
     697           0 :         if ( gts->vsb==NULL && gts->rcnt*gts->fh+10 > nested.height )
     698           0 :             nested.height = gts->tabcnt*gts->fh+10;
     699           0 :         else if ( gts->vsb!=NULL && 2*gts->vsb->r.width + 20 > nested.height )
     700           0 :             nested.height = 2*gts->vsb->r.width + 20;     /* Minimum size for scrollbar arrows, vaguely */
     701             :     }
     702             : 
     703           0 :     if ( g->desired_width>=0 ) nested.width = g->desired_width - 2*bp;
     704           0 :     if ( g->desired_height>=0 ) nested.height = g->desired_height - 2*bp;
     705           0 :     if ( nested.width==0 ) nested.width = 100;
     706           0 :     if ( nested.height==0 ) nested.height = 100;
     707             : 
     708           0 :     if ( inner != NULL )
     709           0 :         *inner = nested;
     710           0 :     if ( gts->vertical ) {
     711           0 :         if ( outer != NULL ) {
     712           0 :             *outer = nested;
     713           0 :             outer->width += gts->vert_list_width + 2*bp;
     714           0 :             outer->height += 2*bp;
     715             :         }
     716             :     } else {
     717           0 :         if ( outer != NULL ) {
     718           0 :             *outer = nested;
     719           0 :             outer->width += 2*bp;
     720           0 :             outer->height += gts->rcnt*gts->rowh + bp;
     721             :         }
     722             :     }
     723           0 : }
     724             : 
     725             : struct gfuncs gtabset_funcs = {
     726             :     0,
     727             :     sizeof(struct gfuncs),
     728             : 
     729             :     gtabset_expose,
     730             :     gtabset_mouse,
     731             :     gtabset_key,
     732             :     NULL,
     733             :     gtabset_focus,
     734             :     NULL,
     735             :     NULL,
     736             : 
     737             :     _gtabset_redraw,
     738             :     _gtabset_move,
     739             :     _gtabset_resize,
     740             :     _gtabset_setvisible,
     741             :     _ggadget_setenabled,                /* Doesn't work right */
     742             :     _ggadget_getsize,
     743             :     _ggadget_getinnersize,
     744             : 
     745             :     gtabset_destroy,
     746             : 
     747             :     NULL,
     748             :     NULL,
     749             :     NULL,
     750             :     NULL,
     751             :     NULL,
     752             :     GTabSetSetFont,
     753             :     GTabSetGetFont,
     754             : 
     755             :     NULL,
     756             :     NULL,
     757             :     NULL,
     758             :     NULL,
     759             :     NULL,
     760             :     NULL,
     761             :     NULL,
     762             :     NULL,
     763             :     NULL,
     764             :     NULL,
     765             :     NULL,
     766             : 
     767             :     gtabset_GetDesiredSize,
     768             :     _ggadget_setDesiredSize,
     769             :     gtabset_FillsWindow,
     770             :     NULL
     771             : };
     772             : 
     773           0 : static int sendtoparent_eh(GWindow gw, GEvent *event) {
     774           0 :     switch ( event->type ) {
     775             :       case et_controlevent: case et_char: case et_drop:
     776           0 :         event->w = GDrawGetParentWindow(gw);
     777           0 :         GDrawPostEvent(event);
     778           0 :       break;
     779             :       case et_resize:
     780           0 :         GDrawRequestExpose(gw,NULL,false);
     781           0 :       break;
     782             :     }
     783             : 
     784           0 : return( true );
     785             : }
     786             : 
     787           0 : static int gtabset_vscroll(GGadget *g, GEvent *event) {
     788           0 :     enum sb sbt = event->u.control.u.sb.type;
     789           0 :     GTabSet *gts = (GTabSet *) (g->data);
     790           0 :     int loff = gts->offtop;
     791           0 :     int page = (g->inner.height-6)/gts->fh- ((g->inner.height-6)/gts->fh>2?1:0);
     792             : 
     793           0 :     if ( sbt==et_sb_top )
     794           0 :         loff = 0;
     795           0 :     else if ( sbt==et_sb_bottom ) {
     796           0 :         loff = gts->tabcnt - (gts->g.inner.height-6)/gts->fh;
     797           0 :     } else if ( sbt==et_sb_up ) {
     798           0 :         --loff;
     799           0 :     } else if ( sbt==et_sb_down ) {
     800           0 :         ++loff;
     801           0 :     } else if ( sbt==et_sb_uppage ) {
     802           0 :         loff -= page;
     803           0 :     } else if ( sbt==et_sb_downpage ) {
     804           0 :         loff += page;
     805             :     } else /* if ( sbt==et_sb_thumb || sbt==et_sb_thumbrelease ) */ {
     806           0 :         loff = event->u.control.u.sb.pos;
     807             :     }
     808           0 :     if ( loff + (gts->g.inner.height-6)/gts->fh > gts->tabcnt )
     809           0 :         loff = gts->tabcnt - (gts->g.inner.height-6)/gts->fh;
     810           0 :     if ( loff<0 )
     811           0 :         loff = 0;
     812           0 :     if ( loff!=gts->offtop ) {
     813           0 :         gts->offtop = loff;
     814           0 :         GScrollBarSetPos(gts->vsb, loff );
     815           0 :         GGadgetRedraw(&gts->g);
     816             :     }
     817           0 : return( true );
     818             : }
     819             : 
     820           0 : GGadget *GTabSetCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     821           0 :     GTabSet *gts = calloc(1,sizeof(GTabSet));
     822             :     int i, bp;
     823             :     GRect r;
     824             :     GWindowAttrs childattrs;
     825             : 
     826           0 :     memset(&childattrs,0,sizeof(childattrs));
     827           0 :     childattrs.mask = wam_events;
     828           0 :     childattrs.event_masks = -1;
     829             : 
     830           0 :     if ( !gtabset_inited )
     831           0 :         GTabSetInit();
     832           0 :     gts->g.funcs = &gtabset_funcs;
     833           0 :     _GGadget_Create(&gts->g,base,gd,data, gd->flags&gg_tabset_vert ? &gvtabset_box  : &gtabset_box);
     834           0 :     gts->font = gtabset_font;
     835             : 
     836           0 :     gts->g.takes_input = true; gts->g.takes_keyboard = true; gts->g.focusable = true;
     837             : 
     838           0 :     GDrawGetSize(base,&r);
     839           0 :     if ( gd->pos.x <= 0 )
     840           0 :         gts->g.r.x = GDrawPointsToPixels(base,2);
     841           0 :     if ( gd->pos.y <= 0 )
     842           0 :         gts->g.r.y = GDrawPointsToPixels(base,2);
     843           0 :     if ( gd->pos.width<=0 )
     844           0 :         gts->g.r.width = r.width - gts->g.r.x - GDrawPointsToPixels(base,2);
     845           0 :     if ( gd->pos.height<=0 ) {
     846           0 :         if ( gd->flags&gg_tabset_nowindow )
     847           0 :             gts->g.r.height = GDrawPointsToPixels(base,20);
     848             :         else
     849           0 :             gts->g.r.height = r.height - gts->g.r.y - GDrawPointsToPixels(base,26);
     850             :     }
     851             : 
     852           0 :     for ( i=0; gd->u.tabs[i].text!=NULL; ++i );
     853           0 :     gts->tabcnt = i;
     854           0 :     gts->tabs = malloc(i*sizeof(struct tabs));
     855           0 :     for ( i=0; gd->u.tabs[i].text!=NULL; ++i ) {
     856           0 :         if ( gd->u.tabs[i].text_in_resource )
     857           0 :             gts->tabs[i].name = u_copy(GStringGetResource((intpt) (gd->u.tabs[i].text),NULL));
     858           0 :         else if ( gd->u.tabs[i].text_is_1byte )
     859           0 :             gts->tabs[i].name = utf82u_copy((char *) (gd->u.tabs[i].text));
     860             :         else
     861           0 :             gts->tabs[i].name = u_copy(gd->u.tabs[i].text);
     862           0 :         gts->tabs[i].disabled = gd->u.tabs[i].disabled;
     863           0 :         gts->tabs[i].nesting = gd->u.tabs[i].nesting;
     864           0 :         if ( gd->u.tabs[i].selected && !gts->tabs[i].disabled )
     865           0 :             gts->sel = i;
     866             :     }
     867           0 :     if ( gd->flags&gg_tabset_scroll ) gts->scrolled = true;
     868           0 :     if ( gd->flags&gg_tabset_filllines ) gts->filllines = true;
     869           0 :     if ( gd->flags&gg_tabset_fill1line ) gts->fill1line = true;
     870           0 :     if ( gd->flags&gg_tabset_vert ) gts->vertical = true;
     871           0 :     gts->offset_per_row = GDrawPointsToPixels(base,2);
     872           0 :     if ( gts->vertical && gts->scrolled ) {
     873             :         GGadgetData gd;
     874           0 :         memset(&gd,'\0',sizeof(gd));
     875           0 :         gd.pos.y = gts->g.r.y; gd.pos.height = gts->g.inner.height;
     876           0 :         gd.pos.width = GDrawPointsToPixels(gts->g.base,_GScrollBar_Width);
     877           0 :         gd.pos.x = gts->g.inner.x;
     878           0 :         gd.flags = (gts->g.state==gs_invisible?0:gg_visible)|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
     879           0 :         gd.handle_controlevent = gtabset_vscroll;
     880           0 :         gts->vsb = GScrollBarCreate(gts->g.base,&gd,gts);
     881           0 :         gts->vsb->contained = true;
     882             :     }
     883           0 :     GTabSet_Remetric(gts);
     884           0 :     _GGadget_FinalPosition(&gts->g,base,gd);
     885             : 
     886           0 :     bp = GBoxBorderWidth(base,gts->g.box);
     887           0 :     gts->g.inner = gts->g.r;
     888           0 :     if ( gts->vertical ) {
     889           0 :         gts->g.inner.x += bp+gts->vert_list_width; gts->g.inner.width -= 2*bp+gts->vert_list_width;
     890           0 :         gts->g.inner.y += bp; gts->g.inner.height -= 2*bp;
     891             :     } else {
     892           0 :         gts->g.inner.x += bp; gts->g.inner.width -= 2*bp;
     893           0 :         gts->g.inner.y += gts->rcnt*gts->rowh+bp; gts->g.inner.height -= 2*bp+gts->rcnt*gts->rowh;
     894             :     }
     895           0 :     if ( gts->rcnt==1 ) {
     896           0 :         gts->g.inner.y += bp; gts->g.inner.height -= bp;
     897             :     }
     898           0 :     if ( gts->vsb!=NULL ) {
     899           0 :         GGadgetMove(gts->vsb, gts->g.r.x + bp + gts->vert_list_width - gts->vsb->r.width, gts->g.r.y + bp);
     900           0 :         GGadgetResize(gts->vsb, gts->vsb->r.width, gts->g.r.height-2*bp);
     901           0 :         if ( gts->g.inner.height>26 )
     902           0 :             GScrollBarSetBounds(gts->vsb,0,gts->tabcnt,(gts->g.r.height-2*bp-6)/gts->fh);
     903             :     }
     904             : 
     905           0 :     if ( gd->flags&gg_tabset_nowindow ) gts->nowindow = true;
     906             : 
     907           0 :     for ( i=0; gd->u.tabs[i].text!=NULL; ++i )
     908           0 :         if ( !(gd->flags&gg_tabset_nowindow)) {
     909           0 :             gts->tabs[i].w = GDrawCreateSubWindow(base,&gts->g.inner,sendtoparent_eh,GDrawGetUserData(base),&childattrs);
     910           0 :             if ( gd->u.tabs[i].gcd!=NULL )
     911           0 :                 GGadgetsCreate(gts->tabs[i].w,gd->u.tabs[i].gcd);
     912           0 :             if ( gts->sel==i && (gd->flags & gg_visible ))
     913           0 :                 GDrawSetVisible(gts->tabs[i].w,true);
     914             :         } else
     915           0 :             gts->tabs[i].w = NULL;
     916             : 
     917           0 :     if ( gd->flags & gg_group_end )
     918           0 :         _GGadgetCloseGroup(&gts->g);
     919             : 
     920           0 :     for ( i=0; gd->u.tabs[i].text!=NULL && !gd->u.tabs[i].selected; ++i );
     921           0 :     if ( i!=0 && gd->u.tabs[i].text!=NULL )
     922           0 :         GTabSetChangeSel(gts,i,false);
     923             : 
     924           0 : return( &gts->g );
     925             : }
     926             : 
     927           0 : int GTabSetGetSel(GGadget *g) {
     928           0 :     GTabSet *gts = (GTabSet *) g;
     929           0 : return( gts->sel );
     930             : }
     931             : 
     932           0 : void GTabSetSetSel(GGadget *g,int sel) {
     933           0 :     GTabSet *gts = (GTabSet *) g;
     934           0 :     GTabSetChangeSel(gts,sel,false);
     935           0 : }
     936             : 
     937           0 : void GTabSetSetEnabled(GGadget *g,int pos,int enabled) {
     938           0 :     GTabSet *gts = (GTabSet *) g;
     939             : 
     940           0 :     if ( pos>=0 && pos<gts->tabcnt ) {
     941           0 :         gts->tabs[pos].disabled = !enabled;
     942             :     }
     943           0 :     GDrawRequestExpose(g->base, &g->r, false);
     944           0 : }
     945             : 
     946           0 : GWindow GTabSetGetSubwindow(GGadget *g,int pos) {
     947           0 :     GTabSet *gts = (GTabSet *) g;
     948             : 
     949           0 :     if ( pos>=0 && pos<gts->tabcnt )
     950           0 : return( gts->tabs[pos].w );
     951             : 
     952           0 : return( NULL );
     953             : }
     954             : 
     955           0 : int GTabSetGetTabLines(GGadget *g) {
     956           0 :     GTabSet *gts = (GTabSet *) g;
     957           0 : return( gts->rcnt );
     958             : }
     959             : 
     960           0 : void GTabSetSetNestedExpose(GGadget *g, void (*ne)(GWindow,GGadget *,GEvent *)) {
     961           0 :     GTabSet *gts = (GTabSet *) g;
     962           0 :     gts->nested_expose = ne;
     963           0 : }
     964             : 
     965           0 : void GTabSetSetNestedMouse(GGadget *g, int (*nm)(GGadget *,GEvent *)) {
     966           0 :     GTabSet *gts = (GTabSet *) g;
     967           0 :     gts->nested_mouse = nm;
     968           0 : }
     969             : 
     970           0 : void GTabSetChangeTabName(GGadget *g, const char *name, int pos) {
     971           0 :     GTabSet *gts = (GTabSet *) g;
     972             : 
     973           0 :     if ( pos==gts->tabcnt && gts->nowindow ) {
     974           0 :         gts->tabs = realloc(gts->tabs,(pos+1)*sizeof(struct tabs));
     975           0 :         memset(&gts->tabs[pos],0,sizeof(struct tabs));
     976           0 :         ++gts->tabcnt;
     977             :     }
     978           0 :     if ( pos<gts->tabcnt ) {
     979           0 :         free(gts->tabs[pos].name);
     980           0 :         gts->tabs[pos].name = utf82u_copy(name);
     981             :     }
     982           0 : }
     983             : 
     984           0 : void GTabSetRemetric(GGadget *g) {
     985           0 :     GTabSet *gts = (GTabSet *) g;
     986           0 :     GTabSet_Remetric(gts);
     987           0 : }
     988             : 
     989           0 : void GTabSetRemoveTabByPos(GGadget *g, int pos) {
     990           0 :     GTabSet *gts = (GTabSet *) g;
     991             :     int i;
     992             : 
     993           0 :     if ( gts->nowindow && pos>=0 && pos<gts->tabcnt && gts->tabcnt>1 ) {
     994           0 :         free(gts->tabs[pos].name);
     995           0 :         for ( i=pos+1; i<gts->tabcnt; ++i )
     996           0 :             gts->tabs[i-1] = gts->tabs[i];
     997           0 :         --gts->tabcnt;
     998           0 :         if ( gts->sel==pos ) {
     999           0 :             if ( gts->sel==gts->tabcnt )
    1000           0 :                 --gts->sel;
    1001           0 :             GTabSetChanged(gts,pos);
    1002             :         }
    1003             :     }
    1004           0 : }
    1005             :         
    1006           0 : void GTabSetRemoveTabByName(GGadget *g, char *name) {
    1007           0 :     GTabSet *gts = (GTabSet *) g;
    1008             :     int pos;
    1009           0 :     unichar_t *uname = utf82u_copy(name);
    1010             : 
    1011           0 :     for ( pos=0; pos<gts->tabcnt; ++pos ) {
    1012           0 :         if ( u_strcmp(uname,gts->tabs[pos].name)==0 ) {
    1013           0 :             GTabSetRemoveTabByPos(g,pos);
    1014           0 :     break;
    1015             :         }
    1016             :     }
    1017             : 
    1018           0 :     free(uname);
    1019           0 : }
    1020             : 
    1021           0 : GResInfo *_GTabSetRIHead(void) {
    1022           0 :     if ( !gtabset_inited )
    1023           0 :         GTabSetInit();
    1024           0 : return( &gtabset_ri );
    1025             : }

Generated by: LCOV version 1.10