/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkgc.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkgc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.70  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25