]>
cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkgc.c
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.
7 * Copyright 1990 Regents of the University of California
8 * Permission to use, copy, modify, and distribute this
9 * software and its documentation for any purpose and without
10 * fee is hereby granted, provided that the above copyright
11 * notice appear in all copies. The University of California
12 * makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without
14 * express or implied warranty.
18 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkGC.c,v 1.9 92/05/13 08:48:45 ouster Exp $ SPRITE (Berkeley)";
25 * One of the following data structures exists for each GC that is
26 * currently active. The structure is indexed with two hash tables,
27 * one based on font name and one based on XFontStruct address.
31 GC gc
; /* Graphics context. */
32 Display
*display
; /* Display to which gc belongs. */
33 int refCount
; /* Number of active uses of gc. */
34 Tcl_HashEntry
*valueHashPtr
;/* Entry in valueTable (needed when deleting
39 * Hash table to map from a GC's values to a TkGC structure describing
40 * a GC with those values (used by Tk_GetGC).
43 static Tcl_HashTable valueTable
;
45 XGCValues values
; /* Desired values for GC. */
46 Screen
*screen
; /* Screen for which GC is valid. */
50 * Hash table for GC -> TkGC mapping. This table is indexed by the
51 * GC identifier, and is used by Tk_FreeGC.
54 static Tcl_HashTable idTable
;
56 static int initialized
= 0; /* 0 means static structures haven't been
60 * Forward declarations for procedures defined in this file:
63 static void GCInit
_ANSI_ARGS_((void));
66 *----------------------------------------------------------------------
70 * Given a desired set of values for a graphics context, find
71 * a read-only graphics context with the desired values.
74 * The return value is the X identifer for the desired graphics
75 * context. The caller should never modify this GC, and should
76 * call Tk_FreeGC when the GC is no longer needed.
79 * The GC is added to an internal database with a reference count.
80 * For each call to this procedure, there should eventually be a call
81 * to Tk_FreeGC, so that the database can be cleaned up when GC's
82 * aren't needed anymore.
84 *----------------------------------------------------------------------
89 Tk_Window tkwin
, /* Window in which GC will be used. */
90 register unsigned long valueMask
,
91 register XGCValues
*valuePtr
93 /* Values are specified here for bits set
97 Tcl_HashEntry
*valueHashPtr
, *idHashPtr
;
106 * Must zero key at start to clear out pad bytes that may be
107 * part of structure on some systems.
110 memset((VOID
*) &key
, 0, sizeof(key
));
113 * First, check to see if there's already a GC that will work
114 * for this request (exact matches only, sorry).
117 if (valueMask
& GCFunction
) {
118 key
.values
.function
= valuePtr
->function
;
120 key
.values
.function
= GXcopy
;
122 if (valueMask
& GCPlaneMask
) {
123 key
.values
.plane_mask
= valuePtr
->plane_mask
;
125 key
.values
.plane_mask
= ~0;
127 if (valueMask
& GCForeground
) {
128 key
.values
.foreground
= valuePtr
->foreground
;
130 key
.values
.foreground
= 0;
132 if (valueMask
& GCBackground
) {
133 key
.values
.background
= valuePtr
->background
;
135 key
.values
.background
= 1;
137 if (valueMask
& GCLineWidth
) {
138 key
.values
.line_width
= valuePtr
->line_width
;
140 key
.values
.line_width
= 0;
142 if (valueMask
& GCLineStyle
) {
143 key
.values
.line_style
= valuePtr
->line_style
;
145 key
.values
.line_style
= LineSolid
;
147 if (valueMask
& GCCapStyle
) {
148 key
.values
.cap_style
= valuePtr
->cap_style
;
150 key
.values
.cap_style
= CapButt
;
152 if (valueMask
& GCJoinStyle
) {
153 key
.values
.join_style
= valuePtr
->join_style
;
155 key
.values
.join_style
= JoinMiter
;
157 if (valueMask
& GCFillStyle
) {
158 key
.values
.fill_style
= valuePtr
->fill_style
;
160 key
.values
.fill_style
= FillSolid
;
162 if (valueMask
& GCFillRule
) {
163 key
.values
.fill_rule
= valuePtr
->fill_rule
;
165 key
.values
.fill_rule
= EvenOddRule
;
167 if (valueMask
& GCArcMode
) {
168 key
.values
.arc_mode
= valuePtr
->arc_mode
;
170 key
.values
.arc_mode
= ArcPieSlice
;
172 if (valueMask
& GCTile
) {
173 key
.values
.tile
= valuePtr
->tile
;
175 key
.values
.tile
= None
;
177 if (valueMask
& GCStipple
) {
178 key
.values
.stipple
= valuePtr
->stipple
;
180 key
.values
.stipple
= None
;
182 if (valueMask
& GCTileStipXOrigin
) {
183 key
.values
.ts_x_origin
= valuePtr
->ts_x_origin
;
185 key
.values
.ts_x_origin
= 0;
187 if (valueMask
& GCTileStipYOrigin
) {
188 key
.values
.ts_y_origin
= valuePtr
->ts_y_origin
;
190 key
.values
.ts_y_origin
= 0;
192 if (valueMask
& GCFont
) {
193 key
.values
.font
= valuePtr
->font
;
195 key
.values
.font
= None
;
197 if (valueMask
& GCSubwindowMode
) {
198 key
.values
.subwindow_mode
= valuePtr
->subwindow_mode
;
200 key
.values
.subwindow_mode
= ClipByChildren
;
202 if (valueMask
& GCGraphicsExposures
) {
203 key
.values
.graphics_exposures
= valuePtr
->graphics_exposures
;
205 key
.values
.graphics_exposures
= True
;
207 if (valueMask
& GCClipXOrigin
) {
208 key
.values
.clip_x_origin
= valuePtr
->clip_x_origin
;
210 key
.values
.clip_x_origin
= 0;
212 if (valueMask
& GCClipYOrigin
) {
213 key
.values
.clip_y_origin
= valuePtr
->clip_y_origin
;
215 key
.values
.clip_y_origin
= 0;
217 if (valueMask
& GCClipMask
) {
218 key
.values
.clip_mask
= valuePtr
->clip_mask
;
220 key
.values
.clip_mask
= None
;
222 if (valueMask
& GCDashOffset
) {
223 key
.values
.dash_offset
= valuePtr
->dash_offset
;
225 key
.values
.dash_offset
= 0;
227 if (valueMask
& GCDashList
) {
228 key
.values
.dashes
= valuePtr
->dashes
;
230 key
.values
.dashes
= 4;
232 key
.screen
= Tk_Screen(tkwin
);
233 valueHashPtr
= Tcl_CreateHashEntry(&valueTable
, (char *) &key
, &new);
235 gcPtr
= (TkGC
*) Tcl_GetHashValue(valueHashPtr
);
241 * No GC is currently available for this set of values. Allocate a
242 * new GC and add a new structure to the database.
245 gcPtr
= (TkGC
*) ckalloc(sizeof(TkGC
));
247 gcPtr
->gc
= XCreateGC(Tk_Display(tkwin
),
248 RootWindowOfScreen(Tk_Screen(tkwin
)),
249 valueMask
, &key
.values
);
251 gcPtr
->gc
= XCreateGC(Tk_Display(tkwin
),
252 Tk_DefaultPixmap(Tk_Screen(tkwin
)),
253 valueMask
, &key
.values
);
255 gcPtr
->display
= Tk_Display(tkwin
);
257 gcPtr
->valueHashPtr
= valueHashPtr
;
258 idHashPtr
= Tcl_CreateHashEntry(&idTable
, (char *) gcPtr
->gc
, &new);
260 panic("GC already registered in Tk_GetGC");
262 Tcl_SetHashValue(valueHashPtr
, gcPtr
);
263 Tcl_SetHashValue(idHashPtr
, gcPtr
);
268 *----------------------------------------------------------------------
272 * This procedure is called to release a font allocated by
279 * The reference count associated with gc is decremented, and
280 * gc is officially deallocated if no-one is using it anymore.
282 *----------------------------------------------------------------------
287 GC gc
/* Graphics context to be released. */
290 Tcl_HashEntry
*idHashPtr
;
291 register TkGC
*gcPtr
;
294 panic("Tk_FreeGC called before Tk_GetGC");
297 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) gc
);
298 if (idHashPtr
== NULL
) {
299 panic("Tk_FreeGC received unknown gc argument");
301 gcPtr
= (TkGC
*) Tcl_GetHashValue(idHashPtr
);
303 if (gcPtr
->refCount
== 0) {
304 XFreeGC(gcPtr
->display
, gcPtr
->gc
);
305 Tcl_DeleteHashEntry(gcPtr
->valueHashPtr
);
306 Tcl_DeleteHashEntry(idHashPtr
);
307 ckfree((char *) gcPtr
);
312 *----------------------------------------------------------------------
316 * Initialize the structures used for GC management.
324 *----------------------------------------------------------------------
331 Tcl_InitHashTable(&valueTable
, sizeof(ValueKey
)/sizeof(int));
332 Tcl_InitHashTable(&idTable
, TCL_ONE_WORD_KEYS
);