OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [generic/] [tkVisual.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.