]>
git.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 *----------------------------------------------------------------------
88 Tk_GetGC(tkwin
, valueMask
, valuePtr
)
89 Tk_Window tkwin
; /* Window in which GC will be used. */
90 register unsigned long valueMask
;
91 /* 1 bits correspond to values specified
92 * in *valuesPtr; other values are set
94 register XGCValues
*valuePtr
;
95 /* Values are specified here for bits set
99 Tcl_HashEntry
*valueHashPtr
, *idHashPtr
;
100 register TkGC
*gcPtr
;
108 * Must zero key at start to clear out pad bytes that may be
109 * part of structure on some systems.
112 memset((VOID
*) &key
, 0, sizeof(key
));
115 * First, check to see if there's already a GC that will work
116 * for this request (exact matches only, sorry).
119 if (valueMask
& GCFunction
) {
120 key
.values
.function
= valuePtr
->function
;
122 key
.values
.function
= GXcopy
;
124 if (valueMask
& GCPlaneMask
) {
125 key
.values
.plane_mask
= valuePtr
->plane_mask
;
127 key
.values
.plane_mask
= ~0;
129 if (valueMask
& GCForeground
) {
130 key
.values
.foreground
= valuePtr
->foreground
;
132 key
.values
.foreground
= 0;
134 if (valueMask
& GCBackground
) {
135 key
.values
.background
= valuePtr
->background
;
137 key
.values
.background
= 1;
139 if (valueMask
& GCLineWidth
) {
140 key
.values
.line_width
= valuePtr
->line_width
;
142 key
.values
.line_width
= 0;
144 if (valueMask
& GCLineStyle
) {
145 key
.values
.line_style
= valuePtr
->line_style
;
147 key
.values
.line_style
= LineSolid
;
149 if (valueMask
& GCCapStyle
) {
150 key
.values
.cap_style
= valuePtr
->cap_style
;
152 key
.values
.cap_style
= CapButt
;
154 if (valueMask
& GCJoinStyle
) {
155 key
.values
.join_style
= valuePtr
->join_style
;
157 key
.values
.join_style
= JoinMiter
;
159 if (valueMask
& GCFillStyle
) {
160 key
.values
.fill_style
= valuePtr
->fill_style
;
162 key
.values
.fill_style
= FillSolid
;
164 if (valueMask
& GCFillRule
) {
165 key
.values
.fill_rule
= valuePtr
->fill_rule
;
167 key
.values
.fill_rule
= EvenOddRule
;
169 if (valueMask
& GCArcMode
) {
170 key
.values
.arc_mode
= valuePtr
->arc_mode
;
172 key
.values
.arc_mode
= ArcPieSlice
;
174 if (valueMask
& GCTile
) {
175 key
.values
.tile
= valuePtr
->tile
;
177 key
.values
.tile
= None
;
179 if (valueMask
& GCStipple
) {
180 key
.values
.stipple
= valuePtr
->stipple
;
182 key
.values
.stipple
= None
;
184 if (valueMask
& GCTileStipXOrigin
) {
185 key
.values
.ts_x_origin
= valuePtr
->ts_x_origin
;
187 key
.values
.ts_x_origin
= 0;
189 if (valueMask
& GCTileStipYOrigin
) {
190 key
.values
.ts_y_origin
= valuePtr
->ts_y_origin
;
192 key
.values
.ts_y_origin
= 0;
194 if (valueMask
& GCFont
) {
195 key
.values
.font
= valuePtr
->font
;
197 key
.values
.font
= None
;
199 if (valueMask
& GCSubwindowMode
) {
200 key
.values
.subwindow_mode
= valuePtr
->subwindow_mode
;
202 key
.values
.subwindow_mode
= ClipByChildren
;
204 if (valueMask
& GCGraphicsExposures
) {
205 key
.values
.graphics_exposures
= valuePtr
->graphics_exposures
;
207 key
.values
.graphics_exposures
= True
;
209 if (valueMask
& GCClipXOrigin
) {
210 key
.values
.clip_x_origin
= valuePtr
->clip_x_origin
;
212 key
.values
.clip_x_origin
= 0;
214 if (valueMask
& GCClipYOrigin
) {
215 key
.values
.clip_y_origin
= valuePtr
->clip_y_origin
;
217 key
.values
.clip_y_origin
= 0;
219 if (valueMask
& GCClipMask
) {
220 key
.values
.clip_mask
= valuePtr
->clip_mask
;
222 key
.values
.clip_mask
= None
;
224 if (valueMask
& GCDashOffset
) {
225 key
.values
.dash_offset
= valuePtr
->dash_offset
;
227 key
.values
.dash_offset
= 0;
229 if (valueMask
& GCDashList
) {
230 key
.values
.dashes
= valuePtr
->dashes
;
232 key
.values
.dashes
= 4;
234 key
.screen
= Tk_Screen(tkwin
);
235 valueHashPtr
= Tcl_CreateHashEntry(&valueTable
, (char *) &key
, &new);
237 gcPtr
= (TkGC
*) Tcl_GetHashValue(valueHashPtr
);
243 * No GC is currently available for this set of values. Allocate a
244 * new GC and add a new structure to the database.
247 gcPtr
= (TkGC
*) ckalloc(sizeof(TkGC
));
249 gcPtr
->gc
= XCreateGC(Tk_Display(tkwin
),
250 RootWindowOfScreen(Tk_Screen(tkwin
)),
251 valueMask
, &key
.values
);
253 gcPtr
->gc
= XCreateGC(Tk_Display(tkwin
),
254 Tk_DefaultPixmap(Tk_Screen(tkwin
)),
255 valueMask
, &key
.values
);
257 gcPtr
->display
= Tk_Display(tkwin
);
259 gcPtr
->valueHashPtr
= valueHashPtr
;
260 idHashPtr
= Tcl_CreateHashEntry(&idTable
, (char *) gcPtr
->gc
, &new);
262 panic("GC already registered in Tk_GetGC");
264 Tcl_SetHashValue(valueHashPtr
, gcPtr
);
265 Tcl_SetHashValue(idHashPtr
, gcPtr
);
270 *----------------------------------------------------------------------
274 * This procedure is called to release a font allocated by
281 * The reference count associated with gc is decremented, and
282 * gc is officially deallocated if no-one is using it anymore.
284 *----------------------------------------------------------------------
289 GC gc
; /* Graphics context to be released. */
291 Tcl_HashEntry
*idHashPtr
;
292 register TkGC
*gcPtr
;
295 panic("Tk_FreeGC called before Tk_GetGC");
298 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) gc
);
299 if (idHashPtr
== NULL
) {
300 panic("Tk_FreeGC received unknown gc argument");
302 gcPtr
= (TkGC
*) Tcl_GetHashValue(idHashPtr
);
304 if (gcPtr
->refCount
== 0) {
305 XFreeGC(gcPtr
->display
, gcPtr
->gc
);
306 Tcl_DeleteHashEntry(gcPtr
->valueHashPtr
);
307 Tcl_DeleteHashEntry(idHashPtr
);
308 ckfree((char *) gcPtr
);
313 *----------------------------------------------------------------------
317 * Initialize the structures used for GC management.
325 *----------------------------------------------------------------------
332 Tcl_InitHashTable(&valueTable
, sizeof(ValueKey
)/sizeof(int));
333 Tcl_InitHashTable(&idTable
, TCL_ONE_WORD_KEYS
);