Home | History | Annotate | Line # | Download | only in src
      1 /***********************************************************
      2 Copyright (c) 1993, Oracle and/or its affiliates.
      3 
      4 Permission is hereby granted, free of charge, to any person obtaining a
      5 copy of this software and associated documentation files (the "Software"),
      6 to deal in the Software without restriction, including without limitation
      7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 and/or sell copies of the Software, and to permit persons to whom the
      9 Software is furnished to do so, subject to the following conditions:
     10 
     11 The above copyright notice and this permission notice (including the next
     12 paragraph) shall be included in all copies or substantial portions of the
     13 Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 DEALINGS IN THE SOFTWARE.
     22 
     23 Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
     24 
     25                         All Rights Reserved
     26 
     27 Permission to use, copy, modify, and distribute this software and its
     28 documentation for any purpose and without fee is hereby granted,
     29 provided that the above copyright notice appear in all copies and that
     30 both that copyright notice and this permission notice appear in
     31 supporting documentation, and that the name of Digital not be
     32 used in advertising or publicity pertaining to distribution of the
     33 software without specific, written prior permission.
     34 
     35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     41 SOFTWARE.
     42 
     43 ******************************************************************/
     44 
     45 /*
     46 
     47 Copyright 1987, 1988, 1990, 1994, 1998  The Open Group
     48 
     49 Permission to use, copy, modify, distribute, and sell this software and its
     50 documentation for any purpose is hereby granted without fee, provided that
     51 the above copyright notice appear in all copies and that both that
     52 copyright notice and this permission notice appear in supporting
     53 documentation.
     54 
     55 The above copyright notice and this permission notice shall be included in
     56 all copies or substantial portions of the Software.
     57 
     58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     64 
     65 Except as contained in this notice, the name of The Open Group shall not be
     66 used in advertising or otherwise to promote the sale, use or other dealings
     67 in this Software without prior written authorization from The Open Group.
     68 
     69 */
     70 
     71 #ifdef HAVE_CONFIG_H
     72 #include <config.h>
     73 #endif
     74 #include "IntrinsicI.h"
     75 
     76 typedef struct _GCrec {
     77     unsigned char screen;       /* Screen for GC */
     78     unsigned char depth;        /* Depth for GC */
     79     char dashes;                /* Dashes value */
     80     Pixmap clip_mask;           /* Clip_mask value */
     81     Cardinal ref_count;         /* # of shareholders */
     82     GC gc;                      /* The GC itself. */
     83     XtGCMask dynamic_mask;      /* Writable values */
     84     XtGCMask unused_mask;       /* Unused values */
     85     struct _GCrec *next;        /* Next GC for this widgetkind. */
     86 } GCrec, *GCptr;
     87 
     88 #define GCVAL(bit,mask,val,default) ((bit&mask) ? val : default)
     89 
     90 #define CHECK(bit,comp,default) \
     91     if ((checkMask & bit) && \
     92         (GCVAL(bit,valueMask,v->comp,default) != gcv.comp)) return False
     93 
     94 #define ALLGCVALS (GCFunction | GCPlaneMask | GCForeground | \
     95                    GCBackground | GCLineWidth | GCLineStyle | \
     96                    GCCapStyle | GCJoinStyle | GCFillStyle | \
     97                    GCFillRule | GCTile | GCStipple | \
     98                    GCTileStipXOrigin | GCTileStipYOrigin | \
     99                    GCFont | GCSubwindowMode | GCGraphicsExposures | \
    100                    GCClipXOrigin | GCClipYOrigin | GCDashOffset | \
    101                    GCArcMode)
    102 
    103 static Bool
    104 Matches(Display *dpy,
    105         GCptr ptr,
    106         register XtGCMask valueMask,
    107         register XGCValues *v,
    108         XtGCMask readOnlyMask,
    109         XtGCMask dynamicMask)
    110 {
    111     XGCValues gcv;
    112     register XtGCMask checkMask;
    113 
    114     if (readOnlyMask & ptr->dynamic_mask)
    115         return False;
    116     if (((ptr->dynamic_mask | ptr->unused_mask) & dynamicMask) != dynamicMask)
    117         return False;
    118     if (!XGetGCValues(dpy, ptr->gc, ALLGCVALS, &gcv))
    119         return False;
    120     checkMask = readOnlyMask & ~ptr->unused_mask;
    121     CHECK(GCForeground, foreground, 0);
    122     CHECK(GCBackground, background, 1);
    123     CHECK(GCFont, font, ~0UL);
    124     CHECK(GCFillStyle, fill_style, FillSolid);
    125     CHECK(GCLineWidth, line_width, 0);
    126     CHECK(GCFunction, function, GXcopy);
    127     CHECK(GCGraphicsExposures, graphics_exposures, True);
    128     CHECK(GCTile, tile, ~0UL);
    129     CHECK(GCSubwindowMode, subwindow_mode, ClipByChildren);
    130     CHECK(GCPlaneMask, plane_mask, AllPlanes);
    131     CHECK(GCLineStyle, line_style, LineSolid);
    132     CHECK(GCCapStyle, cap_style, CapButt);
    133     CHECK(GCJoinStyle, join_style, JoinMiter);
    134     CHECK(GCFillRule, fill_rule, EvenOddRule);
    135     CHECK(GCArcMode, arc_mode, ArcPieSlice);
    136     CHECK(GCStipple, stipple, ~0UL);
    137     CHECK(GCTileStipXOrigin, ts_x_origin, 0);
    138     CHECK(GCTileStipYOrigin, ts_y_origin, 0);
    139     CHECK(GCClipXOrigin, clip_x_origin, 0);
    140     CHECK(GCClipYOrigin, clip_y_origin, 0);
    141     CHECK(GCDashOffset, dash_offset, 0);
    142     gcv.clip_mask = ptr->clip_mask;
    143     CHECK(GCClipMask, clip_mask, None);
    144     gcv.dashes = ptr->dashes;
    145     CHECK(GCDashList, dashes, 4);
    146     valueMask &= ptr->unused_mask | dynamicMask;
    147     if (valueMask) {
    148         XChangeGC(dpy, ptr->gc, valueMask, v);
    149         if (valueMask & GCDashList)
    150             ptr->dashes = v->dashes;
    151         if (valueMask & GCClipMask)
    152             ptr->clip_mask = v->clip_mask;
    153     }
    154     ptr->unused_mask &= ~(dynamicMask | readOnlyMask);
    155     ptr->dynamic_mask |= dynamicMask;
    156     return True;
    157 }                               /* Matches */
    158 
    159 /* Called by CloseDisplay to free the per-display GC list */
    160 void
    161 _XtGClistFree(Display *dpy, register XtPerDisplay pd)
    162 {
    163     GCptr GClist, next;
    164 
    165     GClist = pd->GClist;
    166     while (GClist) {
    167         next = GClist->next;
    168         XtFree((char *) GClist);
    169         GClist = next;
    170     }
    171     if (pd->pixmap_tab) {
    172         int i;
    173 
    174         for (i = ScreenCount(dpy); --i >= 0;) {
    175             if (pd->pixmap_tab[i])
    176                 XtFree((char *) pd->pixmap_tab[i]);
    177         }
    178         XtFree((char *) pd->pixmap_tab);
    179     }
    180 }
    181 
    182 /*
    183  * Return a GC with the given values and characteristics.
    184  */
    185 
    186 GC
    187 XtAllocateGC(register Widget widget,
    188              Cardinal depth,
    189              XtGCMask valueMask,
    190              XGCValues *values,
    191              XtGCMask dynamicMask,
    192              XtGCMask unusedMask)
    193 {
    194     register GCptr *prev;
    195     register GCptr cur;
    196     Screen *screen;
    197     register Display *dpy;
    198     register XtPerDisplay pd;
    199     Drawable drawable;
    200     Drawable *pixmaps;
    201     XtGCMask readOnlyMask;
    202     GC retval;
    203 
    204     WIDGET_TO_APPCON(widget);
    205 
    206     LOCK_APP(app);
    207     LOCK_PROCESS;
    208     if (!XtIsWidget(widget))
    209         widget = _XtWindowedAncestor(widget);
    210     if (!depth)
    211         depth = widget->core.depth;
    212     screen = XtScreen(widget);
    213     dpy = DisplayOfScreen(screen);
    214     pd = _XtGetPerDisplay(dpy);
    215     unusedMask &= ~valueMask;
    216     readOnlyMask = ~(dynamicMask | unusedMask);
    217 
    218     /* Search for existing GC that matches exactly */
    219     for (prev = &pd->GClist; (cur = *prev); prev = &cur->next) {
    220         if (cur->depth == depth &&
    221             ScreenOfDisplay(dpy, cur->screen) == screen &&
    222             Matches(dpy, cur, valueMask, values, readOnlyMask, dynamicMask)) {
    223             cur->ref_count++;
    224             /* Move this GC to front of list */
    225             *prev = cur->next;
    226             cur->next = pd->GClist;
    227             pd->GClist = cur;
    228             retval = cur->gc;
    229             UNLOCK_PROCESS;
    230             UNLOCK_APP(app);
    231             return retval;
    232         }
    233     }
    234 
    235     /* No matches, have to create a new one */
    236     cur = XtNew(GCrec);
    237     cur->screen = (unsigned char) XScreenNumberOfScreen(screen);
    238     cur->depth = (unsigned char) depth;
    239     cur->ref_count = 1;
    240     cur->dynamic_mask = dynamicMask;
    241     cur->unused_mask = (unusedMask & ~dynamicMask);
    242     cur->dashes = GCVAL(GCDashList, valueMask, values->dashes, 4);
    243     cur->clip_mask = GCVAL(GCClipMask, valueMask, values->clip_mask, None);
    244     drawable = 0;
    245     if (depth == widget->core.depth)
    246         drawable = XtWindow(widget);
    247     if (!drawable && depth == (Cardinal) DefaultDepthOfScreen(screen))
    248         drawable = RootWindowOfScreen(screen);
    249     if (!drawable) {
    250         if (!pd->pixmap_tab) {
    251             int n;
    252 
    253             pd->pixmap_tab = XtMallocArray((Cardinal) ScreenCount(dpy),
    254                                            (Cardinal) sizeof(Drawable *));
    255             for (n = 0; n < ScreenCount(dpy); n++)
    256                 pd->pixmap_tab[n] = NULL;
    257         }
    258         pixmaps = pd->pixmap_tab[cur->screen];
    259         if (!pixmaps) {
    260             int max, n, *depths;
    261 
    262             depths = XListDepths(dpy, cur->screen, &n);
    263             n--;
    264             max = depths[n];
    265             while (n--) {
    266                 if (depths[n] > max)
    267                     max = depths[n];
    268             }
    269             XFree((char *) depths);
    270             pixmaps = (Drawable *) __XtCalloc((unsigned) max, sizeof(Drawable));
    271             pd->pixmap_tab[cur->screen] = pixmaps;
    272         }
    273         drawable = pixmaps[cur->depth - 1];
    274         if (!drawable) {
    275             drawable = XCreatePixmap(dpy, RootWindowOfScreen(screen), 1, 1,
    276                                      cur->depth);
    277             pixmaps[cur->depth - 1] = drawable;
    278         }
    279     }
    280     cur->gc = XCreateGC(dpy, drawable, valueMask, values);
    281     cur->next = pd->GClist;
    282     pd->GClist = cur;
    283     retval = cur->gc;
    284     UNLOCK_PROCESS;
    285     UNLOCK_APP(app);
    286     return retval;
    287 }                               /* XtAllocateGC */
    288 
    289 /*
    290  * Return a read-only GC with the given values.
    291  */
    292 
    293 GC
    294 XtGetGC(register Widget widget, XtGCMask valueMask, XGCValues *values)
    295 {
    296     return XtAllocateGC(widget, 0, valueMask, values, 0, 0);
    297 }                               /* XtGetGC */
    298 
    299 void
    300 XtReleaseGC(Widget widget, register GC gc)
    301 {
    302     register GCptr cur, *prev;
    303     Display *dpy;
    304     XtPerDisplay pd;
    305 
    306     WIDGET_TO_APPCON(widget);
    307 
    308     LOCK_APP(app);
    309     LOCK_PROCESS;
    310     dpy = XtDisplayOfObject(widget);
    311     pd = _XtGetPerDisplay(dpy);
    312 
    313     for (prev = &pd->GClist; (cur = *prev); prev = &cur->next) {
    314         if (cur->gc == gc) {
    315             if (--(cur->ref_count) == 0) {
    316                 *prev = cur->next;
    317                 XFreeGC(dpy, gc);
    318                 XtFree((char *) cur);
    319             }
    320             break;
    321         }
    322     }
    323     UNLOCK_PROCESS;
    324     UNLOCK_APP(app);
    325 }                               /* XtReleaseGC */
    326 
    327 /*  The following interface is broken and supplied only for backwards
    328  *  compatibility.  It will work properly in all cases only if there
    329  *  is exactly 1 Display created by the application.
    330  */
    331 
    332 void
    333 XtDestroyGC(register GC gc)
    334 {
    335     GCptr cur, *prev;
    336     XtAppContext app;
    337 
    338     LOCK_PROCESS;
    339     app = _XtGetProcessContext()->appContextList;
    340     /* This is awful; we have to search through all the lists
    341        to find the GC. */
    342     for (; app; app = app->next) {
    343         int i;
    344 
    345         for (i = app->count; i;) {
    346             Display *dpy = app->list[--i];
    347             XtPerDisplay pd = _XtGetPerDisplay(dpy);
    348 
    349             for (prev = &pd->GClist; (cur = *prev); prev = &cur->next) {
    350                 if (cur->gc == gc) {
    351                     if (--(cur->ref_count) == 0) {
    352                         *prev = cur->next;
    353                         XFreeGC(dpy, gc);
    354                         XtFree((char *) cur);
    355                     }
    356                     UNLOCK_PROCESS;
    357                     return;
    358                 }
    359             }
    360         }
    361     }
    362     UNLOCK_PROCESS;
    363 }                               /* XtDestroyGC */
    364