OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkGC.c] - Blame information for rev 579

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkGC.c --
3
 *
4
 *      This file maintains a database of read-only graphics contexts
5
 *      for the Tk toolkit, in order to allow GC's to be shared.
6
 *
7
 * Copyright (c) 1990-1994 The Regents of the University of California.
8
 * Copyright (c) 1994 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkGC.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
14
 */
15
 
16
#include "tkPort.h"
17
#include "tk.h"
18
 
19
/* CYGNUS LOCAL, for TkRegisterColorGC.  */
20
#include "tkInt.h"
21
 
22
/*
23
 * One of the following data structures exists for each GC that is
24
 * currently active.  The structure is indexed with two hash tables,
25
 * one based on the values in the graphics context and the other
26
 * based on the display and GC identifier.
27
 */
28
 
29
typedef struct {
30
    GC gc;                      /* Graphics context. */
31
    Display *display;           /* Display to which gc belongs. */
32
    int refCount;               /* Number of active uses of gc. */
33
    Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
34
                                 * this structure). */
35
    /* CYGNUS LOCAL.  */
36
    XColor *foreground;         /* Foreground color.  */
37
    XColor *background;         /* Background color.  */
38
} TkGC;
39
 
40
/*
41
 * Hash table to map from a GC's values to a TkGC structure describing
42
 * a GC with those values (used by Tk_GetGC).
43
 */
44
 
45
static Tcl_HashTable valueTable;
46
typedef struct {
47
    XGCValues values;           /* Desired values for GC. */
48
    Display *display;           /* Display for which GC is valid. */
49
    int screenNum;              /* screen number of display */
50
    int depth;                  /* and depth for which GC is valid. */
51
    /* CYGNUS LOCAL.  */
52
    XColor *foreground;         /* Foreground color.  */
53
    XColor *background;         /* Background color.  */
54
} ValueKey;
55
 
56
/*
57
 * Hash table for <display + GC> -> TkGC mapping. This table is used by
58
 * Tk_FreeGC.
59
 */
60
 
61
static Tcl_HashTable idTable;
62
typedef struct {
63
    Display *display;           /* Display for which GC was allocated. */
64
    GC gc;                      /* X's identifier for GC. */
65
} IdKey;
66
 
67
static int initialized = 0;      /* 0 means static structures haven't been
68
                                 * initialized yet. */
69
 
70
/*
71
 * Forward declarations for procedures defined in this file:
72
 */
73
 
74
static void             GCInit _ANSI_ARGS_((void));
75
 
76
/*
77
 *----------------------------------------------------------------------
78
 *
79
 * Tk_GetGC --
80
 *
81
 *      Given a desired set of values for a graphics context, find
82
 *      a read-only graphics context with the desired values.
83
 *
84
 * Results:
85
 *      The return value is the X identifer for the desired graphics
86
 *      context.  The caller should never modify this GC, and should
87
 *      call Tk_FreeGC when the GC is no longer needed.
88
 *
89
 * Side effects:
90
 *      The GC is added to an internal database with a reference count.
91
 *      For each call to this procedure, there should eventually be a call
92
 *      to Tk_FreeGC, so that the database can be cleaned up when GC's
93
 *      aren't needed anymore.
94
 *
95
 *----------------------------------------------------------------------
96
 */
97
 
98
/* CYGNUS LOCAL: Rename this to Tk_GetGCColor.  The new Tk_GetGC is
99
   below.  */
100
 
101
GC
102
Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
103
    Tk_Window tkwin;            /* Window in which GC will be used. */
104
    register unsigned long valueMask;
105
                                /* 1 bits correspond to values specified
106
                                 * in *valuesPtr;  other values are set
107
                                 * from defaults. */
108
    register XGCValues *valuePtr;
109
                                /* Values are specified here for bits set
110
                                 * in valueMask. */
111
    /* CYGNUS LOCAL.  */
112
    XColor *foreground;         /* Foreground color. */
113
    XColor *background;         /* Background color. */
114
{
115
    ValueKey valueKey;
116
    IdKey idKey;
117
    Tcl_HashEntry *valueHashPtr, *idHashPtr;
118
    register TkGC *gcPtr;
119
    int new;
120
    Drawable d, freeDrawable;
121
 
122
    if (!initialized) {
123
        GCInit();
124
    }
125
 
126
#if !defined(__WIN32__) && !defined(_WIN32)
127
    /* CYGNUS LOCAL.  We only care about special foreground and
128
       background colors on Windows.  If we are on some other
129
       platform, just ignore them.  If we don't do this, we may
130
       allocate an unnecessary GC if we have two colors with different
131
       names but the same pixel value.  */
132
    foreground = NULL;
133
    background = NULL;
134
#endif
135
 
136
    /*
137
     * Must zero valueKey at start to clear out pad bytes that may be
138
     * part of structure on some systems.
139
     */
140
 
141
    memset((VOID *) &valueKey, 0, sizeof(valueKey));
142
 
143
    /*
144
     * First, check to see if there's already a GC that will work
145
     * for this request (exact matches only, sorry).
146
     */
147
 
148
    if (valueMask & GCFunction) {
149
        valueKey.values.function = valuePtr->function;
150
    } else {
151
        valueKey.values.function = GXcopy;
152
    }
153
    if (valueMask & GCPlaneMask) {
154
        valueKey.values.plane_mask = valuePtr->plane_mask;
155
    } else {
156
        valueKey.values.plane_mask = (unsigned) ~0;
157
    }
158
    if (valueMask & GCForeground) {
159
        valueKey.values.foreground = valuePtr->foreground;
160
    } else {
161
        valueKey.values.foreground = 0;
162
    }
163
    if (valueMask & GCBackground) {
164
        valueKey.values.background = valuePtr->background;
165
    } else {
166
        valueKey.values.background = 1;
167
    }
168
    if (valueMask & GCLineWidth) {
169
        valueKey.values.line_width = valuePtr->line_width;
170
    } else {
171
        valueKey.values.line_width = 0;
172
    }
173
    if (valueMask & GCLineStyle) {
174
        valueKey.values.line_style = valuePtr->line_style;
175
    } else {
176
        valueKey.values.line_style = LineSolid;
177
    }
178
    if (valueMask & GCCapStyle) {
179
        valueKey.values.cap_style = valuePtr->cap_style;
180
    } else {
181
        valueKey.values.cap_style = CapButt;
182
    }
183
    if (valueMask & GCJoinStyle) {
184
        valueKey.values.join_style = valuePtr->join_style;
185
    } else {
186
        valueKey.values.join_style = JoinMiter;
187
    }
188
    if (valueMask & GCFillStyle) {
189
        valueKey.values.fill_style = valuePtr->fill_style;
190
    } else {
191
        valueKey.values.fill_style = FillSolid;
192
    }
193
    if (valueMask & GCFillRule) {
194
        valueKey.values.fill_rule = valuePtr->fill_rule;
195
    } else {
196
        valueKey.values.fill_rule = EvenOddRule;
197
    }
198
    if (valueMask & GCArcMode) {
199
        valueKey.values.arc_mode = valuePtr->arc_mode;
200
    } else {
201
        valueKey.values.arc_mode = ArcPieSlice;
202
    }
203
    if (valueMask & GCTile) {
204
        valueKey.values.tile = valuePtr->tile;
205
    } else {
206
        valueKey.values.tile = None;
207
    }
208
    if (valueMask & GCStipple) {
209
        valueKey.values.stipple = valuePtr->stipple;
210
    } else {
211
        valueKey.values.stipple = None;
212
    }
213
    if (valueMask & GCTileStipXOrigin) {
214
        valueKey.values.ts_x_origin = valuePtr->ts_x_origin;
215
    } else {
216
        valueKey.values.ts_x_origin = 0;
217
    }
218
    if (valueMask & GCTileStipYOrigin) {
219
        valueKey.values.ts_y_origin = valuePtr->ts_y_origin;
220
    } else {
221
        valueKey.values.ts_y_origin = 0;
222
    }
223
    if (valueMask & GCFont) {
224
        valueKey.values.font = valuePtr->font;
225
    } else {
226
        valueKey.values.font = None;
227
    }
228
    if (valueMask & GCSubwindowMode) {
229
        valueKey.values.subwindow_mode = valuePtr->subwindow_mode;
230
    } else {
231
        valueKey.values.subwindow_mode = ClipByChildren;
232
    }
233
    if (valueMask & GCGraphicsExposures) {
234
        valueKey.values.graphics_exposures = valuePtr->graphics_exposures;
235
    } else {
236
        valueKey.values.graphics_exposures = True;
237
    }
238
    if (valueMask & GCClipXOrigin) {
239
        valueKey.values.clip_x_origin = valuePtr->clip_x_origin;
240
    } else {
241
        valueKey.values.clip_x_origin = 0;
242
    }
243
    if (valueMask & GCClipYOrigin) {
244
        valueKey.values.clip_y_origin = valuePtr->clip_y_origin;
245
    } else {
246
        valueKey.values.clip_y_origin = 0;
247
    }
248
    if (valueMask & GCClipMask) {
249
        valueKey.values.clip_mask = valuePtr->clip_mask;
250
    } else {
251
        valueKey.values.clip_mask = None;
252
    }
253
    if (valueMask & GCDashOffset) {
254
        valueKey.values.dash_offset = valuePtr->dash_offset;
255
    } else {
256
        valueKey.values.dash_offset = 0;
257
    }
258
    if (valueMask & GCDashList) {
259
        valueKey.values.dashes = valuePtr->dashes;
260
    } else {
261
        valueKey.values.dashes = 4;
262
    }
263
    valueKey.display = Tk_Display(tkwin);
264
    valueKey.screenNum = Tk_ScreenNumber(tkwin);
265
    valueKey.depth = Tk_Depth(tkwin);
266
 
267
    /* CYGNUS LOCAL.  Set colors.  */
268
    valueKey.foreground = foreground;
269
    valueKey.background = background;
270
 
271
    valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new);
272
    if (!new) {
273
        gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr);
274
        gcPtr->refCount++;
275
        return gcPtr->gc;
276
    }
277
 
278
    /*
279
     * No GC is currently available for this set of values.  Allocate a
280
     * new GC and add a new structure to the database.
281
     */
282
 
283
    gcPtr = (TkGC *) ckalloc(sizeof(TkGC));
284
 
285
    /*
286
     * Find or make a drawable to use to specify the screen and depth
287
     * of the GC.  We may have to make a small pixmap, to avoid doing
288
     * Tk_MakeWindowExist on the window.
289
     */
290
 
291
    freeDrawable = None;
292
    if (Tk_WindowId(tkwin) != None) {
293
        d = Tk_WindowId(tkwin);
294
    } else if (valueKey.depth ==
295
            DefaultDepth(valueKey.display, valueKey.screenNum)) {
296
        d = RootWindow(valueKey.display, valueKey.screenNum);
297
    } else {
298
        d = Tk_GetPixmap(valueKey.display,
299
                RootWindow(valueKey.display, valueKey.screenNum),
300
                1, 1, valueKey.depth);
301
        freeDrawable = d;
302
    }
303
 
304
    gcPtr->gc = XCreateGC(valueKey.display, d, valueMask, &valueKey.values);
305
    gcPtr->display = valueKey.display;
306
    gcPtr->refCount = 1;
307
    gcPtr->valueHashPtr = valueHashPtr;
308
    idKey.display = valueKey.display;
309
    idKey.gc = gcPtr->gc;
310
    idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
311
    if (!new) {
312
        panic("GC already registered in Tk_GetGC");
313
    }
314
    Tcl_SetHashValue(valueHashPtr, gcPtr);
315
    Tcl_SetHashValue(idHashPtr, gcPtr);
316
    if (freeDrawable != None) {
317
        Tk_FreePixmap(valueKey.display, freeDrawable);
318
    }
319
 
320
    /* CYGNUS LOCAL.  Record and register the colors.  */
321
    gcPtr->foreground = foreground;
322
    gcPtr->background = background;
323
    if (foreground != NULL) {
324
        TkRegisterColorGC(foreground, valueKey.display, gcPtr->gc,
325
                          GCForeground);
326
    }
327
    if (background != NULL) {
328
        TkRegisterColorGC(background, valueKey.display, gcPtr->gc,
329
                          GCBackground);
330
    }
331
 
332
    return gcPtr->gc;
333
}
334
 
335
/* CYGNUS LOCAL.  Tk_GetGC now just calls Tk_GetGCColor.  */
336
 
337
GC
338
Tk_GetGC(tkwin, valueMask, valuePtr)
339
    Tk_Window tkwin;            /* Window in which GC will be used. */
340
    register unsigned long valueMask;
341
                                /* 1 bits correspond to values specified
342
                                 * in *valuesPtr;  other values are set
343
                                 * from defaults. */
344
    register XGCValues *valuePtr;
345
                                /* Values are specified here for bits set
346
                                 * in valueMask. */
347
{
348
    return Tk_GetGCColor(tkwin, valueMask, valuePtr, NULL, NULL);
349
}
350
 
351
/*
352
 *----------------------------------------------------------------------
353
 *
354
 * Tk_FreeGC --
355
 *
356
 *      This procedure is called to release a graphics context allocated by
357
 *      Tk_GetGC.
358
 *
359
 * Results:
360
 *      None.
361
 *
362
 * Side effects:
363
 *      The reference count associated with gc is decremented, and
364
 *      gc is officially deallocated if no-one is using it anymore.
365
 *
366
 *----------------------------------------------------------------------
367
 */
368
 
369
void
370
Tk_FreeGC(display, gc)
371
    Display *display;           /* Display for which gc was allocated. */
372
    GC gc;                      /* Graphics context to be released. */
373
{
374
    IdKey idKey;
375
    Tcl_HashEntry *idHashPtr;
376
    register TkGC *gcPtr;
377
 
378
    if (!initialized) {
379
        panic("Tk_FreeGC called before Tk_GetGC");
380
    }
381
 
382
    idKey.display = display;
383
    idKey.gc = gc;
384
    idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
385
    if (idHashPtr == NULL) {
386
        panic("Tk_FreeGC received unknown gc argument");
387
    }
388
    gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr);
389
    gcPtr->refCount--;
390
    if (gcPtr->refCount == 0) {
391
        /* CYGNUS LOCAL: Deregister the colors.  */
392
        if (gcPtr->foreground != NULL) {
393
            TkDeregisterColorGC(gcPtr->foreground, gcPtr->gc,
394
                                GCForeground);
395
        }
396
        if (gcPtr->background != NULL) {
397
            TkDeregisterColorGC(gcPtr->background, gcPtr->gc,
398
                                GCBackground);
399
        }
400
 
401
        Tk_FreeXId(gcPtr->display, (XID) XGContextFromGC(gcPtr->gc));
402
        XFreeGC(gcPtr->display, gcPtr->gc);
403
        Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
404
        Tcl_DeleteHashEntry(idHashPtr);
405
        ckfree((char *) gcPtr);
406
    }
407
}
408
 
409
/*
410
 *----------------------------------------------------------------------
411
 *
412
 * GCInit --
413
 *
414
 *      Initialize the structures used for GC management.
415
 *
416
 * Results:
417
 *      None.
418
 *
419
 * Side effects:
420
 *      Read the code.
421
 *
422
 *----------------------------------------------------------------------
423
 */
424
 
425
static void
426
GCInit()
427
{
428
    initialized = 1;
429
    Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
430
    Tcl_InitHashTable(&idTable, sizeof(IdKey)/sizeof(int));
431
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.