/[dtapublic]/projs/trunk/shared_source/tk_base/tkvisual.c
ViewVC logotype

Annotation of /projs/trunk/shared_source/tk_base/tkvisual.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations) (download)
Sat Oct 8 06:43:03 2016 UTC (7 years, 9 months ago) by dashley
Original Path: sf_code/esrgpcpj/shared/tk_base/tkvisual.c
File MIME type: text/plain
File size: 16896 byte(s)
Initial commit.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkvisual.c,v 1.1.1.1 2001/06/13 05:11:40 dtashley Exp $ */
2    
3     /*
4     * tkVisual.c --
5     *
6     * This file contains library procedures for allocating and
7     * freeing visuals and colormaps. This code is based on a
8     * prototype implementation by Paul Mackerras.
9     *
10     * Copyright (c) 1994 The Regents of the University of California.
11     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
12     *
13     * See the file "license.terms" for information on usage and redistribution
14     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15     *
16     * RCS: @(#) $Id: tkvisual.c,v 1.1.1.1 2001/06/13 05:11:40 dtashley Exp $
17     */
18    
19     #include "tkInt.h"
20     #include "tkPort.h"
21    
22     /*
23     * The table below maps from symbolic names for visual classes
24     * to the associated X class symbols.
25     */
26    
27     typedef struct VisualDictionary {
28     char *name; /* Textual name of class. */
29     int minLength; /* Minimum # characters that must be
30     * specified for an unambiguous match. */
31     int class; /* X symbol for class. */
32     } VisualDictionary;
33     static VisualDictionary visualNames[] = {
34     {"best", 1, 0},
35     {"directcolor", 2, DirectColor},
36     {"grayscale", 1, GrayScale},
37     {"greyscale", 1, GrayScale},
38     {"pseudocolor", 1, PseudoColor},
39     {"staticcolor", 7, StaticColor},
40     {"staticgray", 7, StaticGray},
41     {"staticgrey", 7, StaticGray},
42     {"truecolor", 1, TrueColor},
43     {NULL, 0, 0},
44     };
45    
46     /*
47     * One of the following structures exists for each distinct non-default
48     * colormap allocated for a display by Tk_GetColormap.
49     */
50    
51     struct TkColormap {
52     Colormap colormap; /* X's identifier for the colormap. */
53     Visual *visual; /* Visual for which colormap was
54     * allocated. */
55     int refCount; /* How many uses of the colormap are still
56     * outstanding (calls to Tk_GetColormap
57     * minus calls to Tk_FreeColormap). */
58     int shareable; /* 0 means this colormap was allocated by
59     * a call to Tk_GetColormap with "new",
60     * implying that the window wants it all
61     * for itself. 1 means that the colormap
62     * was allocated as a default for a particular
63     * visual, so it can be shared. */
64     struct TkColormap *nextPtr; /* Next in list of colormaps for this display,
65     * or NULL for end of list. */
66     };
67    
68     /*
69     *----------------------------------------------------------------------
70     *
71     * Tk_GetVisual --
72     *
73     * Given a string identifying a particular kind of visual, this
74     * procedure returns a visual and depth that matches the specification.
75     *
76     * Results:
77     * The return value is normally a pointer to a visual. If an
78     * error occurred in looking up the visual, NULL is returned and
79     * an error message is left in the interp's result. The depth of the
80     * visual is returned to *depthPtr under normal returns. If
81     * colormapPtr is non-NULL, then this procedure also finds a
82     * suitable colormap for use with the visual in tkwin, and it
83     * returns that colormap in *colormapPtr unless an error occurs.
84     *
85     * Side effects:
86     * A new colormap may be allocated.
87     *
88     *----------------------------------------------------------------------
89     */
90    
91     Visual *
92     Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr)
93     Tcl_Interp *interp; /* Interpreter to use for error
94     * reporting. */
95     Tk_Window tkwin; /* Window in which visual will be
96     * used. */
97     char *string; /* String describing visual. See
98     * manual entry for details. */
99     int *depthPtr; /* The depth of the returned visual
100     * is stored here. */
101     Colormap *colormapPtr; /* If non-NULL, then a suitable
102     * colormap for visual is placed here.
103     * This colormap must eventually be
104     * freed by calling Tk_FreeColormap. */
105     {
106     Tk_Window tkwin2;
107     XVisualInfo template, *visInfoList, *bestPtr;
108     long mask;
109     Visual *visual;
110     int length, c, numVisuals, prio, bestPrio, i;
111     char *p;
112     VisualDictionary *dictPtr;
113     TkColormap *cmapPtr;
114     TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
115    
116     /*
117     * Parse string and set up a template for use in searching for
118     * an appropriate visual.
119     */
120    
121     c = string[0];
122     if (c == '.') {
123     /*
124     * The string must be a window name. If the window is on the
125     * same screen as tkwin, then just use its visual. Otherwise
126     * use the information about the visual as a template for the
127     * search.
128     */
129    
130     tkwin2 = Tk_NameToWindow(interp, string, tkwin);
131     if (tkwin2 == NULL) {
132     return NULL;
133     }
134     visual = Tk_Visual(tkwin2);
135     if (Tk_Screen(tkwin) == Tk_Screen(tkwin2)) {
136     *depthPtr = Tk_Depth(tkwin2);
137     if (colormapPtr != NULL) {
138     /*
139     * Use the colormap from the other window too (but be sure
140     * to increment its reference count if it's one of the ones
141     * allocated here).
142     */
143    
144     *colormapPtr = Tk_Colormap(tkwin2);
145     for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
146     cmapPtr = cmapPtr->nextPtr) {
147     if (cmapPtr->colormap == *colormapPtr) {
148     cmapPtr->refCount += 1;
149     break;
150     }
151     }
152     }
153     return visual;
154     }
155     template.depth = Tk_Depth(tkwin2);
156     template.class = visual->class;
157     template.red_mask = visual->red_mask;
158     template.green_mask = visual->green_mask;
159     template.blue_mask = visual->blue_mask;
160     template.colormap_size = visual->map_entries;
161     template.bits_per_rgb = visual->bits_per_rgb;
162     mask = VisualDepthMask|VisualClassMask|VisualRedMaskMask
163     |VisualGreenMaskMask|VisualBlueMaskMask|VisualColormapSizeMask
164     |VisualBitsPerRGBMask;
165     } else if ((c == 0) || ((c == 'd') && (string[1] != 0)
166     && (strncmp(string, "default", strlen(string)) == 0))) {
167     /*
168     * Use the default visual for the window's screen.
169     */
170    
171     if (colormapPtr != NULL) {
172     *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));
173     }
174     *depthPtr = DefaultDepthOfScreen(Tk_Screen(tkwin));
175     return DefaultVisualOfScreen(Tk_Screen(tkwin));
176     } else if (isdigit(UCHAR(c))) {
177     int visualId;
178    
179     /*
180     * This is a visual ID.
181     */
182    
183     if (Tcl_GetInt(interp, string, &visualId) == TCL_ERROR) {
184     Tcl_ResetResult(interp);
185     Tcl_AppendResult(interp, "bad X identifier for visual: ",
186     string, "\"", (char *) NULL);
187     return NULL;
188     }
189     template.visualid = visualId;
190     mask = VisualIDMask;
191     } else {
192     /*
193     * Parse the string into a class name (or "best") optionally
194     * followed by whitespace and a depth.
195     */
196    
197     for (p = string; *p != 0; p++) {
198     if (isspace(UCHAR(*p)) || isdigit(UCHAR(*p))) {
199     break;
200     }
201     }
202     length = p - string;
203     template.class = -1;
204     for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
205     if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength)
206     && (strncmp(string, dictPtr->name,
207     (size_t) length) == 0)) {
208     template.class = dictPtr->class;
209     break;
210     }
211     }
212     if (template.class == -1) {
213     Tcl_AppendResult(interp, "unknown or ambiguous visual name \"",
214     string, "\": class must be ", (char *) NULL);
215     for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
216     Tcl_AppendResult(interp, dictPtr->name, ", ", (char *) NULL);
217     }
218     Tcl_AppendResult(interp, "or default", (char *) NULL);
219     return NULL;
220     }
221     while (isspace(UCHAR(*p))) {
222     p++;
223     }
224     if (*p == 0) {
225     template.depth = 10000;
226     } else {
227     if (Tcl_GetInt(interp, p, &template.depth) != TCL_OK) {
228     return NULL;
229     }
230     }
231     if (c == 'b') {
232     mask = 0;
233     } else {
234     mask = VisualClassMask;
235     }
236     }
237    
238     /*
239     * Find all visuals that match the template we've just created,
240     * and return an error if there are none that match.
241     */
242    
243     template.screen = Tk_ScreenNumber(tkwin);
244     mask |= VisualScreenMask;
245     visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &template,
246     &numVisuals);
247     if (visInfoList == NULL) {
248     Tcl_SetResult(interp, "couldn't find an appropriate visual",
249     TCL_STATIC);
250     return NULL;
251     }
252    
253     /*
254     * Search through the visuals that were returned to find the best
255     * one. The choice is based on the following criteria, in decreasing
256     * order of importance:
257     *
258     * 1. Depth: choose a visual with exactly the desired depth,
259     * else one with more bits than requested but as few bits
260     * as possible, else one with fewer bits but as many as
261     * possible.
262     * 2. Class: some visual classes are more desirable than others;
263     * pick the visual with the most desirable class.
264     * 3. Default: the default visual for the screen gets preference
265     * over other visuals, all else being equal.
266     */
267    
268     bestPrio = 0;
269     bestPtr = NULL;
270     for (i = 0; i < numVisuals; i++) {
271     switch (visInfoList[i].class) {
272     case DirectColor: prio = 5; break;
273     case GrayScale: prio = 1; break;
274     case PseudoColor: prio = 7; break;
275     case StaticColor: prio = 3; break;
276     case StaticGray: prio = 1; break;
277     case TrueColor: prio = 5; break;
278     default: prio = 0; break;
279     }
280     if (visInfoList[i].visual
281     == DefaultVisualOfScreen(Tk_Screen(tkwin))) {
282     prio++;
283     }
284     if (bestPtr == NULL) {
285     goto newBest;
286     }
287     if (visInfoList[i].depth < bestPtr->depth) {
288     if (visInfoList[i].depth >= template.depth) {
289     goto newBest;
290     }
291     } else if (visInfoList[i].depth > bestPtr->depth) {
292     if (bestPtr->depth < template.depth) {
293     goto newBest;
294     }
295     } else {
296     if (prio > bestPrio) {
297     goto newBest;
298     }
299     }
300     continue;
301    
302     newBest:
303     bestPtr = &visInfoList[i];
304     bestPrio = prio;
305     }
306     *depthPtr = bestPtr->depth;
307     visual = bestPtr->visual;
308     XFree((char *) visInfoList);
309    
310     /*
311     * If we need to find a colormap for this visual, do it now.
312     * If the visual is the default visual for the screen, then
313     * use the default colormap. Otherwise search for an existing
314     * colormap that's shareable. If all else fails, create a new
315     * colormap.
316     */
317    
318     if (colormapPtr != NULL) {
319     if (visual == DefaultVisualOfScreen(Tk_Screen(tkwin))) {
320     *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));
321     } else {
322     for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
323     cmapPtr = cmapPtr->nextPtr) {
324     if (cmapPtr->shareable && (cmapPtr->visual == visual)) {
325     *colormapPtr = cmapPtr->colormap;
326     cmapPtr->refCount += 1;
327     goto done;
328     }
329     }
330     cmapPtr = (TkColormap *) ckalloc(sizeof(TkColormap));
331     cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
332     RootWindowOfScreen(Tk_Screen(tkwin)), visual,
333     AllocNone);
334     cmapPtr->visual = visual;
335     cmapPtr->refCount = 1;
336     cmapPtr->shareable = 1;
337     cmapPtr->nextPtr = dispPtr->cmapPtr;
338     dispPtr->cmapPtr = cmapPtr;
339     *colormapPtr = cmapPtr->colormap;
340     }
341     }
342    
343     done:
344     return visual;
345     }
346    
347     /*
348     *----------------------------------------------------------------------
349     *
350     * Tk_GetColormap --
351     *
352     * Given a string identifying a colormap, this procedure finds
353     * an appropriate colormap.
354     *
355     * Results:
356     * The return value is normally the X resource identifier for the
357     * colormap. If an error occurs, None is returned and an error
358     * message is placed in the interp's result.
359     *
360     * Side effects:
361     * A reference count is incremented for the colormap, so
362     * Tk_FreeColormap must eventually be called exactly once for
363     * each call to Tk_GetColormap.
364     *
365     *----------------------------------------------------------------------
366     */
367    
368     Colormap
369     Tk_GetColormap(interp, tkwin, string)
370     Tcl_Interp *interp; /* Interpreter to use for error
371     * reporting. */
372     Tk_Window tkwin; /* Window where colormap will be
373     * used. */
374     char *string; /* String that identifies colormap:
375     * either "new" or the name of
376     * another window. */
377     {
378     Colormap colormap;
379     TkColormap *cmapPtr;
380     TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
381     Tk_Window other;
382    
383     /*
384     * Allocate a new colormap, if that's what is wanted.
385     */
386    
387     if (strcmp(string, "new") == 0) {
388     cmapPtr = (TkColormap *) ckalloc(sizeof(TkColormap));
389     cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
390     RootWindowOfScreen(Tk_Screen(tkwin)), Tk_Visual(tkwin),
391     AllocNone);
392     cmapPtr->visual = Tk_Visual(tkwin);
393     cmapPtr->refCount = 1;
394     cmapPtr->shareable = 0;
395     cmapPtr->nextPtr = dispPtr->cmapPtr;
396     dispPtr->cmapPtr = cmapPtr;
397     return cmapPtr->colormap;
398     }
399    
400     /*
401     * Use a colormap from an existing window. It must have the same
402     * visual as tkwin (which means, among other things, that the
403     * other window must be on the same screen).
404     */
405    
406     other = Tk_NameToWindow(interp, string, tkwin);
407     if (other == NULL) {
408     return None;
409     }
410     if (Tk_Screen(other) != Tk_Screen(tkwin)) {
411     Tcl_AppendResult(interp, "can't use colormap for ", string,
412     ": not on same screen", (char *) NULL);
413     return None;
414     }
415     if (Tk_Visual(other) != Tk_Visual(tkwin)) {
416     Tcl_AppendResult(interp, "can't use colormap for ", string,
417     ": incompatible visuals", (char *) NULL);
418     return None;
419     }
420     colormap = Tk_Colormap(other);
421    
422     /*
423     * If the colormap was a special one allocated by code in this file,
424     * increment its reference count.
425     */
426    
427     for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
428     cmapPtr = cmapPtr->nextPtr) {
429     if (cmapPtr->colormap == colormap) {
430     cmapPtr->refCount += 1;
431     }
432     }
433     return colormap;
434     }
435    
436     /*
437     *----------------------------------------------------------------------
438     *
439     * Tk_FreeColormap --
440     *
441     * This procedure is called to release a colormap that was
442     * previously allocated by Tk_GetColormap.
443     *
444     * Results:
445     * None.
446     *
447     * Side effects:
448     * The colormap's reference count is decremented. If this was the
449     * last reference to the colormap, then the colormap is freed.
450     *
451     *----------------------------------------------------------------------
452     */
453    
454     void
455     Tk_FreeColormap(display, colormap)
456     Display *display; /* Display for which colormap was
457     * allocated. */
458     Colormap colormap; /* Colormap that is no longer needed.
459     * Must have been returned by previous
460     * call to Tk_GetColormap, or
461     * preserved by a previous call to
462     * Tk_PreserveColormap. */
463     {
464     TkDisplay *dispPtr;
465     TkColormap *cmapPtr, *prevPtr;
466    
467     /*
468     * Find Tk's information about the display, then see if this
469     * colormap is a non-default one (if it's a default one, there
470     * won't be an entry for it in the display's list).
471     */
472    
473     dispPtr = TkGetDisplay(display);
474     if (dispPtr == NULL) {
475     panic("unknown display passed to Tk_FreeColormap");
476     }
477     for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
478     prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) {
479     if (cmapPtr->colormap == colormap) {
480     cmapPtr->refCount -= 1;
481     if (cmapPtr->refCount == 0) {
482     XFreeColormap(display, colormap);
483     if (prevPtr == NULL) {
484     dispPtr->cmapPtr = cmapPtr->nextPtr;
485     } else {
486     prevPtr->nextPtr = cmapPtr->nextPtr;
487     }
488     ckfree((char *) cmapPtr);
489     }
490     return;
491     }
492     }
493     }
494    
495     /*
496     *----------------------------------------------------------------------
497     *
498     * Tk_PreserveColormap --
499     *
500     * This procedure is called to indicate to Tk that the specified
501     * colormap is being referenced from another location and should
502     * not be freed until all extra references are eliminated. The
503     * colormap must have been returned by Tk_GetColormap.
504     *
505     * Results:
506     * None.
507     *
508     * Side effects:
509     * The colormap's reference count is incremented, so
510     * Tk_FreeColormap must eventually be called exactly once for
511     * each call to Tk_PreserveColormap.
512     *
513     *----------------------------------------------------------------------
514     */
515    
516     void
517     Tk_PreserveColormap(display, colormap)
518     Display *display; /* Display for which colormap was
519     * allocated. */
520     Colormap colormap; /* Colormap that should be
521     * preserved. */
522     {
523     TkDisplay *dispPtr;
524     TkColormap *cmapPtr;
525    
526     /*
527     * Find Tk's information about the display, then see if this
528     * colormap is a non-default one (if it's a default one, there
529     * won't be an entry for it in the display's list).
530     */
531    
532     dispPtr = TkGetDisplay(display);
533     if (dispPtr == NULL) {
534     panic("unknown display passed to Tk_PreserveColormap");
535     }
536     for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
537     cmapPtr = cmapPtr->nextPtr) {
538     if (cmapPtr->colormap == colormap) {
539     cmapPtr->refCount += 1;
540     return;
541     }
542     }
543     }
544    
545    
546     /* $History: tkVisual.c $
547     *
548     * ***************** Version 1 *****************
549     * User: Dtashley Date: 1/02/01 Time: 3:12a
550     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
551     * Initial check-in.
552     */
553    
554     /* End of TKVISUAL.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25