2121 * The plumbing and control flow here is quite contorted; 
2222 * it would be better to address this problem in the core instead. 
2323 * 
24-  * @@@ BUGS/TODO: Need distinct caches for each combination 
25-  * of display, visual, and colormap. 
26-  * 
2724 * @@@ Colormap flashing on PseudoColor visuals is still possible, 
2825 * but this will be a transient effect. 
2926 */ 
3027
3128#include  "tkInt.h" 
3229#include  "ttkTheme.h" 
3330
31+ #if  defined(_WIN32 ) ||  defined(MAC_OSX_TK )
32+ #   define  NEED_EXTRA_INFO  0
33+ #else 
34+  /* 
35+   * Display, Screen, Visual, and Colormap need be tracked, too. 
36+   * Required on X11 with multiple display connections or 
37+   * special visuals/colormaps. 
38+   */ 
39+ #   define  NEED_EXTRA_INFO  1
40+ #endif 
41+ 
42+ #if  NEED_EXTRA_INFO 
43+ typedef  struct  {
44+     Tcl_Obj  * objPtr ;		/* The cached Tcl_Obj*. */ 
45+     Display  * display ;		/* Display of (Font|Border|Color)Obj */ 
46+     int  screenNum ;		/* Screen number of (Font|Border|Color)Obj */ 
47+     Visual  * visual ;		/* Visual of (Font|Border|Color)Obj */ 
48+     Colormap  colormap ;		/* Colormap of (Font|Border|Color)Obj */ 
49+ } Ttk_Cached ;
50+ #endif 
51+ 
3452#ifdef  _WIN32 
3553#include  "tkWinInt.h" 
3654#endif 
@@ -79,11 +97,27 @@ static void Ttk_ClearCache(Ttk_ResourceCache cache)
7997     */ 
8098    entryPtr  =  Tcl_FirstHashEntry (& cache -> fontTable , & search );
8199    while  (entryPtr  !=  NULL ) {
100+ #if  !NEED_EXTRA_INFO 
82101	Tcl_Obj  * fontObj  =  (Tcl_Obj  * )Tcl_GetHashValue (entryPtr );
83102	if  (fontObj ) {
84103	    Tk_FreeFontFromObj (cache -> tkwin , fontObj );
85104	    Tcl_DecrRefCount (fontObj );
86105	}
106+ #else 
107+ 	Ttk_Cached  * cachedPtr  =  Tcl_GetHashValue (entryPtr );
108+ 	if  (cachedPtr ) {
109+ 	    TkWindow  fakeWin ;
110+ 	    Tcl_Obj  * fontObj  =  cachedPtr -> objPtr ;
111+ 	    fakeWin  =  * ((TkWindow  * ) cache -> tkwin );
112+ 	    fakeWin .display  =  cachedPtr -> display ;
113+ 	    fakeWin .screenNum  =  cachedPtr -> screenNum ;
114+ 	    fakeWin .visual  =  cachedPtr -> visual ;
115+ 	    fakeWin .atts .colormap  =  cachedPtr -> colormap ;
116+ 	    Tk_FreeFontFromObj ((Tk_Window ) & fakeWin , fontObj );
117+ 	    Tcl_DecrRefCount (fontObj );
118+ 	    ckfree (cachedPtr );
119+ 	}
120+ #endif 
87121	entryPtr  =  Tcl_NextHashEntry (& search );
88122    }
89123    Tcl_DeleteHashTable (& cache -> fontTable );
@@ -94,11 +128,27 @@ static void Ttk_ClearCache(Ttk_ResourceCache cache)
94128     */ 
95129    entryPtr  =  Tcl_FirstHashEntry (& cache -> colorTable , & search );
96130    while  (entryPtr  !=  NULL ) {
131+ #if  !NEED_EXTRA_INFO 
97132	Tcl_Obj  * colorObj  =  (Tcl_Obj  * )Tcl_GetHashValue (entryPtr );
98133	if  (colorObj ) {
99134	    Tk_FreeColorFromObj (cache -> tkwin , colorObj );
100135	    Tcl_DecrRefCount (colorObj );
101136	}
137+ #else 
138+ 	Ttk_Cached  * cachedPtr  =  Tcl_GetHashValue (entryPtr );
139+ 	if  (cachedPtr ) {
140+ 	    TkWindow  fakeWin ;
141+ 	    Tcl_Obj  * colorObj  =  cachedPtr -> objPtr ;
142+ 	    fakeWin  =  * ((TkWindow  * ) cache -> tkwin );
143+ 	    fakeWin .display  =  cachedPtr -> display ;
144+ 	    fakeWin .screenNum  =  cachedPtr -> screenNum ;
145+ 	    fakeWin .visual  =  cachedPtr -> visual ;
146+ 	    fakeWin .atts .colormap  =  cachedPtr -> colormap ;
147+ 	    Tk_FreeColorFromObj ((Tk_Window ) & fakeWin , colorObj );
148+ 	    Tcl_DecrRefCount (colorObj );
149+ 	    ckfree (cachedPtr );
150+ 	}
151+ #endif 
102152	entryPtr  =  Tcl_NextHashEntry (& search );
103153    }
104154    Tcl_DeleteHashTable (& cache -> colorTable );
@@ -109,11 +159,27 @@ static void Ttk_ClearCache(Ttk_ResourceCache cache)
109159     */ 
110160    entryPtr  =  Tcl_FirstHashEntry (& cache -> borderTable , & search );
111161    while  (entryPtr  !=  NULL ) {
162+ #if  !NEED_EXTRA_INFO 
112163	Tcl_Obj  * borderObj  =  (Tcl_Obj  * )Tcl_GetHashValue (entryPtr );
113164	if  (borderObj ) {
114165	    Tk_Free3DBorderFromObj (cache -> tkwin , borderObj );
115166	    Tcl_DecrRefCount (borderObj );
116167	}
168+ #else 
169+ 	Ttk_Cached  * cachedPtr  =  Tcl_GetHashValue (entryPtr );
170+ 	if  (cachedPtr ) {
171+ 	    TkWindow  fakeWin ;
172+ 	    Tcl_Obj  * borderObj  =  cachedPtr -> objPtr ;
173+ 	    fakeWin  =  * ((TkWindow  * ) cache -> tkwin );
174+ 	    fakeWin .display  =  cachedPtr -> display ;
175+ 	    fakeWin .screenNum  =  cachedPtr -> screenNum ;
176+ 	    fakeWin .visual  =  cachedPtr -> visual ;
177+ 	    fakeWin .atts .colormap  =  cachedPtr -> colormap ;
178+ 	    Tk_Free3DBorderFromObj ((Tk_Window ) & fakeWin , borderObj );
179+ 	    Tcl_DecrRefCount (borderObj );
180+ 	    ckfree (cachedPtr );
181+ 	}
182+ #endif 
117183	entryPtr  =  Tcl_NextHashEntry (& search );
118184    }
119185    Tcl_DeleteHashTable (& cache -> borderTable );
@@ -186,14 +252,12 @@ static void CacheWinEventHandler(void *clientData, XEvent *eventPtr)
186252/* 
187253 * InitCacheWindow -- 
188254 *	Specify the cache window if not already set. 
189-  *	@@@ SHOULD: use separate caches for each combination 
190-  *	@@@ of display, visual, and colormap. 
191255 */ 
192256static  void  InitCacheWindow (Ttk_ResourceCache  cache , Tk_Window  tkwin )
193257{
194258    if  (cache -> tkwin  ==  NULL ) {
195- 	cache -> tkwin  =  tkwin ;
196- 	Tk_CreateEventHandler (tkwin , StructureNotifyMask ,
259+ 	cache -> tkwin  =  Tk_MainWindow ( cache -> interp ) ;
260+ 	Tk_CreateEventHandler (cache -> tkwin , StructureNotifyMask ,
197261		CacheWinEventHandler , cache );
198262    }
199263}
@@ -266,19 +330,47 @@ static Tcl_Obj *Ttk_Use(
266330    Tcl_Obj  * objPtr )
267331{
268332    int  newEntry ;
269-     Tcl_HashEntry  * entryPtr  = 
270- 	Tcl_CreateHashEntry (table ,Tcl_GetString (objPtr ),& newEntry );
333+     Tcl_HashEntry  * entryPtr ;
271334    Tcl_Obj  * cacheObj ;
335+ #if  !NEED_EXTRA_INFO 
336+     entryPtr  =  Tcl_CreateHashEntry (table , Tcl_GetString (objPtr ), & newEntry );
337+ #else 
338+     Tcl_DString  ds ;
339+     char  buffer [64 ];
340+ 
341+     Tcl_DStringInit (& ds );
342+     Tcl_DStringAppend (& ds , Tcl_GetString (objPtr ), -1 );
343+     snprintf (buffer , 64 , ",%d,%lu,%lu" , ConnectionNumber (Tk_Display (tkwin )),
344+ 	    Tk_Visual (tkwin )-> visualid , (unsigned long )Tk_Colormap (tkwin ));
345+     Tcl_DStringAppend (& ds , buffer , -1 );
346+     entryPtr  =  Tcl_CreateHashEntry (table , Tcl_DStringValue (& ds ), & newEntry );
347+     Tcl_DStringFree (& ds );
348+ #endif 
272349
273350    if  (!newEntry ) {
351+ #if  !NEED_EXTRA_INFO 
274352	return  (Tcl_Obj  * )Tcl_GetHashValue (entryPtr );
353+ #else 
354+ 	Ttk_Cached  * cachedPtr  =  Tcl_GetHashValue (entryPtr );
355+ 	return  cachedPtr  ? cachedPtr -> objPtr  : NULL ;
356+ #endif 
275357    }
276358
277359    cacheObj  =  Tcl_DuplicateObj (objPtr );
278360    Tcl_IncrRefCount (cacheObj );
279361
280362    if  (allocate (interp , tkwin , cacheObj )) {
363+ #if  !NEED_EXTRA_INFO 
281364	Tcl_SetHashValue (entryPtr , cacheObj );
365+ #else 
366+ 	Ttk_Cached  * cachedPtr  =  ckalloc (sizeof (* cachedPtr ));
367+ 	cachedPtr -> objPtr  =  cacheObj ;
368+ 	cachedPtr -> display  =  Tk_Display (tkwin );
369+ 	cachedPtr -> screenNum  =  Tk_ScreenNumber (tkwin );
370+ 	cachedPtr -> visual  =  Tk_Visual (tkwin );
371+ 	cachedPtr -> colormap  =  Tk_Colormap (tkwin );
372+ 	Tcl_SetHashValue (entryPtr , cachedPtr );
373+ #endif 
282374	return  cacheObj ;
283375    } else  {
284376	Tcl_DecrRefCount (cacheObj );
@@ -347,11 +439,25 @@ Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
347439{
348440    const  char  * imageName  =  Tcl_GetString (objPtr );
349441    int  newEntry ;
350-     Tcl_HashEntry  * entryPtr  = 
351- 	Tcl_CreateHashEntry (& cache -> imageTable ,imageName ,& newEntry );
442+     Tcl_HashEntry  * entryPtr ;
352443    Tk_Image  image ;
353444
354445    InitCacheWindow (cache , tkwin );
446+ #if  !NEED_EXTRA_INFO 
447+     entryPtr  =  Tcl_CreateHashEntry (& cache -> imageTable , imageName , & newEntry );
448+ #else 
449+     Tcl_DString  ds ;
450+     char  buffer [64 ];
451+ 
452+     Tcl_DStringInit (& ds );
453+     Tcl_DStringAppend (& ds , imageName , -1 );
454+     snprintf (buffer , 64 , ",%d,%lu,%lu" , ConnectionNumber (Tk_Display (tkwin )),
455+ 	Tk_Visual (tkwin )-> visualid , (unsigned long )Tk_Colormap (tkwin ));
456+     Tcl_DStringAppend (& ds , buffer , -1 );
457+     entryPtr  =  Tcl_CreateHashEntry (& cache -> imageTable ,
458+ 	Tcl_DStringValue (& ds ), & newEntry );
459+     Tcl_DStringFree (& ds );
460+ #endif 
355461
356462    if  (!newEntry ) {
357463	return  (Tk_Image )Tcl_GetHashValue (entryPtr );
0 commit comments