~ubuntu-branches/debian/stretch/libxt/stretch

« back to all changes in this revision

Viewing changes to src/GCManager.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Stone
  • Date: 2005-09-12 17:29:07 UTC
  • Revision ID: james.westby@ubuntu.com-20050912172907-ad6dg6r117jij2uo
Tags: upstream-0.99.0+cvs.20050803
ImportĀ upstreamĀ versionĀ 0.99.0+cvs.20050803

Show diffs side-by-side

added added

removed removed

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