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

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkvisual.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations) (download)
Fri Oct 14 02:09:58 2016 UTC (8 years, 1 month ago) by dashley
File MIME type: text/plain
File size: 16896 byte(s)
Rename for reorganization.
1 /* $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