LCOV - code coverage report
Current view: top level - gdraw - gcontainer.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 758 0.0 %
Date: 2017-08-04 Functions: 0 47 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 "gwidgetP.h"
      28             : #include "ggadgetP.h"
      29             : #include "../gdraw/gdrawP.h"
      30             : #include <ggadget.h>
      31             : #include <gkeysym.h>
      32             : #include <utype.h>
      33             : #include <gresource.h>
      34             : #include <string.h>
      35             : 
      36             : static GWindow current_focus_window, previous_focus_window, last_input_window;
      37             :     /* in focus follows pointer mode, the current focus doesn't really count */
      38             :     /*  until the window gets input (otherwise moving the mouse across a wind */
      39             :     /*  would set the previous_focus_window to something inappropriate) */
      40             :     /* So... we set current focus window when a window gains the focus, and */
      41             :     /*  at the same time we set the previous focus window to the last window */
      42             :     /*  that got input. NOT to the old current_focus_window (which might be junk) */
      43             : static GWindow last_paletted_focus_window = NULL;
      44             : 
      45             : static int broken_palettes = true;
      46             : static int widgets_initted = false;
      47             : 
      48           0 : static void gwidget_init(void) {
      49           0 :     broken_palettes = GResourceFindBool("GWidget.BrokenPalettes",broken_palettes);
      50           0 :     widgets_initted = true;
      51           0 : }
      52             : 
      53           0 : GWindow GWindowGetCurrentFocusTopWindow(void) {
      54           0 : return( current_focus_window );
      55             : }
      56             : 
      57           0 : GWindow GWidgetGetPreviousFocusTopWindow(void) {
      58           0 : return( previous_focus_window );
      59             : }
      60             : 
      61           0 : GGadget *GWindowGetCurrentFocusGadget(void) {
      62             :     GTopLevelD *td;
      63           0 :     if ( current_focus_window==NULL )
      64           0 : return( NULL );
      65           0 :     td = (GTopLevelD *) (current_focus_window->widget_data);
      66           0 : return( td->gfocus );
      67             : }
      68             : 
      69           0 : void GWindowClearFocusGadgetOfWindow(GWindow gw) {
      70             :     GTopLevelD *td;
      71           0 :     if ( gw==NULL )
      72           0 : return;
      73           0 :     while ( gw->parent!=NULL && !gw->is_toplevel ) gw=gw->parent;
      74           0 :     td = (GTopLevelD *) (gw->widget_data);
      75           0 :     if ( gw == current_focus_window && td->gfocus!=NULL &&
      76           0 :             td->gfocus->funcs->handle_focus!=NULL ) {
      77             :         GEvent e;
      78           0 :         e.type = et_focus;
      79           0 :         e.w = gw;
      80           0 :         e.u.focus.gained_focus = false;
      81           0 :         e.u.focus.mnemonic_focus = mf_normal;
      82           0 :         (td->gfocus->funcs->handle_focus)(td->gfocus,&e);
      83             :     }
      84           0 :     td->gfocus = NULL;
      85             : }
      86             : 
      87           0 : GGadget *GWindowGetFocusGadgetOfWindow(GWindow gw) {
      88             :     GTopLevelD *td;
      89           0 :     if ( gw==NULL )
      90           0 : return( NULL );
      91           0 :     while ( gw->parent!=NULL && !gw->is_toplevel ) gw=gw->parent;
      92           0 :     td = (GTopLevelD *) (gw->widget_data);
      93           0 : return( td->gfocus );
      94             : }
      95             : 
      96           0 : int GGadgetActiveGadgetEditCmd(GWindow gw,enum editor_commands cmd) {
      97           0 :     GGadget *g = GWindowGetFocusGadgetOfWindow(gw);
      98             : 
      99           0 :     if ( g==NULL )
     100           0 : return( false );
     101           0 : return( GGadgetEditCmd(g,cmd));
     102             : }
     103             : 
     104           0 : GWindow GWidgetGetCurrentFocusWindow(void) {
     105             :     GTopLevelD *td;
     106           0 :     if ( current_focus_window==NULL )
     107           0 : return( NULL );
     108           0 :     td = (GTopLevelD *) (current_focus_window->widget_data);
     109           0 :     if ( td->gfocus!=NULL )
     110           0 : return( td->gfocus->base );
     111           0 : return( td->wfocus );
     112             : }
     113             : 
     114             : struct gfuncs *last_indicatedfocus_funcs;               /* !!!! Debug code */
     115             : GGadget *last_indicatedfocus_gadget;
     116             : struct gwindow *last_indicatedfocus_widget;
     117             : 
     118           0 : static void _GWidget_IndicateFocusGadget(GGadget *g, enum mnemonic_focus mf) {
     119             :     GWindow top;
     120             :     GTopLevelD *td;
     121             :     GEvent e;
     122             : 
     123           0 :   last_indicatedfocus_funcs = g->funcs;
     124           0 :   last_indicatedfocus_gadget = g;
     125           0 :   last_indicatedfocus_widget = g->base;
     126             : 
     127           0 :     if ( g->funcs==NULL ) {
     128           0 :         fprintf( stderr, "Bad focus attempt\n" );
     129           0 : return;
     130             :     }
     131             : 
     132             :     // We recurse and find the top-level gadget.
     133           0 :     for ( top=g->base; top->parent!=NULL && !top->is_toplevel ; top=top->parent );
     134           0 :     td = (GTopLevelD *) (top->widget_data);
     135             : 
     136             :     // We check whether the gadget in question has focus.
     137           0 :     if ( td->gfocus!=g ) {
     138             :       // If not, we try to deal with the lack of focus.
     139             : /* Hmm. KDE doesn't give us a focus out event when we make a window invisible */
     140             : /*  So to be on the save side lets send local focus out events even when not */
     141             : /*  strictly needed */
     142           0 :         if ( /*top == current_focus_window &&*/ td->gfocus!=NULL &&
     143           0 :                 td->gfocus->funcs->handle_focus!=NULL ) {
     144             :             // We use the focus handler provided by the presently focussed gadget and process a loss-of-focus event for the currently focused object.
     145           0 :             memset(&e, 0, sizeof(GEvent));
     146           0 :             e.type = et_focus;
     147           0 :             e.w = top;
     148           0 :             e.u.focus.gained_focus = false;
     149           0 :             e.u.focus.mnemonic_focus = mf_normal;
     150           0 :             (td->gfocus->funcs->handle_focus)(td->gfocus,&e);
     151             :         }
     152             :     }
     153             :     // We give focus to the desired gadget.
     154           0 :     td->gfocus = g; td->wfocus = NULL;
     155           0 :     if ( top == current_focus_window && g->funcs->handle_focus!=NULL ) {
     156             :         // If the desired gadget has a focus handler, we construct an event and run it.
     157           0 :         memset(&e, 0, sizeof(GEvent));
     158           0 :         e.u.focus.gained_focus = true;
     159           0 :         e.u.focus.mnemonic_focus = mf;
     160           0 :         (g->funcs->handle_focus)(g,&e);
     161             :     }
     162             : }
     163             : 
     164           0 : void GWidgetIndicateFocusGadget(GGadget *g) {
     165           0 :     _GWidget_IndicateFocusGadget(g,mf_normal);
     166           0 : }
     167             : 
     168           0 : static GGadget *_GWidget_FindPost(GContainerD *cd,GGadget *oldfocus,GGadget **last) {
     169             :     GGadget *g;
     170             :     GWidgetD *w;
     171             : 
     172           0 :     if ( cd==NULL || !cd->iscontainer )
     173           0 : return( false );
     174           0 :     for ( g=cd->gadgets; g!=NULL; g=g->prev ) {
     175           0 :         if ( g==oldfocus )
     176           0 : return( *last );
     177           0 :         if ( g->focusable && g->state!=gs_invisible && g->state!=gs_disabled )
     178           0 :             *last = g;
     179             :     }
     180           0 :     for ( w=cd->widgets; w!=NULL; w=w->next ) {
     181           0 :         if (( g = _GWidget_FindPost((GContainerD *) w,oldfocus,last))!=NULL )
     182           0 : return( g );
     183             :     }
     184           0 : return( NULL );
     185             : }
     186             : 
     187           0 : void GWidgetNextFocus(GWindow top) {
     188             :     GTopLevelD *topd;
     189           0 :     GGadget *focus, *last=NULL;
     190             : 
     191           0 :     while ( top->parent!=NULL && !top->is_toplevel ) top = top->parent;
     192           0 :     topd = (GTopLevelD *) (top->widget_data);
     193           0 :     if ( topd==NULL || topd->gfocus == NULL )
     194           0 : return;
     195           0 :     if ( (focus = _GWidget_FindPost((GContainerD *) topd,topd->gfocus,&last))== NULL ) {
     196             :         /* if we didn't find a Next Gadget, it's either because: */
     197             :         /*  1) the focus gadget is first in the chain, in which case we want */
     198             :         /*      the last thing in the chain */
     199             :         /*  2) our data structures are screwed up */
     200           0 :         _GWidget_FindPost((GContainerD *) topd,NULL,&last);
     201           0 :         focus = last;
     202             :     }
     203           0 :     _GWidget_IndicateFocusGadget(focus,mf_tab);
     204             : }
     205             : 
     206           0 : static GGadget *_GWidget_FindPrev(GContainerD *cd,GGadget *oldfocus,GGadget **first, int *found) {
     207             :     GGadget *g;
     208             :     GWidgetD *w;
     209             : 
     210           0 :     if ( cd==NULL || !cd->iscontainer )
     211           0 : return( false );
     212           0 :     for ( g=cd->gadgets; g!=NULL; g=g->prev ) {
     213           0 :         if ( g->focusable && g->state!=gs_invisible && g->state!=gs_disabled ) {
     214           0 :             if ( *first==NULL )
     215           0 :                 *first = g;
     216           0 :             if ( *found )
     217           0 : return( g );
     218             :         }
     219           0 :         if ( g==oldfocus )
     220           0 :             *found = true;
     221             :     }
     222           0 :     for ( w=cd->widgets; w!=NULL; w=w->next ) {
     223           0 :         if (( g = _GWidget_FindPrev((GContainerD *) w,oldfocus,first,found))!=NULL )
     224           0 : return( g );
     225             :     }
     226           0 : return( NULL );
     227             : }
     228             :     
     229           0 : void GWidgetPrevFocus(GWindow top) {
     230             :     GTopLevelD *topd;
     231             :     GGadget *focus;
     232             : 
     233           0 :     while ( top->parent!=NULL && !top->is_toplevel ) top = top->parent;
     234           0 :     topd = (GTopLevelD *) (top->widget_data);
     235           0 :     if ( topd==NULL || topd->gfocus == NULL )
     236           0 : return;
     237           0 :     for ( focus = topd->gfocus->prev;
     238           0 :             focus!=NULL && (!focus->focusable || focus->state==gs_invisible || focus->state==gs_disabled);
     239           0 :             focus = focus->prev );
     240           0 :     if ( focus==NULL ) {
     241           0 :         GGadget *first = NULL; int found = false;
     242           0 :         if ( (focus = _GWidget_FindPrev((GContainerD *) topd,topd->gfocus,&first,&found))== NULL )
     243           0 :             focus = first;
     244             :     }
     245           0 :     _GWidget_IndicateFocusGadget(focus,mf_tab);
     246             : }
     247             : 
     248           0 : static int _GWidget_Container_eh(GWindow gw, GEvent *event) {
     249             : /* Gadgets can get mouse, char and expose events */
     250             : /* Widgets might need char events redirected to them */
     251             : /* If a gadget doesn't want an event it returns false from its eh */
     252             : /* If a subwidget doesn't want an event it may send it up to us */
     253           0 :     int handled = false;
     254             :     GGadget *gadget;
     255           0 :     GContainerD *gd = (GContainerD *) (gw->widget_data);
     256             :     GWindow pixmap;
     257             :     GWindow parent;
     258             :     GTopLevelD *topd;
     259             : 
     260           0 :     if ( gd==NULL )                     /* dying */
     261           0 : return(true);
     262             : 
     263           0 :     for ( parent = gw; parent->parent!=NULL && parent->parent->widget_data!=NULL &&
     264           0 :             !parent->is_toplevel; parent = parent->parent );
     265           0 :     topd = (GTopLevelD *) (parent->widget_data);
     266           0 :     if ( topd==NULL )
     267           0 :         fprintf( stderr, "No top level window found\n" );
     268             : 
     269           0 :     GGadgetPopupExternalEvent(event);
     270           0 :     if ( event->type == et_expose ) {
     271             :         GRect old;
     272             : 
     273           0 :         pixmap = _GWidget_GetPixmap(gw,&event->u.expose.rect);
     274           0 :         pixmap->ggc->bg = gw->ggc->bg;
     275           0 :         GDrawPushClip(pixmap,&event->u.expose.rect,&old);
     276           0 :         pixmap->user_data = gw->user_data;
     277             : 
     278           0 :         if ( gd->e_h!=NULL ) {
     279           0 :             (gd->e_h)(pixmap,event);
     280             :         }
     281           0 :         for ( gadget = gd->gadgets; gadget!=NULL ; gadget=gadget->prev )
     282           0 :             if ( ! ( gadget->r.x>event->u.expose.rect.x+event->u.expose.rect.width ||
     283           0 :                     gadget->r.y>event->u.expose.rect.y+event->u.expose.rect.height ||
     284           0 :                     gadget->r.x+gadget->r.width<event->u.expose.rect.x ||
     285           0 :                     gadget->r.y+gadget->r.height<event->u.expose.rect.y ) &&
     286           0 :                     gadget->state!=gs_invisible )
     287           0 :                 (gadget->funcs->handle_expose)(pixmap,gadget,event);
     288             : 
     289           0 :         GDrawPopClip(pixmap,&old);
     290           0 :         _GWidget_RestorePixmap(gw,pixmap,&event->u.expose.rect);
     291             : 
     292           0 : return( true );
     293           0 :     } else if ( event->type >= et_mousemove && event->type <= et_crossing ) {
     294           0 :         if ( topd!=NULL && topd->popupowner!=NULL ) {
     295           0 :             handled = (topd->popupowner->funcs->handle_mouse)(topd->popupowner,event);
     296           0 : return( handled );
     297             :         }
     298           0 :         if ( gd->grabgadget && event->type==et_mousedown &&
     299           0 :                 (event->u.mouse.state&ksm_buttons)==0 )
     300           0 :             gd->grabgadget = NULL;           /* Happens if a gadget invokes a popup menu. Gadget remains grabbed because menu gets the mouse up */
     301           0 :         if ( gd->grabgadget!=NULL ) {
     302           0 :             handled = (gd->grabgadget->funcs->handle_mouse)(gd->grabgadget,event);
     303           0 :             if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     304           0 :                     gw->is_dying || gw->widget_data==NULL )
     305           0 : return( true );
     306           0 :             if ( event->type==et_mouseup )
     307           0 :                 gd->grabgadget = NULL;
     308           0 :         } else if ( event->type==et_mousedown ) {
     309           0 :             if ( !parent->is_popup )
     310           0 :                 last_input_window = parent;
     311           0 :             for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     312           0 :                 if ( gadget->state!=gs_disabled && gadget->state!=gs_invisible &&
     313           0 :                         gadget->takes_input &&
     314           0 :                         GGadgetWithin(gadget,event->u.mouse.x,event->u.mouse.y)) {
     315           0 :                     handled = (gadget->funcs->handle_mouse)(gadget,event);
     316           0 :                     if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     317           0 :                             gw->is_dying || gw->widget_data==NULL )
     318           0 : return( true );
     319           0 :                     gd->grabgadget = gadget;
     320           0 :                     if ( gadget->focusable && handled )
     321           0 :                         GWidgetIndicateFocusGadget(gadget);
     322             :                 }
     323             :             }
     324             :         } else {
     325           0 :             for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     326           0 :                 if ( !gadget->state!=gs_disabled && gadget->state!=gs_invisible &&
     327             :                         /*gadget->takes_input &&*/   /* everybody needs mouse moves for popups, even labels */
     328           0 :                         GGadgetWithin(gadget,event->u.mouse.x,event->u.mouse.y)) {
     329           0 :                     if ( gd->lastwiggle!=NULL && gd->lastwiggle!=gadget )
     330           0 :                         (gd->lastwiggle->funcs->handle_mouse)(gd->lastwiggle,event);
     331           0 :                     handled = (gadget->funcs->handle_mouse)(gadget,event);
     332           0 :                     if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     333           0 :                             gw->is_dying || gw->widget_data==NULL )
     334           0 : return( true );
     335           0 :                     gd->lastwiggle = gadget;
     336             :                 }
     337             :             }
     338           0 :             if ( !handled && gd->lastwiggle!=NULL ) {
     339           0 :                 (gd->lastwiggle->funcs->handle_mouse)(gd->lastwiggle,event);
     340           0 :                 if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     341             :                         gw->is_dying )
     342           0 : return( true );
     343             :             }
     344             :         }
     345           0 :     } else if ( event->type == et_char || event->type == et_charup ) {
     346           0 :         if ( topd!=NULL ) {
     347           0 :             handled = (topd->handle_key)(parent,gw,event);
     348             :         }
     349           0 :     } else if ( event->type == et_drag || event->type == et_dragout || event->type==et_drop ) {
     350           0 :         GGadget *lastdd = NULL;
     351             :         GEvent e;
     352           0 :         for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     353           0 :             if ( gadget->funcs->handle_sel &&
     354           0 :                     GGadgetWithin(gadget,event->u.drag_drop.x,event->u.drag_drop.y))
     355           0 :                 if (( handled = (gadget->funcs->handle_sel)(gadget,event) )) {
     356           0 :                     lastdd = gadget;
     357           0 :                     if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     358             :                             gw->is_dying )
     359           0 : return( true );
     360             :                     }
     361             :         }
     362           0 :         if ( !handled && gd->e_h!=NULL ) {
     363           0 :             handled = (gd->e_h)(gw,event);
     364           0 :             if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     365             :                     gw->is_dying )
     366           0 : return( true );
     367           0 :             lastdd = (GGadget *) -1;
     368             :         }
     369           0 :         e.type = et_dragout;
     370           0 :         e.w = gw;
     371           0 :         if ( lastdd!=gd->lastddgadget ) {
     372           0 :             if ( gd->lastddgadget==(GGadget *) -1 )
     373           0 :                 (gd->e_h)(gw,&e);
     374           0 :             else if ( gd->lastddgadget!=NULL )
     375           0 :                 (gd->lastddgadget->funcs->handle_sel)(gd->lastddgadget,&e);
     376           0 :             if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
     377             :                     gw->is_dying )
     378           0 : return( true );
     379             :         }
     380           0 :         if ( event->type==et_drag )
     381           0 :             gd->lastddgadget = lastdd;
     382             :         else
     383           0 :             gd->lastddgadget = NULL;
     384           0 : return( handled );
     385           0 :     } else if ( event->type == et_selclear ) {
     386           0 :         for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     387           0 :             if ( gadget->funcs->handle_sel ) {
     388           0 :                 if ( (handled = (gadget->funcs->handle_sel)(gadget,event)) )
     389           0 :         break;
     390             :             }
     391             :         }
     392           0 :     } else if ( event->type == et_timer ) {
     393           0 :         for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     394           0 :             if ( gadget->funcs->handle_timer ) {
     395           0 :                 if ( (handled = (gadget->funcs->handle_timer)(gadget,event)) )
     396           0 :         break;
     397             :             }
     398             :         }
     399           0 :     } else if ( event->type == et_resize ) {
     400           0 :         GWidgetFlowGadgets(gw);
     401             :     }
     402           0 :     if ( gd->e_h!=NULL && (!handled || event->type==et_mousemove ))
     403           0 :         handled = (gd->e_h)(gw,event);
     404           0 :     if ( event->type == et_destroy ) {
     405             :         GGadget *prev;
     406           0 :         for ( gadget = gd->gadgets; gadget!=NULL ; gadget=prev ) {
     407           0 :             prev = gadget->prev;
     408           0 :             if ( !gadget->contained )
     409           0 :                 (gadget->funcs->destroy)(gadget);
     410             :             /* contained ggadgets will be destroyed when their owner is destroyed */
     411             :         }
     412             :         /* Widgets are windows and should get their own destroy events and free themselves */
     413             :         /* remove us from our parent */
     414           0 :         parent = gw->parent;
     415           0 :         if ( parent!=NULL && parent->widget_data!=NULL ) {
     416           0 :             GContainerD *pgd = (GContainerD *) (parent->widget_data);
     417             :             struct gwidgetdata *wd, *pwd;
     418           0 :             for ( pwd=NULL, wd=pgd->widgets; wd!=NULL && wd!=(struct gwidgetdata *) gd; pwd = wd, wd = wd->next );
     419           0 :             if ( pwd==NULL )
     420           0 :                 pgd->widgets = gd->next;
     421             :             else
     422           0 :                 pwd->next = gd->next;
     423             :         }
     424           0 :         free(gd);
     425           0 :         gw->widget_data = NULL;
     426             :     }
     427           0 : return( handled );
     428             : }
     429             : 
     430           0 : static int GWidgetCheckMn(GContainerD *gd,GEvent *event) {
     431           0 :     int handled = false;
     432             :     GGadget *gadget, *last;
     433             :     struct gwidgetdata *widget;
     434           0 :     unichar_t keysym = event->u.chr.keysym;
     435           0 :     int mask = GMenuMask() & (ksm_control|ksm_cmdmacosx);
     436             : 
     437           0 :     if ( (mask&ksm_cmdmacosx) && keysym>0x7f &&
     438           0 :             (event->u.chr.state&ksm_meta) && !(event->u.chr.state&mask) )
     439           0 :         keysym = GGadgetUndoMacEnglishOptionCombinations(event);
     440             : 
     441           0 :     if ( islower(keysym)) keysym = toupper(keysym);
     442           0 :     for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
     443           0 :         if ( (event->u.chr.state&ksm_meta) && !(event->u.chr.state&mask) &&
     444           0 :                 gadget->mnemonic==keysym &&
     445           0 :                 gadget->state != gs_invisible && gadget->state != gs_disabled ) {
     446           0 :             if ( gadget->focusable ) {       /* labels may have a mnemonic */
     447             :                     /* (ie. because textfields can't display mnemonics) */
     448             :                     /* but they don't act on it */
     449           0 :                 _GWidget_IndicateFocusGadget(gadget,mf_mnemonic);
     450           0 :                 handled = true;
     451           0 :             } else if ( last!=NULL && last->mnemonic=='\0' ) {
     452             :                 /* So if we get a label with a mnemonic, and the next gadget */
     453             :                 /*  is focusable and doesn't have a mnemoic itself, give it */
     454             :                 /*  the label's focus */
     455           0 :                 _GWidget_IndicateFocusGadget(last,mf_mnemonic);
     456           0 :                 handled = true;
     457             :             }
     458           0 :         } else if ( gadget->shortcut == keysym &&
     459           0 :                 (gadget->short_mask&event->u.chr.state)==gadget->short_mask ) {
     460           0 :             _GWidget_IndicateFocusGadget(gadget,mf_shortcut);
     461           0 :             handled = true;
     462           0 :         } else if ( gadget->state != gs_invisible &&
     463           0 :                 gadget->state != gs_disabled &&
     464             :                 gadget->focusable ) {
     465           0 :             last = gadget;
     466             :         }
     467             :     }
     468           0 :     for ( widget = gd->widgets; widget!=NULL && !handled ; widget=widget->next ) {
     469           0 :         if ( widget->iscontainer )
     470           0 :             handled = GWidgetCheckMn((GContainerD *) widget,event);
     471             :     }
     472           0 : return( handled );
     473             : }
     474             : 
     475           0 : static int _GWidget_TopLevel_Key(GWindow top, GWindow ew, GEvent *event) {
     476           0 :     GTopLevelD *topd = (GTopLevelD *) (top->widget_data);
     477           0 :     int handled=0;
     478             :     GEvent sub;
     479             : 
     480           0 :     if ( !top->is_popup )
     481           0 :         last_input_window = top;
     482             : 
     483             :     /* If the palette has the focus, and it usually will under kde, then */
     484             :     /*  give the event to the main window if the cursor is outside of the palette */
     485           0 :     if ( topd->ispalette ) {
     486           0 :         if ( event->u.chr.x<-2 || event->u.chr.x>top->pos.width+2 ||
     487           0 :                 event->u.chr.y<-2 || event->u.chr.y>top->pos.height+2 ) {
     488             :             GPoint p;
     489           0 :             topd = topd->owner;
     490           0 :             p.x = event->u.chr.x; p.y = event->u.chr.y;
     491           0 :             GDrawTranslateCoordinates(ew,topd->w,&p);
     492           0 :             event->u.chr.x = p.x; event->u.chr.y = p.y;
     493           0 :             ew = top = topd->w;
     494           0 :             event->w = top;
     495             :         }
     496             :     }
     497             :     /* Check for mnemonics and shortcuts */
     498           0 :     if ( event->type == et_char && !GKeysymIsModifier(event->u.chr.keysym) ) {
     499           0 :         handled = GMenuPopupCheckKey(event);
     500           0 :         if ( topd->ispalette ) {
     501           0 :             if ( !(handled = GMenuBarCheckKey(top,topd->owner->gmenubar,event)) )
     502           0 :                 handled = GWidgetCheckMn((GContainerD *) topd->owner,event);
     503             :         }
     504           0 :         if ( !handled )
     505           0 :             if ( !(handled = GMenuBarCheckKey(top,topd->gmenubar,event)) )
     506           0 :                 handled = GWidgetCheckMn((GContainerD *) topd,event);
     507             :     }
     508           0 :     if ( handled )
     509             :         /* No op */;
     510           0 :     else if ( topd->popupowner!=NULL ) {
     511             :         /* When we've got an active popup (menu, list, etc.) all key events */
     512             :         /*  go to the popups owner (which, presumably sends them to the popup)*/
     513           0 :         if ( topd->popupowner->funcs->handle_key !=NULL )
     514           0 :             handled = (topd->popupowner->funcs->handle_key)(topd->popupowner,event);
     515           0 :     } else if ( topd->gfocus!=NULL && topd->gfocus->funcs->handle_key )
     516           0 :         handled = (topd->gfocus->funcs->handle_key)(topd->gfocus,event);
     517           0 :     else if ( topd->wfocus!=NULL ) {
     518           0 :         if ( topd->wfocus->widget_data==NULL ) {
     519           0 :             if ( topd->wfocus->eh!=NULL )
     520           0 :                 handled = (topd->wfocus->eh)(topd->wfocus,event);
     521           0 :         } else if ( topd->wfocus->widget_data->e_h!=NULL )
     522           0 :             handled = (topd->wfocus->widget_data->e_h)(topd->wfocus,event);
     523             :     }
     524           0 :     if ( !handled ) {
     525           0 :         if ( ew->widget_data==NULL ) {
     526           0 :             if ( ew->eh!=NULL )
     527           0 :                 handled = (ew->eh)(ew,event);
     528           0 :         } else if ( ew->widget_data->e_h!=NULL )
     529           0 :             handled = (ew->widget_data->e_h)(ew,event);
     530             :     }
     531             : 
     532           0 :     if ( event->type==et_charup )
     533           0 : return( handled );
     534             :     /* If no one wanted it then try keyboard navigation */
     535             :     /* Tab or back tab cycles the focus through our widgets/gadgets */
     536           0 :     if ( !handled && (event->u.chr.keysym==GK_Tab || event->u.chr.keysym==GK_BackTab )) {
     537           0 :         if ( event->u.chr.keysym==GK_BackTab || (event->u.chr.state&ksm_shift) )
     538           0 :             GWidgetPrevFocus(ew);
     539             :         else
     540           0 :             GWidgetNextFocus(ew);
     541           0 :         handled = true;
     542             :     }
     543             :     /* Return activates the default button (if there is one) */
     544           0 :     else if ( !handled && (event->u.chr.keysym==GK_Return || event->u.chr.keysym==GK_KP_Enter) &&
     545           0 :             topd->gdef!=NULL ) {
     546           0 :         sub.type = et_controlevent;
     547           0 :         sub.w = topd->gdef->base;
     548           0 :         sub.u.control.subtype = et_buttonactivate;
     549           0 :         sub.u.control.g = topd->gdef;
     550           0 :         sub.u.control.u.button.clicks = 0;
     551           0 :         if ( topd->gdef->handle_controlevent != NULL )
     552           0 :             (topd->gdef->handle_controlevent)(topd->gdef,&sub);
     553             :         else
     554           0 :             GDrawPostEvent(&sub);
     555             :     }
     556             :     /* Escape activates the cancel button (if there is one) */
     557             :     /*  (On the mac, Command-. has that meaning) */
     558           0 :     else if ( !handled && topd->gcancel!=NULL &&
     559           0 :             (event->u.chr.keysym==GK_Escape ||
     560           0 :              ((GMenuMask()&ksm_cmdmacosx) &&
     561           0 :               (event->u.chr.state&GMenuMask())==ksm_cmdmacosx &&
     562           0 :               event->u.chr.keysym=='.'))) {
     563           0 :         sub.type = et_controlevent;
     564           0 :         sub.w = topd->gcancel->base;
     565           0 :         sub.u.control.subtype = et_buttonactivate;
     566           0 :         sub.u.control.g = topd->gcancel;
     567           0 :         sub.u.control.u.button.clicks = 0;
     568           0 :         if ( topd->gcancel->handle_controlevent != NULL )
     569           0 :             (topd->gcancel->handle_controlevent)(topd->gcancel,&sub);
     570             :         else
     571           0 :             GDrawPostEvent(&sub);
     572             :     }
     573           0 : return( handled );
     574             : }
     575             : 
     576           0 : static int GiveToAll(GContainerD *wd, GEvent *event) {
     577             :     GGadget *g;
     578             :     GContainerD *sub;
     579             : 
     580           0 :     if ( wd!=NULL && wd->iscontainer ) {
     581           0 :         for ( g=wd->gadgets; g!=NULL; g=g->prev )
     582           0 :             if ( g->funcs->handle_mouse!=NULL )
     583           0 :                 (g->funcs->handle_mouse)(g,event);
     584           0 :         for ( sub = (GContainerD *) (wd->widgets); sub!=NULL;
     585           0 :                 sub=(GContainerD *) (sub->next) )
     586           0 :             GiveToAll(sub,event);
     587             :     }
     588           0 :     if ( wd!=NULL ) {
     589           0 :         if ( wd->e_h!=NULL )
     590           0 :             (wd->e_h)(wd->w,event);
     591             :     } else {
     592           0 :         if ( wd->w->eh!=NULL )
     593           0 :             (wd->w->eh)(wd->w,event);
     594             :     }
     595           0 : return( true );
     596             : }
     597             : 
     598           0 : static void ManagePalettesVis(GTopLevelD *td, int is_visible ) {
     599             :     GTopLevelD *palette;
     600             : 
     601           0 :     if ( td->w!=last_paletted_focus_window )
     602           0 : return;
     603           0 :     for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
     604           0 :         if ( is_visible && palette->w->visible_request )
     605           0 :             GDrawSetVisible(palette->w,true);
     606           0 :         else if ( !is_visible && palette->w->visible_request ) {
     607           0 :             GDrawSetVisible(palette->w,false);
     608           0 :             palette->w->visible_request = true;
     609             :         }
     610             :     }
     611             : }
     612             : 
     613             : static GTopLevelD *oldtd = NULL;
     614             : static GGadget *oldgfocus = NULL;
     615             : 
     616           0 : static int _GWidget_TopLevel_eh(GWindow gw, GEvent *event) {
     617             :     GTopLevelD *td;
     618             :     int ret;
     619             : 
     620           0 :     if ( !GDrawNativeWindowExists(NULL,event->native_window) )
     621           0 : return( true );
     622             : 
     623           0 :     td = (GTopLevelD *) (gw->widget_data);
     624           0 :     if ( td==NULL )             /* Dying */
     625           0 : return( true );
     626             : 
     627           0 :     GGadgetPopupExternalEvent(event);
     628           0 :     if ( event->type==et_focus ) {
     629             :         
     630           0 :         if ( event->u.focus.gained_focus ) {
     631           0 :             if ( gw->is_toplevel && !gw->is_popup && !gw->is_dying ) {
     632           0 :                 if ( last_input_window!=gw )
     633           0 :                     previous_focus_window = last_input_window;
     634           0 :                 current_focus_window = gw;
     635             :             }
     636           0 :         } else if ( current_focus_window==gw ) {
     637           0 :             current_focus_window = NULL;
     638             :         }
     639           0 :         if ( !td->ispalette && gw->is_visible && event->u.focus.gained_focus && !gw->is_dying ) {
     640           0 :             GWindow dlg = GDrawGetRedirectWindow(NULL);
     641           0 :             if ( dlg==NULL || dlg==gw ) {
     642             :                 /* If top level window loses the focus all its palettes go invisible */
     643             :                 /* if it gains focus then all palettes that are supposed to be vis */
     644             :                 /*  become visible */
     645             :                 /* But not if we've got an active dialog */
     646             :                 GTopLevelD *palette;
     647           0 :                 if ( last_paletted_focus_window!=NULL && !last_paletted_focus_window->is_dying ) {
     648           0 :                     GTopLevelD *lpfw_td = (GTopLevelD *) (last_paletted_focus_window->widget_data);
     649           0 :                     for ( palette=lpfw_td->palettes; palette!=NULL; palette = palette->nextp ) {
     650           0 :                         if ( !palette->w->is_visible && palette->w->visible_request ) {
     651           0 :                             GDrawSetVisible(palette->w,false);
     652           0 :                             palette->w->visible_request = true;
     653             :                         }
     654             :                     }
     655             :                 }
     656           0 :                 for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
     657           0 :                     if ( !palette->w->is_visible && palette->w->visible_request )
     658           0 :                         GDrawSetVisible(palette->w,true);
     659             :                 }
     660           0 :                 last_paletted_focus_window = gw;
     661             :             }
     662             :         }
     663           0 :         if ( !gw->is_dying && td->gfocus!=NULL && td->gfocus->funcs->handle_focus!=NULL ) {
     664           0 :  { oldtd = td; oldgfocus = td->gfocus; }     /* Debug!!!! */
     665           0 :             (td->gfocus->funcs->handle_focus)(td->gfocus,event);
     666           0 :         } else if ( !gw->is_dying && td->wfocus!=NULL ) {
     667           0 :             if ( td->wfocus->widget_data!=NULL ) {
     668           0 :                 if ( td->wfocus->widget_data->e_h!=NULL )
     669           0 :                     (td->wfocus->widget_data->e_h)(td->wfocus,event);
     670           0 :             } else if ( td->wfocus->eh!=NULL )
     671           0 :                 (td->wfocus->eh)(td->wfocus,event);
     672             :         }
     673           0 :         if ( !gw->is_dying && td->e_h!=NULL )
     674           0 :             (td->e_h)(gw,event);
     675           0 : return( true );
     676           0 :     } else if ( !gw->is_dying && event->type == et_crossing ) {
     677           0 :         GiveToAll((GContainerD *) td,event);
     678           0 : return( true );
     679           0 :     } else if ( event->type == et_char || event->type == et_charup ) {
     680           0 : return( _GWidget_TopLevel_Key(gw,gw,event));
     681           0 :     } else if ( !gw->is_dying && event->type == et_resize ) {
     682             :         GRect r;
     683           0 :         if ( td->gmenubar!=NULL ) {
     684           0 :             GGadgetGetSize(td->gmenubar,&r);
     685           0 :             GGadgetResize(td->gmenubar,event->u.resize.size.width,r.height);
     686           0 :             GGadgetRedraw(td->gmenubar);
     687             :         } /* status line, toolbar, etc. */
     688           0 :         if ( td->palettes!=NULL && event->u.resize.moved ) {
     689             :             GTopLevelD *palette;
     690           0 :             for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
     691           0 :                 if ( !broken_palettes || !palette->positioned_yet ) {
     692           0 :                     int x = gw->pos.x + palette->owner_off_x,
     693           0 :                         y = gw->pos.y + palette->owner_off_y;
     694           0 :                     if ( x<0 ) x=0;
     695           0 :                     if ( y<0 ) y=0;
     696           0 :                     if ( x+palette->w->pos.width>GDrawGetRoot(NULL)->pos.width )
     697           0 :                         x = GDrawGetRoot(NULL)->pos.width-palette->w->pos.width;
     698           0 :                     if ( y+palette->w->pos.height>GDrawGetRoot(NULL)->pos.height )
     699           0 :                         y = GDrawGetRoot(NULL)->pos.height-palette->w->pos.height;
     700           0 :                     ++palette->programmove;
     701           0 :                     if ( gw->is_visible )
     702           0 :                         GDrawTrueMove(palette->w, x, y);
     703             :                     else
     704           0 :                         GDrawMove(palette->w, x, y);
     705           0 :                     palette->positioned_yet = true;
     706             :                 }
     707             :             }
     708             :         }
     709           0 :         if ( td->ispalette ) {
     710           0 :             if ( td->programmove>0 )
     711           0 :                 --td->programmove;
     712             :             else {
     713           0 :                 td->owner_off_x = gw->pos.x - td->owner->w->pos.x;
     714           0 :                 td->owner_off_y = gw->pos.y - td->owner->w->pos.y;
     715             :             }
     716             :         }
     717           0 :     } else if ( event->type == et_close && td->ispalette ) {
     718           0 :         GDrawSetVisible(gw,false);
     719           0 : return( true );
     720           0 :     } else if ( !gw->is_dying && event->type == et_visibility ) {
     721           0 :         if ( broken_palettes )
     722             :             /* Do Nothing */;
     723           0 :         else if ( td->ispalette && event->u.visibility.state!=vs_unobscured ) {
     724           0 :             if ( !GDrawIsAbove(gw,td->owner->w))
     725           0 :                 GDrawRaiseAbove(gw,td->owner->w);
     726             :         }
     727           0 :     } else if ( !gw->is_dying && event->type == et_map && !td->ispalette ) {
     728             :         /* If top level window goes invisible all its palettes follow */
     729             :         /* if it goes visible then all palettes that are supposed to be vis */
     730             :         /*  follow */
     731           0 :         ManagePalettesVis(td, event->u.map.is_visible );
     732             :     }
     733           0 :     if ( event->type == et_destroy ) {
     734           0 :         if ( td->palettes!=NULL ) {
     735             :             struct gtopleveldata *palettes, *next;
     736           0 :             for ( palettes=td->palettes; palettes!=NULL; palettes = next ) {
     737           0 :                 next = palettes->nextp;
     738           0 :                 GDrawDestroyWindow(palettes->w);
     739             :             }
     740             :             /* Palettes must die before our widget data are freed */
     741           0 :             GDrawSync(GDrawGetDisplayOfWindow(gw));
     742           0 :             GDrawProcessPendingEvents(GDrawGetDisplayOfWindow(gw));
     743             :         }
     744             :     }
     745           0 :     ret = _GWidget_Container_eh(gw,event);
     746           0 :     if ( event->type == et_destroy ) {
     747           0 :         if ( gw==current_focus_window )
     748           0 :             current_focus_window = NULL;
     749           0 :         if ( gw==previous_focus_window )
     750           0 :             previous_focus_window = NULL;
     751           0 :         if ( gw==last_input_window )
     752           0 :             last_input_window = NULL;
     753           0 :         if ( gw==last_paletted_focus_window )
     754           0 :             last_paletted_focus_window = NULL;
     755           0 :         ret = true;
     756             :     }
     757           0 : return( ret );
     758             : }
     759             : 
     760             : static struct wfuncs _gwidget_container_funcs;
     761             : static struct wfuncs _gwidget_toplevel_funcs;
     762             : 
     763           0 : static void MakeContainerWidget(GWindow gw) {
     764             :     struct gwidgetcontainerdata *gd;
     765             : 
     766           0 :     if ( gw->widget_data!=NULL )
     767           0 :         GDrawIError( "Attempt to make a window into a widget twice");
     768           0 :     if ( !widgets_initted )
     769           0 :         gwidget_init();
     770           0 :     if ( gw->parent==NULL || gw->is_toplevel )
     771           0 :         gd = calloc(1,sizeof(struct gtopleveldata));
     772             :     else
     773           0 :         gd = calloc(1,sizeof(struct gwidgetcontainerdata));
     774           0 :     gw->widget_data = (struct gwidgetdata *) gd;
     775           0 :     gd->w = gw;
     776           0 :     gd->e_h = gw->eh;
     777           0 :     gw->eh = _GWidget_Container_eh;
     778           0 :     gd->enabled = true;
     779           0 :     gd->iscontainer = true;
     780           0 :     gd->funcs = &_gwidget_container_funcs;
     781           0 :     if ( gw->parent!=NULL && !gw->is_toplevel ) {
     782           0 :         if ( gw->parent->widget_data==NULL )
     783           0 :             MakeContainerWidget(gw->parent);
     784           0 :         if ( !gw->parent->widget_data->iscontainer )
     785           0 :             GDrawIError( "Attempt to add a widget to something which is not a container");
     786           0 :         gd->next = ((struct gwidgetcontainerdata *) (gw->parent->widget_data))->widgets;
     787           0 :         ((struct gwidgetcontainerdata *) (gw->parent->widget_data))->widgets =
     788             :                 (struct gwidgetdata *) gd;
     789             :     } else {
     790             :         struct gtopleveldata *topd;
     791           0 :         topd = (struct gtopleveldata *) gd;
     792           0 :         gd->funcs = &_gwidget_toplevel_funcs;
     793           0 :         gw->eh = _GWidget_TopLevel_eh;
     794           0 :         topd->handle_key = _GWidget_TopLevel_Key;
     795           0 :         topd->istoplevel = true;
     796             :     }
     797           0 : }
     798             : 
     799           0 : void _GWidget_AddGGadget(GWindow gw,GGadget *g) {
     800             :     struct gwidgetcontainerdata *gd;
     801             : 
     802           0 :     if ( gw->widget_data==NULL )
     803           0 :         MakeContainerWidget(gw);
     804           0 :     gd = (struct gwidgetcontainerdata *) (gw->widget_data);
     805           0 :     if ( !gd->iscontainer )
     806           0 :         GDrawIError( "Attempt to add a gadget to something which is not a container");
     807           0 :     g->prev = gd->gadgets;
     808           0 :     gd->gadgets = g;
     809           0 :     if ( g->base!=NULL )
     810           0 :         GDrawIError( "Attempt to add a gadget to two widgets" );
     811           0 :     g->base = gw;
     812           0 : }
     813             : 
     814           0 : void _GWidget_RemoveGadget(GGadget *g) {
     815             :     struct gwidgetcontainerdata *gd;
     816             :     GTopLevelD *td;
     817           0 :     GWindow gw = g->base;
     818             :     GGadget *next;
     819             : 
     820           0 :     if ( gw==NULL )
     821           0 : return;
     822             : 
     823           0 :     gd = (struct gwidgetcontainerdata *) (gw->widget_data);
     824           0 :     if ( gd==NULL || !gd->iscontainer )
     825           0 :         GDrawIError( "Attempt to remove a gadget to something which is not a container");
     826           0 :     if ( gd->gadgets==g )
     827           0 :         gd->gadgets = g->prev;
     828             :     else {
     829           0 :         for ( next = gd->gadgets; next!=NULL && next->prev!=g; next = next->prev );
     830           0 :         if ( next==NULL )
     831           0 :             GDrawIError( "Attempt to remove a gadget which is not in the gadget list" );
     832             :         else
     833           0 :             next->prev = g->prev;
     834             :     }
     835           0 :     if ( gd->grabgadget == g ) gd->grabgadget = NULL;
     836           0 :     g->prev = NULL;
     837           0 :     g->base = NULL;
     838             : 
     839           0 :     while ( gw->parent!=NULL && !gw->is_toplevel ) gw = gw->parent;
     840           0 :     td = (GTopLevelD *) (gw->widget_data);
     841           0 :     if ( td->gdef == g ) td->gdef = NULL;
     842           0 :     if ( td->gcancel == g ) td->gcancel = NULL;
     843           0 :     if ( td->gfocus == g ) td->gfocus = NULL;
     844             : }
     845             : 
     846           0 : void _GWidget_SetDefaultButton(GGadget *g) {
     847           0 :     struct gtopleveldata *gd=NULL;
     848           0 :     GWindow gw = g->base;
     849             : 
     850           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     851           0 :     if ( gw!=NULL )
     852           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     853           0 :     if ( gd==NULL || !gd->istoplevel )
     854           0 :         GDrawIError( "This gadget isn't in a top level widget, can't be a default button" );
     855             :     else
     856           0 :         gd->gdef = g;
     857           0 : }
     858             : 
     859             : /* The previous function assumes everything is set up properly. This one doesn't */
     860             : /*  it's for when you've got two buttons which might be default and you toggle */
     861             : /*  between them. It lets each button know if it's default, and then redraws */
     862             : /*  both */
     863           0 : void _GWidget_MakeDefaultButton(GGadget *g) {
     864           0 :     struct gtopleveldata *gd=NULL;
     865           0 :     GWindow gw = g->base;
     866             : 
     867           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     868           0 :     if ( gw!=NULL )
     869           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     870           0 :     if ( gd==NULL || !gd->istoplevel )
     871           0 :         GDrawIError( "This gadget isn't in a top level widget, can't be a default button" );
     872           0 :     else if ( gd->gdef!=g ) {
     873           0 :         _GButton_SetDefault(gd->gdef,false);
     874           0 :         gd->gdef = g;
     875           0 :         _GButton_SetDefault(g,true);
     876             :     }
     877           0 : }
     878             : 
     879           0 : void _GWidget_SetCancelButton(GGadget *g) {
     880           0 :     struct gtopleveldata *gd=NULL;
     881           0 :     GWindow gw = g->base;
     882             : 
     883           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     884           0 :     if ( gw!=NULL )
     885           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     886           0 :     if ( gd==NULL || !gd->istoplevel )
     887           0 :         GDrawIError( "This gadget isn't in a top level widget, can't be a cancel button" );
     888             :     else
     889           0 :         gd->gcancel = g;
     890           0 : }
     891             : 
     892           0 : void _GWidget_SetMenuBar(GGadget *g) {
     893           0 :     struct gtopleveldata *gd=NULL;
     894           0 :     GWindow gw = g->base;
     895             : 
     896           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     897           0 :     if ( gw!=NULL )
     898           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     899           0 :     if ( gd==NULL || !gd->istoplevel )
     900           0 :         GDrawIError( "This gadget isn't in a top level widget, can't be a menubar" );
     901             :     else
     902           0 :         gd->gmenubar = g;
     903           0 : }
     904             : 
     905           0 : void _GWidget_SetPopupOwner(GGadget *g) {
     906           0 :     struct gtopleveldata *gd=NULL;
     907           0 :     GWindow gw = g->base;
     908             : 
     909           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     910           0 :     if ( gw!=NULL )
     911           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     912           0 :     if ( gd==NULL || !gd->istoplevel )
     913           0 :         GDrawIError( "This gadget isn't in a top level widget, can't have a popup" );
     914             :     else
     915           0 :         gd->popupowner = g;
     916           0 : }
     917             : 
     918           0 : void _GWidget_ClearPopupOwner(GGadget *g) {
     919           0 :     struct gtopleveldata *gd=NULL;
     920           0 :     GWindow gw = g->base;
     921             : 
     922           0 :     if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
     923           0 :     if ( gw!=NULL )
     924           0 :         gd = (struct gtopleveldata *) (gw->widget_data);
     925           0 :     if ( gd==NULL || !gd->istoplevel )
     926           0 :         GDrawIError( "This gadget isn't in a top level widget, can't have a popup" );
     927             :     else
     928           0 :         gd->popupowner = NULL;
     929           0 : }
     930             : 
     931           0 : void _GWidget_SetGrabGadget(GGadget *g) {
     932           0 :     struct gwidgetcontainerdata *gd=NULL;
     933           0 :     GWindow gw = g->base;
     934             : 
     935           0 :     if ( gw!=NULL )
     936           0 :         gd = (struct gwidgetcontainerdata *) (gw->widget_data);
     937           0 :     if ( gd==NULL || !gd->iscontainer )
     938           0 :         GDrawIError( "This gadget isn't in a container, can't be a grab gadget" );
     939             :     else
     940           0 :         gd->grabgadget = g;
     941           0 : }
     942             : 
     943           0 : void _GWidget_ClearGrabGadget(GGadget *g) {
     944           0 :     struct gwidgetcontainerdata *gd=NULL;
     945           0 :     GWindow gw = g->base;
     946             : 
     947           0 :     if ( gw!=NULL )
     948           0 :         gd = (struct gwidgetcontainerdata *) (gw->widget_data);
     949           0 :     if ( gd==NULL || !gd->iscontainer )
     950           0 :         GDrawIError( "This gadget isn't in a container, can't be a grab gadget" );
     951             :     else
     952           0 :         gd->grabgadget = NULL;
     953           0 : }
     954             : 
     955           0 : GWindow GWidgetCreateTopWindow(GDisplay *gdisp, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
     956           0 :     GWindow gw = GDrawCreateTopWindow(gdisp,pos,eh,user_data,wattrs);
     957           0 :     MakeContainerWidget(gw);
     958           0 : return( gw );
     959             : }
     960             : 
     961           0 : GWindow GWidgetCreateSubWindow(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
     962           0 :     GWindow gw = GDrawCreateSubWindow(w,pos,eh,user_data,wattrs);
     963           0 :     MakeContainerWidget(gw);
     964           0 : return( gw );
     965             : }
     966             : 
     967             : /* Palettes follow their owners when the owner moves around the screen */
     968             : /*  Palettes go invisible when the owner does, and become visible again when it does */
     969             : /*  Palettes are always on top of their owner */
     970             : /*  Palettes go invisible when the owner loses focus, and become visible when it gains focus */
     971           0 : GWindow GWidgetCreatePalette(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
     972             :     GWindow gw;
     973             :     GPoint pt, base;
     974             :     GRect newpos, ownerpos, screensize;
     975             :     struct gtopleveldata *gd, *od;
     976             :     GWindow root;
     977             : 
     978           0 :     if ( !w->is_toplevel )
     979           0 : return( false );
     980             : 
     981           0 :     pt.x = pos->x; pt.y = pos->y;
     982           0 :     root = GDrawGetRoot(w->display);
     983           0 :     GDrawGetSize(w,&ownerpos);
     984           0 :     GDrawGetSize(root,&screensize);
     985           0 :     GDrawTranslateCoordinates(w,root,&pt);
     986           0 :     base.x = base.y = 0;
     987           0 :     GDrawTranslateCoordinates(w,root,&base);
     988           0 :     if ( pt.x<0 ) {
     989           0 :         if ( base.x+ownerpos.width+20+pos->width+20 > screensize.width )
     990           0 :             pt.x=0;
     991             :         else
     992           0 :             pt.x = base.x+ownerpos.width+20;
     993             :     }
     994           0 :     if ( pt.y<0 ) pt.y=0;
     995           0 :     if ( pt.x+pos->width>root->pos.width )
     996           0 :         pt.x = root->pos.width-pos->width;
     997           0 :     if ( pt.y+pos->height>root->pos.height )
     998           0 :         pt.y = root->pos.height-pos->height;
     999             : 
    1000           0 :     newpos.x = pt.x; newpos.y = pt.y; newpos.width = pos->width; newpos.height = pos->height;
    1001           0 :     wattrs->event_masks |= (1<<et_visibility);
    1002           0 :     if ( !(wattrs->mask&wam_transient)) {
    1003           0 :         wattrs->mask |= wam_transient;
    1004           0 :         wattrs->transient = GWidgetGetTopWidget(w);
    1005             :     }
    1006           0 :     if ( broken_palettes ) {
    1007           0 :         wattrs->mask |= wam_positioned;
    1008           0 :         wattrs->positioned = true;
    1009             :     }
    1010           0 :     gw = GDrawCreateTopWindow(w->display,&newpos,eh,user_data,wattrs);
    1011           0 :     MakeContainerWidget(gw);
    1012           0 :     if ( w->widget_data==NULL )
    1013           0 :         MakeContainerWidget(w);
    1014           0 :     od = (struct gtopleveldata *) (w->widget_data);
    1015           0 :     gd = (struct gtopleveldata *) (gw->widget_data);
    1016           0 :     gd->nextp = od->palettes;
    1017           0 :     gd->owner = od;
    1018           0 :     od->palettes = gd;
    1019           0 :     gd->ispalette = true;
    1020           0 :     gd->owner_off_x = pos->x; gd->owner_off_y = pos->y;
    1021           0 : return( gw );
    1022             : }
    1023             : 
    1024           0 : void GWidgetRequestVisiblePalette(GWindow palette,int visible) {
    1025           0 :     GTopLevelD *td = (GTopLevelD *) (palette->widget_data);
    1026             : 
    1027           0 :     if ( td->owner!=NULL ) {
    1028           0 :         palette->visible_request = visible;
    1029           0 :         if ( td->owner->w == last_paletted_focus_window )
    1030           0 :             GDrawSetVisible(palette,visible);
    1031             :     }
    1032           0 : }
    1033             : 
    1034           0 : GGadget *GWidgetGetControl(GWindow gw, int cid) {
    1035             :     GGadget *gadget;
    1036           0 :     GContainerD *gd = (GContainerD *) (gw->widget_data);
    1037             :     GWidgetD *widg;
    1038             : 
    1039           0 :     if ( gd==NULL || !gd->iscontainer )
    1040           0 : return( NULL );
    1041           0 :     for ( gadget = gd->gadgets; gadget!=NULL ; gadget=gadget->prev ) {
    1042           0 :         if ( gadget->cid == cid )
    1043           0 : return( gadget );
    1044             :     }
    1045           0 :     for ( widg = gd->widgets; widg!=NULL; widg = widg->next ) {
    1046           0 :         if ( widg->iscontainer ) {
    1047           0 :             gadget = GWidgetGetControl(widg->w,cid);
    1048           0 :             if ( gadget!=NULL )
    1049           0 : return( gadget );
    1050             :         }
    1051             :     }
    1052           0 : return( NULL );
    1053             : }
    1054             : 
    1055           0 : GGadget *_GWidgetGetGadgets(GWindow gw) {
    1056             :     GContainerD *gd;
    1057             : 
    1058           0 :     if ( gw==NULL )
    1059           0 : return( NULL );
    1060             : 
    1061           0 :     gd = (GContainerD *) (gw->widget_data);
    1062             : 
    1063           0 :     if ( gd==NULL || !gd->iscontainer )
    1064           0 : return( NULL );
    1065             : 
    1066           0 : return( gd->gadgets );
    1067             : }
    1068             : 
    1069           0 : GWindow GWidgetGetParent(GWindow gw) {
    1070             : 
    1071           0 : return( gw->parent );
    1072             : }
    1073             : 
    1074           0 : GWindow GWidgetGetTopWidget(GWindow gw) {
    1075             : 
    1076           0 :     for ( ; gw->parent!=NULL && !gw->is_toplevel; gw = gw->parent );
    1077           0 : return( gw );
    1078             : }
    1079             : 
    1080           0 : GDrawEH GWidgetGetEH(GWindow gw) {
    1081           0 :     if ( gw->widget_data==NULL )
    1082           0 : return( gw->eh );
    1083             :     else
    1084           0 : return( gw->widget_data->e_h );
    1085             : }
    1086             : 
    1087           0 : void GWidgetSetEH(GWindow gw, GDrawEH e_h ) {
    1088           0 :     if ( gw->widget_data==NULL )
    1089           0 :         gw->eh = e_h;
    1090             :     else
    1091           0 :         gw->widget_data->e_h = e_h;
    1092           0 : }
    1093             : 
    1094           0 : void GWidgetHidePalettes(void) {
    1095             :     GTopLevelD *td, *palette;
    1096             : 
    1097           0 :     if ( last_paletted_focus_window==NULL )
    1098           0 : return;
    1099           0 :     td = (GTopLevelD *) (last_paletted_focus_window->widget_data);
    1100           0 :     for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
    1101           0 :         if ( palette->w->visible_request ) {
    1102           0 :             GDrawSetVisible(palette->w,false);
    1103           0 :             palette->w->visible_request = true;
    1104             :         }
    1105             :     }
    1106             : }
    1107             : 
    1108           0 : void GWidgetReparentWindow(GWindow child,GWindow newparent, int x,int y) {
    1109           0 :     if ( !child->is_toplevel ) {
    1110             :         GWindow oldparent, gadgetparent;
    1111           0 :         for ( oldparent = child; oldparent->parent!=NULL && !oldparent->is_toplevel; oldparent=oldparent->parent );
    1112           0 :         if ( oldparent!=child ) {
    1113           0 :             GTopLevelD *td = (GTopLevelD *) (oldparent->widget_data);
    1114           0 :             if ( td->gfocus!=NULL ) {
    1115           0 :                 for ( gadgetparent = td->gfocus->base;
    1116           0 :                         gadgetparent!=child &&
    1117           0 :                         gadgetparent!=NULL; gadgetparent = gadgetparent->parent );
    1118           0 :                 if ( gadgetparent==child )
    1119           0 :                     td->gfocus = NULL;
    1120             :             }
    1121             :         }
    1122             :     }
    1123           0 :     GDrawReparentWindow(child,newparent,x,y);
    1124           0 : }
    1125             : 
    1126           0 : GIC *GWidgetCreateInputContext(GWindow w,enum gic_style def_style) {
    1127           0 :     GWidgetD *wd = (GWidgetD *) (w->widget_data);
    1128             : 
    1129           0 :     if ( wd->gic==NULL )
    1130           0 :         wd->gic = GDrawCreateInputContext(w,def_style);
    1131           0 : return( wd->gic );
    1132             : }
    1133             :     
    1134           0 : GIC *GWidgetGetInputContext(GWindow w) {
    1135           0 :     GWidgetD *wd = (GWidgetD *) (w->widget_data);
    1136           0 : return( wd->gic );
    1137             : }
    1138             : 
    1139           0 : void GWidgetFlowGadgets(GWindow gw) {
    1140             :     GGadget *gadget;
    1141           0 :     GContainerD *gd = (GContainerD *) (gw->widget_data);
    1142             : 
    1143           0 :     if ( gd==NULL )
    1144           0 : return;
    1145             : 
    1146           0 :     gadget = gd->gadgets;
    1147           0 :     if ( gadget!=NULL ) {
    1148           0 :         while ( gadget->prev!=NULL )
    1149           0 :             gadget=gadget->prev;
    1150             :     }
    1151           0 :     if ( gadget != NULL && GGadgetFillsWindow(gadget)) {
    1152             :         GRect wsize;
    1153           0 :         GDrawGetSize(gw, &wsize);
    1154             : 
    1155             :         /* Make any offset simmetrical */
    1156           0 :         if (wsize.width >= 2*gadget->r.x) wsize.width -= 2*gadget->r.x;
    1157           0 :         else wsize.width = 0;
    1158             :         
    1159           0 :         if (wsize.height >= 2*gadget->r.y) wsize.height -= 2*gadget->r.y;
    1160           0 :         else wsize.height = 0;
    1161             :         
    1162           0 :         GGadgetResize(gadget,wsize.width,wsize.height);
    1163           0 :         GDrawRequestExpose(gw,NULL,false);
    1164             :     }
    1165             : }
    1166             : 
    1167           0 : void GWidgetToDesiredSize(GWindow gw) {
    1168             :     GGadget *gadget;
    1169           0 :     GContainerD *gd = (GContainerD *) (gw->widget_data);
    1170             : 
    1171           0 :     if ( gd==NULL )
    1172           0 : return;
    1173             : 
    1174           0 :     gadget = gd->gadgets;
    1175           0 :     if ( gadget!=NULL ) {
    1176           0 :         while ( gadget->prev!=NULL )
    1177           0 :             gadget=gadget->prev;
    1178             :     }
    1179           0 :     if ( gadget != NULL && GGadgetFillsWindow(gadget))
    1180           0 :         GHVBoxFitWindow(gadget);
    1181             : }

Generated by: LCOV version 1.10