LCOV - code coverage report
Current view: top level - gdraw - gbuttons.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 604 0.0 %
Date: 2017-08-04 Functions: 0 42 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 <stdlib.h>
      28             : #include "gdraw.h"
      29             : #include "ggadgetP.h"
      30             : #include "ustring.h"
      31             : #include "gkeysym.h"
      32             : #include "gresource.h"
      33             : #include "gwidget.h"
      34             : 
      35             : static void GListButtonDoPopup(GListButton *);
      36             : 
      37             : GBox _GGadget_button_box = GBOX_EMPTY; /* Don't initialize here */
      38             : GBox _GGadget_defaultbutton_box = GBOX_EMPTY; /* Don't initialize here */
      39             : static GBox _GGadget_cancelbutton_box = GBOX_EMPTY; /* Don't initialize here */
      40             : static GBox _GGadget_colorbutton_box = GBOX_EMPTY; /* Don't initialize here */
      41             : static GBox _GGadget_droplist_box = GBOX_EMPTY; /* Don't initialize here */
      42             : static GBox label_box = GBOX_EMPTY; /* Don't initialize here */
      43             : static int shift_on_press = 0;
      44             : static FontInstance *label_font = NULL, *button_font = NULL;
      45             : static int gbutton_inited = false;
      46             : #define COLOR_BUTTON_BOX_LEN    10
      47             : 
      48             : static GResInfo gcancel_ri, gdefault_ri, gbutton_ri, gdroplist_ri, gcolor_ri;
      49             : static GResInfo glabel_ri = {
      50             :     &gbutton_ri, &ggadget_ri,NULL, NULL,
      51             :     &label_box,
      52             :     &label_font,
      53             :     NULL,
      54             :     NULL,
      55             :     N_("Label"),
      56             :     N_("Text Labels"),
      57             :     "GLabel",
      58             :     "Gdraw",
      59             :     false,
      60             :     omf_border_type|omf_border_width|omf_padding,
      61             :     NULL,
      62             :     GBOX_EMPTY,
      63             :     NULL,
      64             :     NULL,
      65             :     NULL
      66             : };
      67             : 
      68             : static GTextInfo button_lab[] = {
      69             :     { (unichar_t *) "Disabled Button", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
      70             :     { (unichar_t *) "Enabled Button" , NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' }
      71             : };
      72             : static GGadgetCreateData button_gcd[] = {
      73             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible, NULL, NULL }, NULL, NULL },
      74             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
      75             : };
      76             : static GGadgetCreateData *barray[] = { GCD_Glue, &button_gcd[0], GCD_Glue, &button_gcd[1], GCD_Glue, NULL, NULL };
      77             : static GGadgetCreateData buttonbox =
      78             :         {GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) barray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
      79             : static struct resed gbutton_re[] = {
      80             :     { N_("Shift On Press"), "ShiftOnPress", rt_bool, &shift_on_press, N_("Background color of column headers at the top of a matrix edit"), NULL, { 0 }, 0, 0 },
      81             :     RESED_EMPTY
      82             : };
      83             : static GResInfo gbutton_ri = {
      84             :     &gdefault_ri, &ggadget_ri,&gdefault_ri, &gcancel_ri,
      85             :     &_GGadget_button_box,
      86             :     &button_font,
      87             :     &buttonbox,
      88             :     gbutton_re,
      89             :     N_("Button"),
      90             :     N_("Buttons"),
      91             :     "GButton",
      92             :     "Gdraw",
      93             :     true,
      94             : #ifdef __Mac
      95             :     box_do_depressed_background|omf_border_type|omf_border_width|
      96             :             omf_border_shape|omf_padding,
      97             : #else
      98             :     box_foreground_border_inner|box_foreground_border_outer|
      99             :         /*box_active_border_inner|*/box_do_depressed_background|box_draw_default,
     100             : #endif
     101             :     /* Will be initialized later */
     102             :     NULL,
     103             :     GBOX_EMPTY,
     104             :     NULL,
     105             :     NULL,
     106             :     NULL
     107             : };
     108             : static GGadgetCreateData def_gcd[] = {
     109             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible|gg_but_default, NULL, NULL }, NULL, NULL },
     110             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled|gg_but_default, NULL, NULL }, NULL, NULL }
     111             : };
     112             : static GGadgetCreateData *darray[] = { GCD_Glue, &def_gcd[0], GCD_Glue, &def_gcd[1], GCD_Glue, NULL, NULL };
     113             : static GGadgetCreateData defbox =
     114             :         { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) darray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
     115             : static GResInfo gdefault_ri = {
     116             :     &gcancel_ri, &gbutton_ri,&gcancel_ri,NULL,
     117             :     &_GGadget_defaultbutton_box,
     118             :     NULL,
     119             :     &defbox,
     120             :     NULL,
     121             :     N_("Default Button"),
     122             :     N_("Default Buttons"),
     123             :     "GDefaultButton",
     124             :     "Gdraw",
     125             :     true,
     126             : #ifdef __Mac
     127             :     box_gradient_bg|omf_main_background|omf_gradient_bg_end,
     128             : #else
     129             :     0,
     130             : #endif
     131             :     NULL,
     132             :     GBOX_EMPTY,
     133             :     NULL,
     134             :     NULL,
     135             :     NULL
     136             : };
     137             : static GGadgetCreateData cancel_gcd[] = {
     138             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible|gg_but_cancel, NULL, NULL }, NULL, NULL },
     139             :     { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled|gg_but_cancel, NULL, NULL }, NULL, NULL }
     140             : };
     141             : static GGadgetCreateData *carray[] = { GCD_Glue, &cancel_gcd[0], GCD_Glue, &cancel_gcd[1], GCD_Glue, NULL, NULL };
     142             : static GGadgetCreateData cancelbox =
     143             :     {GHVGroupCreate, { {2, 2, 0, 0}, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) carray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
     144             : static GResInfo gcancel_ri = {
     145             :     &gcolor_ri, &gbutton_ri,&gdefault_ri,NULL,
     146             :     &_GGadget_cancelbutton_box,
     147             :     NULL,
     148             :     &cancelbox,
     149             :     NULL,
     150             :     N_("Cancel Button"),
     151             :     N_("Cancel Buttons"),
     152             :     "GCancelButton",
     153             :     "Gdraw",
     154             :     true,
     155             : #ifdef __Mac
     156             :     box_gradient_bg|omf_main_background|omf_gradient_bg_end,
     157             : #else
     158             :     0,
     159             : #endif
     160             :     NULL,
     161             :     GBOX_EMPTY,
     162             :     NULL,
     163             :     NULL,
     164             :     NULL
     165             : };
     166             : static GGadgetCreateData color_gcd[] = {
     167             :     { GColorButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) (intpt) (0x000000) }, gg_visible, NULL, NULL }, NULL, NULL },
     168             :     { GColorButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) (intpt) (0x000000) }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
     169             : };
     170             : static GGadgetCreateData *colarray[] = { GCD_Glue, &color_gcd[0], GCD_Glue, &color_gcd[1], GCD_Glue, NULL, NULL };
     171             : static GGadgetCreateData colorbox =
     172             :     { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) colarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
     173             : static GResInfo gcolor_ri = {
     174             :     &gdroplist_ri, &gbutton_ri,NULL,NULL,
     175             :     &_GGadget_colorbutton_box,
     176             :     NULL,
     177             :     &colorbox,
     178             :     NULL,
     179             :     N_("Color Button"),
     180             :     N_("Color Button"),
     181             :     "GColorButton",
     182             :     "Gdraw",
     183             :     true,
     184             :     0,
     185             :     NULL,
     186             :     GBOX_EMPTY,
     187             :     NULL,
     188             :     NULL,
     189             :     NULL
     190             : };
     191             : static GTextInfo list_choices[] = {
     192             :     { (unichar_t *) "1", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
     193             :     { (unichar_t *) "2", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
     194             :     { (unichar_t *) "3", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
     195             :     GTEXTINFO_EMPTY
     196             : };
     197             : 
     198             : static GGadgetCreateData droplist_gcd[] = {
     199             :     { GListButtonCreate, { { 0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[0], { list_choices }, gg_visible, NULL, NULL }, NULL, NULL },
     200             :     { GListButtonCreate, { { 0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[1], { list_choices }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
     201             : };
     202             : static GGadgetCreateData *dlarray[] = { GCD_Glue, &droplist_gcd[0], GCD_Glue, &droplist_gcd[1], GCD_Glue, NULL, NULL };
     203             : static GGadgetCreateData droplistbox =
     204             :     { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) dlarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
     205             : static GResInfo gdroplist_ri = {
     206             :     NULL, &gbutton_ri,&listmark_ri,NULL,
     207             :     &_GGadget_droplist_box,
     208             :     NULL,
     209             :     &droplistbox,
     210             :     NULL,
     211             :     N_("Drop List Button"),
     212             :     N_("Drop List Button"),
     213             :     "GDropList",
     214             :     "Gdraw",
     215             :     true,
     216             : #ifdef __Mac
     217             :     omf_border_type|omf_border_width|omf_border_shape,
     218             : #else
     219             :     0,
     220             : #endif
     221             :     NULL,
     222             :     GBOX_EMPTY,
     223             :     NULL,
     224             :     NULL,
     225             :     NULL
     226             : };
     227             : 
     228           0 : static void GButtonInvoked(GButton *b,GEvent *ev) {
     229             :     GEvent e;
     230             : 
     231           0 :     if ( b->labeltype==3 ) {
     232             :         struct hslrgba hsl;
     233           0 :         gColor2Hslrgba(&hsl,((GColorButton *) b)->col);
     234           0 :         hsl = GWidgetColorA(_("Pick a color"),&hsl,NULL);
     235           0 :         if ( hsl.rgb ) {
     236           0 :             ((GColorButton *) b)->col = gHslrgba2Color(&hsl);
     237           0 :             GGadgetRedraw(&b->g);
     238             :         } else
     239           0 : return;
     240             :     }
     241           0 :     e.type = et_controlevent;
     242           0 :     e.w = b->g.base;
     243           0 :     e.u.control.subtype = et_buttonactivate;
     244           0 :     e.u.control.g = &b->g;
     245           0 :     if ( ev!=NULL && ev->type==et_mouseup ) {
     246           0 :         e.u.control.u.button.clicks = ev->u.mouse.clicks;
     247           0 :         e.u.control.u.button.button = ev->u.mouse.button;
     248           0 :         e.u.control.u.button.state = ev->u.mouse.state;
     249             :     } else {
     250           0 :         e.u.control.u.button.clicks = 0;
     251           0 :         e.u.control.u.button.button = 0;
     252           0 :         e.u.control.u.button.state = 0;
     253             :     }
     254           0 :     if ( b->g.handle_controlevent != NULL )
     255           0 :         (b->g.handle_controlevent)(&b->g,&e);
     256             :     else
     257           0 :         GDrawPostEvent(&e);
     258             : }
     259             : 
     260           0 : static void GButtonPressed(GButton *b) {
     261             :     GEvent e;
     262             : 
     263           0 :     if ( b->labeltype==2 && ((GListButton *) b)->ltot>0 )
     264           0 :         GListButtonDoPopup((GListButton *) b);
     265             :     else {
     266           0 :         e.type = et_controlevent;
     267           0 :         e.w = b->g.base;
     268           0 :         e.u.control.subtype = et_buttonpress;
     269           0 :         e.u.control.g = &b->g;
     270           0 :         if ( b->g.handle_controlevent != NULL )
     271           0 :             (b->g.handle_controlevent)(&b->g,&e);
     272             :         else
     273           0 :             GDrawPostEvent(&e);
     274             :     }
     275           0 : }
     276             : 
     277           0 : static int gbutton_stringsize( GButton *gb,unichar_t *label,int *lcnt ) {
     278           0 :     int maxtextwidth = 0;
     279             :     unichar_t *pt, *start;
     280             : 
     281           0 :     for ( pt = label; ; ) {
     282           0 :         for ( start=pt; *pt!='\0' && *pt!='\n'; ++pt );
     283           0 :         if ( pt!=start ) {
     284           0 :             int w = GDrawGetTextWidth(gb->g.base,start,pt-start);
     285           0 :             if ( w>maxtextwidth ) maxtextwidth=w;
     286             :         }
     287           0 :         ++(*lcnt);
     288           0 :         if ( *pt=='\0' )
     289           0 :     break;
     290           0 :         ++pt;
     291           0 :     }
     292           0 : return maxtextwidth;
     293             : }
     294             : 
     295           0 : static unichar_t *gbutton_textsize( GButton *gb, int *_maxlcnt, int *_maxw ) {
     296             :     int i, lcnt, maxlcnt, maxtextwidth;
     297             :     unichar_t *ltxt;
     298             :     GFont *old;
     299             : 
     300           0 :     old = GDrawSetFont(gb->g.base,gb->font);
     301             : 
     302           0 :     maxtextwidth = maxlcnt = 0;
     303           0 :     if ( gb->label!=NULL ) {
     304           0 :         maxtextwidth = gbutton_stringsize( gb,gb->label,&maxlcnt );
     305           0 :         ltxt = gb->label;
     306             :     }
     307             :     /* If there is a list of alternate labels, iterate through all */
     308             :     /* and get the maximum width and height */
     309           0 :     if ( gb->labeltype == 0 && gb->ti!=NULL ) {
     310           0 :         for ( i=0; i<gb->ltot; i++ ) {
     311           0 :             lcnt = 0;
     312           0 :             int w = gbutton_stringsize( gb,gb->ti[i]->text,&lcnt );
     313           0 :             if ( w>maxtextwidth ) {
     314           0 :                 maxtextwidth=w;
     315           0 :                 ltxt = gb->ti[i]->text;
     316             :             }
     317           0 :             if ( lcnt>maxlcnt ) maxlcnt=lcnt;
     318             :         }
     319             :     }
     320           0 :     (void) GDrawSetFont(gb->g.base,old);
     321           0 :     *_maxlcnt = maxlcnt;
     322           0 :     *_maxw = maxtextwidth;
     323           0 : return( ltxt );
     324             : }
     325             : 
     326           0 : static int gbutton_expose(GWindow pixmap, GGadget *g, GEvent *event) {
     327           0 :     GImageButton *gb = (GImageButton *) g;
     328           0 :     int off = gb->within && gb->shiftonpress ? gb->pressed : 0;
     329           0 :     int x = g->inner.x + off;
     330           0 :     GImage *img = gb->image;
     331             :     GRect old1, old2;
     332             :     int width;
     333           0 :     int marklen = GDrawPointsToPixels(pixmap,_GListMarkSize),
     334           0 :             spacing = GDrawPointsToPixels(pixmap,_GGadget_TextImageSkip);
     335             :     int yoff;
     336             :     GRect unpadded_inner;
     337             :     int pad, lcnt, maxtextwidth;
     338             :     unichar_t *pt, *start;
     339           0 :     int cbbl=0;
     340             : 
     341           0 :     if ( g->state == gs_invisible )
     342           0 : return( false );
     343           0 :     else if ( gb->labeltype!=1 /* Not image buttons */ )
     344             :         /* Do Nothing */;
     345           0 :     else if ( g->state == gs_disabled ) {
     346           0 :         if ( gb->disabled != NULL ) img = gb->disabled;
     347           0 :     } else if ( gb->pressed && gb->within && gb->active!=NULL )
     348           0 :         img = gb->active;
     349           0 :     else if ( gb->within )
     350           0 :         img = gb->img_within;
     351             : 
     352           0 :     GDrawPushClip(pixmap,&g->r,&old1);
     353             : 
     354           0 :     GBoxDrawBackground(pixmap,&g->r,g->box,
     355           0 :             gb->within && gb->pressed? gs_pressedactive: g->state,gb->is_default);
     356           0 :     if ( g->box->border_type!=bt_none ||
     357           0 :             (g->box->flags&(box_foreground_border_inner|box_foreground_border_outer|box_active_border_inner))!=0 ) {
     358           0 :         GBoxDrawBorder(pixmap,&g->r,g->box,g->state,gb->is_default);
     359             : 
     360           0 :         unpadded_inner = g->inner;
     361           0 :         pad = GDrawPointsToPixels(g->base,g->box->padding);
     362           0 :         unpadded_inner.x -= pad; unpadded_inner.y -= pad;
     363           0 :         unpadded_inner.width += 2*pad; unpadded_inner.height += 2*pad;
     364           0 :         GDrawPushClip(pixmap,&unpadded_inner,&old2);
     365             :     }
     366           0 :     if ( gb->font!=NULL )
     367           0 :         GDrawSetFont(pixmap,gb->font);
     368             : 
     369           0 :     gbutton_textsize((GButton *) gb,&lcnt,&maxtextwidth);
     370           0 :     yoff = (g->inner.height-lcnt*gb->fh)/2;
     371           0 :     if ( lcnt>1 && yoff<0 )
     372           0 :         yoff = 0;
     373             : 
     374           0 :     if ( gb->g.takes_input ) {
     375           0 :         width = 0;
     376           0 :         if ( img!=NULL ) {
     377           0 :             width = GImageGetScaledWidth(pixmap,img);
     378           0 :             if ( gb->label!=NULL )
     379           0 :                 width += spacing;
     380             :         }
     381           0 :         if ( gb->label!=NULL )
     382           0 :             width += maxtextwidth;
     383           0 :         if ( gb->labeltype==3 ) {
     384           0 :             cbbl = GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN);
     385           0 :             width += cbbl + spacing;
     386             :         }
     387           0 :         if ( width<=g->inner.width )
     388           0 :             x += ( g->inner.width-width )/2;
     389             :         else
     390           0 :             x += (g->inner.y-g->r.y);
     391             :     }
     392           0 :     if ( gb->labeltype==3 ) {
     393             :         GRect r;
     394           0 :         Color fg = g->state==gs_disabled?g->box->disabled_foreground:
     395           0 :                         g->box->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)):
     396           0 :                         g->box->main_foreground;
     397           0 :         r.x = x+1; r.y = g->inner.y+1;
     398           0 :         r.width = cbbl-2;
     399           0 :         if ( img!=NULL )
     400           0 :             r.height = GImageGetScaledHeight(pixmap,img)-2;
     401             :         else
     402           0 :             r.height = gb->fh-2;
     403           0 :         if ( ((GColorButton *) gb)->col!=COLOR_TRANSPARENT )
     404           0 :             GDrawFillRect(pixmap,&r,((GColorButton *) gb)->col);
     405           0 :         GDrawDrawRect(pixmap,&r,fg);
     406           0 :         x += cbbl + spacing;
     407             :     }
     408           0 :     if ( gb->image_precedes && img!=NULL ) {
     409           0 :         GDrawDrawScaledImage(pixmap,img,x,g->inner.y + off);
     410           0 :         x += GImageGetScaledWidth(pixmap,img) + spacing;
     411             :     }
     412           0 :     if ( gb->label!=NULL ) {
     413           0 :         Color fg = g->state==gs_disabled?g->box->disabled_foreground:
     414           0 :                         g->box->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)):
     415           0 :                         g->box->main_foreground;
     416           0 :         if ( lcnt==1 ) {
     417           0 :             _ggadget_underlineMnemonic(pixmap,x,g->inner.y + gb->as + yoff + off,gb->label,
     418           0 :                     g->mnemonic,fg,g->inner.y+g->inner.height);
     419           0 :             x += GDrawDrawText(pixmap,x,g->inner.y + gb->as + yoff + off,gb->label,-1,fg);
     420             :         } else {
     421           0 :             int y = g->inner.y + gb->as + yoff + off;
     422           0 :             for ( pt = gb->label; ; ) {
     423           0 :                 for ( start=pt; *pt!='\0' && *pt!='\n'; ++pt );
     424           0 :                 if ( pt!=start )
     425           0 :                     GDrawDrawText(pixmap,x,y,start,pt-start,fg);
     426           0 :                 if ( *pt=='\0' )
     427           0 :             break;
     428           0 :                 ++pt;
     429           0 :                 y+=gb->fh;
     430           0 :             }
     431           0 :             x += maxtextwidth;
     432             :         }
     433           0 :         x += spacing;
     434             :     }
     435           0 :     if ( !gb->image_precedes && img!=NULL )
     436           0 :         GDrawDrawScaledImage(pixmap,img,x,g->inner.y + off);
     437             : 
     438           0 :     if ( g->box->border_type!=bt_none ||
     439           0 :             (g->box->flags&(box_foreground_border_inner|box_foreground_border_outer|box_active_border_inner))!=0 )
     440           0 :         GDrawPopClip(pixmap,&old2);
     441             : 
     442           0 :     if ( gb->labeltype==2 ) {
     443           0 :         int bp = GBoxBorderWidth(g->base,g->box);
     444           0 : GListMarkDraw(pixmap,
     445           0 :                 g->r.x + g->r.width - marklen - spacing/2 - bp,
     446             :                 g->inner.y,
     447             :                 g->inner.height,
     448             :                 g->state);
     449             :     }
     450             : 
     451           0 :     GDrawPopClip(pixmap,&old1);
     452           0 : return( true );
     453             : }
     454             : 
     455           0 : static int gbutton_mouse(GGadget *g, GEvent *event) {
     456           0 :     GLabel *gb = (GLabel *) g;
     457           0 :     int within = gb->within, pressed = gb->pressed;
     458             :     int was_state;
     459             : 
     460           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused )) {
     461           0 :         if ( !g->takes_input && event->type == et_mousemove && !gb->pressed &&
     462           0 :                 g->popup_msg )
     463           0 :             GGadgetPreparePopup(g->base,g->popup_msg);
     464           0 : return( false );
     465             :     }
     466             : 
     467           0 :     if ( gb->labeltype==2 && event->type==et_mousedown &&
     468           0 :             ((GListButton *) gb)->popup!=NULL ) {
     469           0 :         GDrawDestroyWindow(((GListButton *) gb)->popup);
     470           0 :         ((GListButton *) gb)->popup = NULL;
     471           0 : return( true );
     472             :     }
     473           0 :     was_state = g->state;
     474           0 :     if ( event->type == et_crossing ) {
     475           0 :         if ( gb->within && !event->u.crossing.entered )
     476           0 :             gb->within = false;
     477           0 :         if ( gb->pressed && (event->u.crossing.state&ksm_buttons)==0 )
     478           0 :             gb->pressed = false;
     479           0 :     } else if ( gb->pressed && event->type==et_mouseup ) {
     480           0 :         if ( GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
     481           0 :             if ( event->type == et_mouseup ) {
     482           0 :                 gb->pressed = false;
     483           0 :                 GButtonInvoked(gb,event);
     484             :             } else
     485           0 :                 gb->within = false;
     486             :         } else
     487           0 :             gb->pressed = false;
     488           0 :     } else if ( event->type == et_mousedown &&
     489           0 :             GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
     490           0 :         gb->pressed = true;
     491           0 :         gb->within = true;
     492           0 :         GButtonPressed(gb);
     493           0 :     } else if ( event->type == et_mousemove &&
     494           0 :             GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
     495           0 :         gb->within = true;
     496           0 :         if ( !gb->pressed && g->popup_msg )
     497           0 :             GGadgetPreparePopup(g->base,g->popup_msg);
     498           0 :     } else if ( event->type == et_mousemove && gb->within ) {
     499           0 :         gb->within = false;
     500             :     } else {
     501           0 : return( false );
     502             :     }
     503           0 :     if ( within != gb->within && was_state==g->state )
     504           0 :         g->state = gb->within? gs_active : gs_enabled;
     505           0 :     if ( within != gb->within || pressed != gb->pressed )
     506           0 :         _ggadget_redraw(g);
     507           0 : return( event->type==et_mousedown || event->type==et_mouseup || gb->within );
     508             : }
     509             : 
     510           0 : static int gbutton_key(GGadget *g, GEvent *event) {
     511           0 :     GLabel *gb = (GLabel *) g;
     512             : 
     513           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active ))
     514           0 : return(false);
     515           0 :     if ( gb->labeltype==2 && ((GListButton *) gb)->popup!=NULL ) {
     516           0 :         GWindow popup = ((GListButton *) gb)->popup;
     517           0 :         (GDrawGetEH(popup))(popup,event);
     518           0 : return( true );
     519             :     }
     520             : 
     521           0 :     if ( event->u.chr.chars[0]==' ' ) {
     522           0 :         GButtonInvoked(gb,NULL);
     523           0 : return( true );
     524             :     }
     525           0 : return(false);
     526             : }
     527             : 
     528           0 : static int gbutton_focus(GGadget *g, GEvent *event) {
     529           0 :     GLabel *gb = (GLabel *) g;
     530             : 
     531           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active ))
     532           0 : return(false);
     533             : 
     534           0 :     if ( event->u.focus.mnemonic_focus==mf_shortcut ||
     535           0 :             event->u.focus.mnemonic_focus==mf_mnemonic ) {
     536           0 :         GButtonInvoked(gb,NULL);
     537           0 : return( true );
     538             :     }
     539           0 : return( true );
     540             : }
     541             : 
     542           0 : static void gbutton_destroy(GGadget *g) {
     543           0 :     GButton *b = (GButton *) g;
     544             : 
     545           0 :     if ( b==NULL )
     546           0 : return;
     547           0 :     if ( b->labeltype==2 ) {
     548           0 :         GListButton *glb = (GListButton *) g;
     549           0 :         if ( glb->popup ) {
     550           0 :             GDrawDestroyWindow(glb->popup);
     551           0 :             GDrawSync(NULL);
     552           0 :             GDrawProcessWindowEvents(glb->popup);    /* popup's destroy routine must execute before we die */
     553             :         }
     554           0 :         GTextInfoArrayFree(glb->ti);
     555             :     }
     556           0 :     free(b->label);
     557           0 :     _ggadget_destroy(g);
     558             : }
     559             : 
     560             : static int GButtonGetDesiredWidth(GLabel *gl);
     561           0 : static void GButtonSetInner(GButton *b) {
     562           0 :     int width, mark = 0;
     563           0 :     int bp = GBoxBorderWidth(b->g.base,b->g.box);
     564             : 
     565           0 :     if ( b->labeltype==2 )
     566           0 :         mark = GDrawPointsToPixels(b->g.base,_GListMarkSize) +
     567           0 :                 GDrawPointsToPixels(b->g.base,_GGadget_TextImageSkip);
     568           0 :     width = GButtonGetDesiredWidth(b);
     569           0 :     if ( width<=b->g.r.width-2*bp-mark )
     570           0 :         b->g.inner.width = width;
     571             :     else
     572           0 :         b->g.inner.width = b->g.r.width-2*bp;
     573           0 :     if ( !b->g.takes_input )
     574           0 :         b->g.inner.x = b->g.r.x + bp;
     575             :     else
     576           0 :         b->g.inner.x = b->g.r.x + (b->g.r.width-b->g.inner.width-mark)/2;
     577           0 : }
     578             : 
     579           0 : static void GButtonSetTitle(GGadget *g,const unichar_t *tit) {
     580           0 :     GButton *b = (GButton *) g;
     581             : 
     582           0 :     if ( b->g.free_box )
     583           0 :         free( b->g.box );
     584           0 :     free(b->label);
     585           0 :     b->label = u_copy(tit);
     586           0 :     GButtonSetInner(b);
     587           0 :     _ggadget_redraw(g);
     588           0 : }
     589             : 
     590           0 : static void GButtonSetImageTitle(GGadget *g,GImage *img,const unichar_t *tit, int before) {
     591           0 :     GButton *b = (GButton *) g;
     592             : 
     593           0 :     if ( b->g.free_box )
     594           0 :         free( b->g.box );
     595           0 :     free(b->label);
     596           0 :     b->label = u_copy(tit);
     597           0 :     b->image = img;
     598           0 :     b->image_precedes = before;
     599             : 
     600           0 :     GButtonSetInner(b);
     601             : 
     602           0 :     _ggadget_redraw(g);
     603           0 : }
     604             : 
     605           0 : static const unichar_t *_GButtonGetTitle(GGadget *g) {
     606           0 :     GButton *b = (GButton *) g;
     607           0 : return( b->label );
     608             : }
     609             : 
     610           0 : static GImage *GButtonGetImage(GGadget *g) {
     611           0 :     GButton *b = (GButton *) g;
     612           0 : return( b->image );
     613             : }
     614             : 
     615           0 : static void GButtonSetFont(GGadget *g,FontInstance *new) {
     616           0 :     GButton *b = (GButton *) g;
     617           0 :     b->font = new;
     618           0 : }
     619             : 
     620           0 : static FontInstance *GButtonGetFont(GGadget *g) {
     621           0 :     GButton *b = (GButton *) g;
     622           0 : return( b->font );
     623             : }
     624             : 
     625           0 : static void GListBSelectOne(GGadget *g, int32 pos) {
     626           0 :     GListButton *gl = (GListButton *) g;
     627             :     int i;
     628             : 
     629           0 :     for ( i=0; i<gl->ltot; ++i )
     630           0 :         gl->ti[i]->selected = false;
     631           0 :     if ( pos>=gl->ltot ) pos = gl->ltot-1;
     632           0 :     if ( pos<0 ) pos = 0;
     633           0 :     if ( gl->ltot>0 ) {
     634           0 :         gl->ti[pos]->selected = true;
     635           0 :         GButtonSetImageTitle(g,gl->ti[pos]->image,gl->ti[pos]->text,gl->ti[pos]->image_precedes);
     636             :     }
     637           0 : }
     638             : 
     639           0 : static int32 GListBIsSelected(GGadget *g, int32 pos) {
     640           0 :     GListButton *gl = (GListButton *) g;
     641             : 
     642           0 :     if ( pos>=gl->ltot )
     643           0 : return( false );
     644           0 :     if ( pos<0 )
     645           0 : return( false );
     646           0 :     if ( gl->ltot>0 )
     647           0 : return( gl->ti[pos]->selected );
     648             : 
     649           0 : return( false );
     650             : }
     651             : 
     652           0 : static int32 GListBGetFirst(GGadget *g) {
     653             :     int i;
     654           0 :     GListButton *gl = (GListButton *) g;
     655             : 
     656           0 :     for ( i=0; i<gl->ltot; ++i )
     657           0 :         if ( gl->ti[i]->selected )
     658           0 : return( i );
     659             : 
     660           0 : return( -1 );
     661             : }
     662             : 
     663           0 : static GTextInfo **GListBGet(GGadget *g,int32 *len) {
     664           0 :     GListButton *gl = (GListButton *) g;
     665           0 :     if ( len!=NULL ) *len = gl->ltot;
     666           0 : return( gl->ti );
     667             : }
     668             : 
     669           0 : static GTextInfo *GListBGetItem(GGadget *g,int32 pos) {
     670           0 :     GListButton *gl = (GListButton *) g;
     671           0 :     if ( pos<0 || pos>=gl->ltot )
     672           0 : return( NULL );
     673             : 
     674           0 : return(gl->ti[pos]);
     675             : }
     676             : 
     677           0 : static void GListButSet(GGadget *g,GTextInfo **ti,int32 docopy) {
     678           0 :     GListButton *gl = (GListButton *) g;
     679             :     int i;
     680             : 
     681           0 :     GTextInfoArrayFree(gl->ti);
     682           0 :     if ( docopy || ti==NULL )
     683           0 :         ti = GTextInfoArrayCopy(ti);
     684           0 :     gl->ti = ti;
     685           0 :     gl->ltot = GTextInfoArrayCount(ti);
     686           0 :     for ( i=0; ti[i]->text!=NULL || ti[i]->line; ++i ) {
     687           0 :         if ( ti[i]->selected && ti[i]->text!=NULL ) {
     688           0 :             GGadgetSetTitle(g,ti[i]->text);
     689           0 :     break;
     690             :         }
     691             :     }
     692           0 : }
     693             : 
     694           0 : static void GListButClear(GGadget *g) {
     695           0 :     GListButSet(g,NULL,true);
     696           0 : }
     697             : 
     698           0 : static int GButtonIsDefault(GGadget *g) {
     699           0 :     GLabel *gl = (GLabel *) g;
     700           0 : return( gl->is_default );
     701             : }
     702             : 
     703           0 : static int GButtonGetDesiredWidth(GLabel *gl) {
     704           0 :     int iwidth=0, width=0;
     705           0 :     if ( gl->image!=NULL ) {
     706           0 :         iwidth = GImageGetScaledWidth(gl->g.base,gl->image);
     707             :     }
     708           0 :     if ( gl->label!=NULL ) {
     709             :         int lcnt;
     710           0 :         gbutton_textsize(gl,&lcnt,&width);
     711             :     }
     712             : 
     713           0 :     if ( width!=0 && iwidth!=0 )
     714           0 :         width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
     715           0 :     width += iwidth;
     716             : 
     717           0 :     if ( gl->labeltype==3 )
     718           0 :         width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
     719           0 :                 GDrawPointsToPixels(gl->g.base,COLOR_BUTTON_BOX_LEN);
     720           0 : return( width );
     721             : }
     722             : 
     723           0 : static void GButtonGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
     724           0 :     GLabel *gl = (GLabel *) g;
     725           0 :     int iwidth=0, iheight=0;
     726             :     GTextBounds bounds;
     727           0 :     int as=0, ds, ld, fh=0, width=0;
     728             :     GRect needed;
     729             :     int i;
     730           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     731             : 
     732           0 :     if ( gl->image!=NULL ) {
     733           0 :         iwidth = GImageGetScaledWidth(gl->g.base,gl->image);
     734           0 :         iheight = GImageGetScaledHeight(gl->g.base,gl->image);
     735             :     }
     736           0 :     GDrawWindowFontMetrics(g->base,gl->font,&as, &ds, &ld);
     737           0 :     if ( gl->label!=NULL ) {
     738             :         int lcnt;
     739           0 :         unichar_t *ltxt = NULL;
     740           0 :         ltxt = gbutton_textsize(gl,&lcnt,&width);
     741           0 :         if ( lcnt==1 ) {
     742           0 :             FontInstance *old = GDrawSetFont(gl->g.base,gl->font);
     743           0 :             width = GDrawGetTextBounds(gl->g.base,ltxt, -1, &bounds);
     744           0 :             GDrawSetFont(gl->g.base,old);
     745           0 :             if ( as<bounds.as ) as = bounds.as;
     746           0 :             if ( ds<bounds.ds ) ds = bounds.ds;
     747           0 :             fh = as+ds;
     748             :         } else
     749           0 :             fh = gl->fh*lcnt;
     750             :     } else
     751           0 :         fh = as+ds;
     752             : 
     753           0 :     if ( gl->labeltype==3 ) {
     754           0 :         if ( width!=0 )
     755           0 :             width += GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN) +
     756           0 :                     GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
     757             :         else
     758           0 :             width = GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN);
     759             :     }
     760             : 
     761           0 :     if ( width!=0 && iwidth!=0 )
     762           0 :         width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
     763           0 :     width += iwidth;
     764           0 :     if ( iheight<fh )
     765           0 :         iheight = fh;
     766             : 
     767           0 :     if ( gl->labeltype==2 ) {
     768           0 :         GListButton *glb = (GListButton *) gl;
     769             :         int temp;
     770           0 :         int extra = GDrawPointsToPixels(gl->g.base,_GListMarkSize) +
     771           0 :                     2*GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
     772           0 :                     GBoxBorderWidth(gl->g.base,&_GListMark_Box);
     773           0 :         for ( i=0; i<glb->ltot; ++i ) {
     774           0 :             temp = GTextInfoGetWidth(gl->g.base,glb->ti[i],gl->font) + extra;
     775           0 :             if ( temp>width ) width = temp;
     776           0 :             temp = GTextInfoGetHeight(gl->g.base,glb->ti[i],gl->font);
     777           0 :             if ( temp>iheight )
     778           0 :                 iheight = temp;
     779             :         }
     780           0 :         width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
     781           0 :                 GDrawPointsToPixels(gl->g.base,_GListMarkSize);
     782             :     }
     783             : 
     784           0 :     if ( gl->shiftonpress ) {
     785           0 :         ++width; ++iheight;             /* one pixel for movement when button is pushed */
     786             :     }
     787             : 
     788           0 :     width += gl->g.takes_input?2*GDrawPointsToPixels(gl->g.base,2):0;
     789           0 :     needed.x = needed.y = 0;
     790           0 :     needed.width = width;
     791           0 :     needed.height = iheight;
     792           0 :     if ( g->desired_width>2*bp )
     793           0 :         needed.width = g->desired_width-2*bp;
     794           0 :     if ( g->desired_height>2*bp )
     795           0 :         needed.height = g->desired_height-2*bp;
     796           0 :     if ( inner!=NULL ) {
     797           0 :         inner->x = inner->y = 0;
     798           0 :         inner->width = width;
     799           0 :         inner->height = iheight;
     800             :     }
     801             : 
     802           0 :     _ggadgetFigureSize(gl->g.base,gl->g.box,&needed,gl->is_default);
     803             : 
     804           0 :     if ( outer!=NULL ) {
     805           0 :         outer->x = outer->y = 0;
     806           0 :         outer->width = needed.width;
     807           0 :         outer->height = needed.height;
     808             :     }
     809           0 : }
     810             : 
     811           0 : static void _gbutton_resize(GGadget *g, int32 width, int32 height ) {
     812             :     GRect inner;
     813           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     814             : 
     815           0 :     GButtonGetDesiredSize(g,NULL,&inner);
     816           0 :     if ( inner.height<height-2*bp ) inner.height = height-2*bp;
     817             :     
     818           0 :     g->inner.height = inner.height;
     819           0 :     g->inner.y = g->r.y + (height-inner.height)/2;
     820           0 :     g->r.width = width;
     821           0 :     g->r.height = height;
     822           0 :     GButtonSetInner((GButton *) g);
     823           0 : }
     824             : 
     825             : struct gfuncs gbutton_funcs = {
     826             :     0,
     827             :     sizeof(struct gfuncs),
     828             : 
     829             :     gbutton_expose,
     830             :     gbutton_mouse,
     831             :     gbutton_key,
     832             :     NULL,
     833             :     gbutton_focus,
     834             :     NULL,
     835             :     NULL,
     836             : 
     837             :     _ggadget_redraw,
     838             :     _ggadget_move,
     839             :     _gbutton_resize,
     840             :     _ggadget_setvisible,
     841             :     _ggadget_setenabled,
     842             :     _ggadget_getsize,
     843             :     _ggadget_getinnersize,
     844             : 
     845             :     gbutton_destroy,
     846             : 
     847             :     GButtonSetTitle,
     848             :     _GButtonGetTitle,
     849             :     NULL,
     850             :     GButtonSetImageTitle,
     851             :     GButtonGetImage,
     852             : 
     853             :     GButtonSetFont,
     854             :     GButtonGetFont,
     855             : 
     856             :     NULL,
     857             :     NULL,
     858             :     NULL,
     859             :     NULL,
     860             :     NULL,
     861             :     NULL,
     862             :     NULL,
     863             :     NULL,
     864             :     NULL,
     865             :     NULL,
     866             :     NULL,
     867             : 
     868             :     GButtonGetDesiredSize,
     869             :     _ggadget_setDesiredSize,
     870             :     NULL,
     871             :     GButtonIsDefault
     872             : };
     873             : 
     874             : struct gfuncs glistbutton_funcs = {
     875             :     0,
     876             :     sizeof(struct gfuncs),
     877             : 
     878             :     gbutton_expose,
     879             :     gbutton_mouse,
     880             :     gbutton_key,
     881             :     NULL,
     882             :     gbutton_focus,
     883             :     NULL,
     884             :     NULL,
     885             : 
     886             :     _ggadget_redraw,
     887             :     _ggadget_move,
     888             :     _gbutton_resize,
     889             :     _ggadget_setvisible,
     890             :     _ggadget_setenabled,
     891             :     _ggadget_getsize,
     892             :     _ggadget_getinnersize,
     893             : 
     894             :     gbutton_destroy,
     895             : 
     896             :     GButtonSetTitle,
     897             :     _GButtonGetTitle,
     898             :     NULL,
     899             :     GButtonSetImageTitle,
     900             :     GButtonGetImage,
     901             : 
     902             :     GButtonSetFont,
     903             :     GButtonGetFont,
     904             : 
     905             :     GListButClear,
     906             :     GListButSet,
     907             :     GListBGet,
     908             :     GListBGetItem,
     909             :     NULL,
     910             :     GListBSelectOne,
     911             :     GListBIsSelected,
     912             :     GListBGetFirst,
     913             :     NULL,
     914             :     NULL,
     915             :     NULL,
     916             : 
     917             :     GButtonGetDesiredSize,
     918             :     _ggadget_setDesiredSize,            /* GTextField does this right. but this is good enough for now */
     919             :     NULL,
     920             :     NULL
     921             : };
     922             : 
     923           0 : void _GButton_SetDefault(GGadget *g,int32 is_default) {
     924           0 :     GButton *gb = (GButton *) g;
     925             :     GRect maxr;
     926           0 :     int scale = GDrawPointsToPixels(g->base,1);
     927           0 :     int def_size = (g->box->flags & box_draw_default)?scale+GDrawPointsToPixels(g->base,2):0;
     928             : 
     929           0 :     if ( gb->is_default == is_default )
     930           0 : return;
     931           0 :     gb->is_default = is_default;
     932           0 :     if ( def_size==0 )
     933           0 : return;
     934           0 :     if ( is_default ) {
     935           0 :         g->r.x -= def_size;
     936           0 :         g->r.y -= def_size;
     937           0 :         g->r.width += 2*def_size;
     938           0 :         g->r.height += 2*def_size;
     939           0 :         maxr = g->r;
     940             :     } else {
     941           0 :         maxr = g->r;
     942           0 :         g->r.x += def_size;
     943           0 :         g->r.y += def_size;
     944           0 :         g->r.width -= 2*def_size;
     945           0 :         g->r.height -= 2*def_size;
     946             :     }
     947           0 :     ++maxr.width; ++maxr.height;
     948           0 :     GDrawRequestExpose(g->base, &maxr, false);
     949             : }
     950             : 
     951           0 : void _GButtonInit(void) {
     952             : #ifdef __Mac
     953             :     extern GBox _ggadget_Default_Box;
     954             : #endif
     955             : 
     956           0 :     if ( gbutton_inited )
     957           0 : return;
     958             : 
     959           0 :     GGadgetInit();
     960           0 :     _GGadgetCopyDefaultBox(&label_box);
     961           0 :     _GGadgetCopyDefaultBox(&_GGadget_button_box);
     962             : #ifdef __Mac
     963             :     _GGadget_button_box.border_type = bt_box;
     964             :     _GGadget_button_box.border_width = 1;
     965             :     _GGadget_button_box.border_shape = bs_roundrect;
     966             :     _GGadget_button_box.flags |= box_do_depressed_background;
     967             :     _GGadget_button_box.padding = 1;
     968             : #else
     969           0 :     _GGadget_button_box.flags |= box_foreground_border_inner|box_foreground_border_outer|
     970             :         /*box_active_border_inner|*/box_do_depressed_background|box_draw_default;
     971             : #endif
     972           0 :     label_box.border_type = bt_none;
     973           0 :     label_box.border_width = label_box.padding = /*label_box.flags =*/ 0;
     974           0 :     button_font = _GGadgetInitDefaultBox("GButton.",&_GGadget_button_box,NULL);
     975           0 :     label_font = _GGadgetInitDefaultBox("GLabel.",&label_box,button_font);
     976           0 :     shift_on_press = GResourceFindBool("GButton.ShiftOnPress",false);
     977           0 :     _GGadget_droplist_box = _GGadget_button_box;
     978           0 :     _GGadget_defaultbutton_box = _GGadget_button_box;
     979           0 :     _GGadget_cancelbutton_box  = _GGadget_button_box;
     980             : #ifdef __Mac
     981             :     _GGadget_defaultbutton_box.flags |= box_gradient_bg;
     982             :     _GGadget_defaultbutton_box.main_background = 0x64a4f2;
     983             :     _GGadget_defaultbutton_box.gradient_bg_end = 0xb7ceeb;
     984             :     _GGadget_cancelbutton_box.flags |= box_gradient_bg;
     985             :     _GGadget_cancelbutton_box.main_background = 0xf27458;
     986             :     _GGadget_cancelbutton_box.gradient_bg_end = 0xebb4a0;
     987             :     _GGadget_droplist_box.border_type = _ggadget_Default_Box.border_type;
     988             :     _GGadget_droplist_box.border_width = _ggadget_Default_Box.border_width;
     989             :     _GGadget_droplist_box.border_shape = _ggadget_Default_Box.border_shape;
     990             : #endif
     991           0 :     _GGadget_colorbutton_box  = _GGadget_button_box;
     992           0 :     _GGadgetInitDefaultBox("GDefaultButton.",&_GGadget_defaultbutton_box,NULL);
     993           0 :     _GGadgetInitDefaultBox("GCancelButton.",&_GGadget_cancelbutton_box,NULL);
     994           0 :     _GGadgetInitDefaultBox("GDropList.",&_GGadget_droplist_box,NULL);
     995           0 :     _GGadgetInitDefaultBox("GColorButton.",&_GGadget_colorbutton_box,NULL);
     996           0 :     gbutton_inited = true;
     997             : }
     998             : 
     999           0 : static void GLabelFit(GLabel *gl) {
    1000           0 :     int as=0, ds, ld;
    1001             :     GRect outer,inner;
    1002             : 
    1003           0 :     if ( gl->g.r.width == -1 ) {
    1004           0 :         gl->g.r.width = GDrawPointsToPixels(gl->g.base,GIntGetResource(_NUM_Buttonsize));
    1005           0 :         if ( gl->is_default )
    1006           0 :             gl->g.r.width += 6;
    1007             :     }
    1008             : 
    1009           0 :     GDrawWindowFontMetrics(gl->g.base,gl->font,&as, &ds, &ld);
    1010           0 :     gl->as = as;
    1011           0 :     gl->fh = as+ds;
    1012             : 
    1013           0 :     GButtonGetDesiredSize(&gl->g,&outer, &inner);
    1014           0 :     _ggadgetSetRects(&gl->g,&outer, &inner, 0, 0);
    1015           0 :     if ( gl->g.takes_input )
    1016           0 :         GButtonSetInner((GButton *) gl);
    1017           0 : }
    1018             : 
    1019           0 : static GLabel *_GLabelCreate(GLabel *gl, struct gwindow *base, GGadgetData *gd,void *data, GBox *def) {
    1020           0 :     if ( !gbutton_inited )
    1021           0 :         _GButtonInit();
    1022           0 :     gl->g.funcs = &gbutton_funcs;
    1023           0 :     _GGadget_Create(&gl->g,base,gd,data,def);
    1024             : 
    1025           0 :     if (( gl->is_default = gd->flags&gg_but_default?1:0 ) )
    1026           0 :         _GWidget_SetDefaultButton(&gl->g);
    1027           0 :     if (( gl->is_cancel = gd->flags&gg_but_cancel?1:0 ))
    1028           0 :         _GWidget_SetCancelButton(&gl->g);
    1029           0 :     gl->font = def==&label_box ? label_font : button_font;
    1030           0 :     if ( gd->label!=NULL ) {
    1031           0 :         gl->image_precedes = gd->label->image_precedes;
    1032           0 :         if ( gd->label->font!=NULL )
    1033           0 :             gl->font = gd->label->font;
    1034           0 :         if ( gd->label->text_in_resource && gd->label->text_is_1byte )
    1035           0 :             gl->label = utf82u_mncopy((char *) gd->label->text,&gl->g.mnemonic);
    1036           0 :         else if ( gd->label->text_in_resource )
    1037           0 :             gl->label = u_copy((unichar_t *) GStringGetResource((intpt) gd->label->text,&gl->g.mnemonic));
    1038           0 :         else if ( gd->label->text_is_1byte )
    1039           0 :             gl->label = /* def2u_*/ utf82u_copy((char *) gd->label->text);
    1040             :         else
    1041           0 :             gl->label = u_copy(gd->label->text);
    1042           0 :         gl->image = gd->label->image;
    1043             :     }
    1044           0 :     gl->shiftonpress = shift_on_press;
    1045           0 :     GLabelFit(gl);
    1046           0 :     _GGadget_FinalPosition(&gl->g,base,gd);
    1047             : 
    1048           0 :     if ( gd->flags & gg_group_end )
    1049           0 :         _GGadgetCloseGroup(&gl->g);
    1050           0 : return( gl );
    1051             : }
    1052             : 
    1053           0 : GGadget *GLabelCreate(struct gwindow *base, GGadgetData *gd,void *data) {
    1054           0 :     GLabel *gl = calloc(1,sizeof(GListButton));;
    1055             :     int i;
    1056             : 
    1057           0 :     if ( gd->u.list!=NULL ) {
    1058           0 :         gl->ti = GTextInfoArrayFromList(gd->u.list,&gl->ltot);
    1059             :     }
    1060           0 :     if ( gd->label==NULL && gd->u.list!=NULL ) {
    1061           0 :         for ( i=0; gd->u.list[i].text == NULL; ++i );
    1062           0 :         if ( gd->u.list[i].text!=NULL )
    1063           0 :             gd->label = &gd->u.list[i];
    1064             :     }
    1065           0 :     gl = _GLabelCreate(gl,base,gd,data,&label_box);
    1066           0 : return( &gl->g );
    1067             : }
    1068             : 
    1069           0 : GGadget *GButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
    1070           0 :     GLabel *gl = _GLabelCreate(calloc(1,sizeof(GLabel)),base,gd,data,
    1071           0 :             gd->flags & gg_but_default ? &_GGadget_defaultbutton_box :
    1072           0 :             gd->flags & gg_but_cancel ? &_GGadget_cancelbutton_box :
    1073             :             &_GGadget_button_box);
    1074             : 
    1075           0 :     gl->g.takes_input = true; gl->g.takes_keyboard = true; gl->g.focusable = true;
    1076           0 : return( &gl->g );
    1077             : }
    1078             : 
    1079           0 : GGadget *GImageButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
    1080           0 :     GImageButton *gl =
    1081           0 :         (GImageButton *) _GLabelCreate(calloc(1,sizeof(GImageButton)),base,gd,data,&_GGadget_button_box);
    1082             : 
    1083           0 :     gl->g.takes_input = true;
    1084           0 :     gl->labeltype = 1;
    1085           0 :     if ( gd->label!=NULL ) {
    1086           0 :         gl->img_within = gd->label[1].image;
    1087           0 :         gl->active = gd->label[2].image;
    1088           0 :         gl->disabled = gd->label[3].image;
    1089             :     }
    1090           0 : return( &gl->g );
    1091             : }
    1092             : 
    1093           0 : GGadget *GColorButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
    1094             :     GColorButton *gl;
    1095             :     static GTextInfo ti;
    1096           0 :     Color col = gd->u.col;
    1097             : 
    1098           0 :     if ( ti.image==NULL && ti.text==NULL ) {
    1099           0 :         ti.image = GGadgetImageCache("colorwheel.png");
    1100           0 :         if ( ti.image==NULL ) {
    1101           0 :             ti.text = (unichar_t *) _("Color");
    1102           0 :             ti.text_is_1byte = true;
    1103             :         }
    1104             :     }
    1105           0 :     gd->label = &ti;
    1106           0 :     gl = calloc(1,sizeof(GColorButton));
    1107           0 :     gl->labeltype = 3;
    1108           0 :     gl = (GColorButton *) _GLabelCreate((GLabel *) gl,base,gd,data,&_GGadget_colorbutton_box);
    1109           0 :     gl->g.takes_input = true;
    1110           0 :     gl->col = col;
    1111           0 : return( &gl->g );
    1112             : }
    1113             : 
    1114           0 : void GColorButtonSetColor(GGadget *g, Color col) {
    1115           0 :     GColorButton *gb = (GColorButton *) g;
    1116           0 :     gb->col = col;
    1117           0 :     GGadgetRedraw(g);
    1118           0 : }
    1119             : 
    1120           0 : Color GColorButtonGetColor(GGadget *g) {
    1121           0 : return( ((GColorButton *) g)->col );
    1122             : }
    1123             : 
    1124           0 : static void GListButtonSelected(GGadget *g, int i) {
    1125           0 :     GListButton *gl = (GListButton *) g;
    1126             :     GEvent e;
    1127             : 
    1128           0 :     gl->popup = NULL;
    1129           0 :     _GWidget_ClearGrabGadget(&gl->g);
    1130           0 :     if ( i<0 || i>=gl->ltot )
    1131           0 : return;
    1132           0 :     free(gl->label); gl->label = u_copy(gl->ti[i]->text);
    1133           0 :     gl->image = gl->ti[i]->image;
    1134           0 :     gl->image_precedes = gl->ti[i]->image_precedes;
    1135           0 :     GButtonSetInner((GButton *) gl);
    1136           0 :     _ggadget_redraw(g);
    1137             : 
    1138           0 :     e.type = et_controlevent;
    1139           0 :     e.w = g->base;
    1140           0 :     e.u.control.subtype = et_listselected;
    1141           0 :     e.u.control.g = g;
    1142           0 :     e.u.control.u.list.from_mouse = true;
    1143           0 :     if ( gl->g.handle_controlevent != NULL )
    1144           0 :         (gl->g.handle_controlevent)(&gl->g,&e);
    1145             :     else
    1146           0 :         GDrawPostEvent(&e);
    1147             : }
    1148             : 
    1149           0 : static void GListButtonDoPopup(GListButton *gl) {
    1150           0 :     gl->within = false; gl->pressed = false;
    1151           0 :     gl->popup = GListPopupCreate(&gl->g,GListButtonSelected,gl->ti);
    1152           0 : }
    1153             : 
    1154           0 : static int _GListAlphaCompare(const void *v1, const void *v2) {
    1155           0 :     GTextInfo * const *pt1 = v1, * const *pt2 = v2;
    1156           0 : return( GTextInfoCompare(*pt1,*pt2));
    1157             : }
    1158             : 
    1159           0 : GGadget *GListButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
    1160           0 :     GListButton *gl = calloc(1,sizeof(GListButton));
    1161             :     int i;
    1162             : 
    1163           0 :     gl->labeltype = 2;
    1164           0 :     gl->g.takes_input = true;
    1165           0 :     if ( gd->u.list!=NULL ) {
    1166           0 :         gl->ti = GTextInfoArrayFromList(gd->u.list,&gl->ltot);
    1167           0 :         if ( gd->flags & gg_list_alphabetic )
    1168           0 :             qsort(gl->ti,gl->ltot,sizeof(GTextInfo *),_GListAlphaCompare);
    1169             :     }
    1170           0 :     if ( gd->label==NULL && gd->u.list!=NULL ) {
    1171             :         /* find first selected item if there is one */
    1172           0 :         for ( i=0; gd->u.list[i].text!=NULL || gd->u.list[i].line; ++i )
    1173           0 :             if ( gd->u.list[i].selected )
    1174           0 :         break;
    1175             :         /* else first item with text */
    1176           0 :         if ( gd->u.list[i].text==NULL && !gd->u.list[i].line ) {
    1177           0 :             for ( i=0; gd->u.list[i].line; ++i );
    1178           0 :             if ( gd->u.list[i].text==NULL && !gd->u.list[i].line )
    1179           0 :                 i = 0;
    1180             :         }
    1181           0 :         gd->label = &gd->u.list[i];
    1182             :     }
    1183           0 :     _GLabelCreate((GLabel *) gl,base,gd,data,&_GGadget_droplist_box);
    1184           0 :     gl->g.funcs = &glistbutton_funcs;
    1185           0 : return( &gl->g );
    1186             : }
    1187             : 
    1188           0 : GResInfo *_GButtonRIHead(void) {
    1189           0 :     _GButtonInit();
    1190           0 : return( &glabel_ri );
    1191             : }

Generated by: LCOV version 1.10