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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkColor.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkColor.c --
3
 *
4
 *      This file maintains a database of color values for the Tk
5
 *      toolkit, in order to avoid round-trips to the server to
6
 *      map color names to pixel values.
7
 *
8
 * Copyright (c) 1990-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: tkColor.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
15
 */
16
 
17
#include <tkColor.h>
18
 
19
/*
20
 * A two-level data structure is used to manage the color database.
21
 * The top level consists of one entry for each color name that is
22
 * currently active, and the bottom level contains one entry for each
23
 * pixel value that is still in use.  The distinction between
24
 * levels is necessary because the same pixel may have several
25
 * different names.  There are two hash tables, one used to index into
26
 * each of the data structures.  The name hash table is used when
27
 * allocating colors, and the pixel hash table is used when freeing
28
 * colors.
29
 */
30
 
31
 
32
/*
33
 * Hash table for name -> TkColor mapping, and key structure used to
34
 * index into that table:
35
 */
36
 
37
static Tcl_HashTable nameTable;
38
typedef struct {
39
    Tk_Uid name;                /* Name of desired color. */
40
    Colormap colormap;          /* Colormap from which color will be
41
                                 * allocated. */
42
    Display *display;           /* Display for colormap. */
43
} NameKey;
44
 
45
/*
46
 * Hash table for value -> TkColor mapping, and key structure used to
47
 * index into that table:
48
 */
49
 
50
static Tcl_HashTable valueTable;
51
typedef struct {
52
    int red, green, blue;       /* Values for desired color. */
53
    Colormap colormap;          /* Colormap from which color will be
54
                                 * allocated. */
55
    Display *display;           /* Display for colormap. */
56
} ValueKey;
57
 
58
static int initialized = 0;      /* 0 means static structures haven't been
59
                                 * initialized yet. */
60
 
61
/*
62
 * Forward declarations for procedures defined in this file:
63
 */
64
 
65
static void             ColorInit _ANSI_ARGS_((void));
66
 
67
/* CYGNUS LOCAL.  */
68
 
69
/* A linked list of GC structures.  */
70
 
71
struct TkGCList {
72
    /* Next item on list.  */
73
    TkGCList *next;
74
    /* The display for the GC.  */
75
    Display *display;
76
    /* The GC.  */
77
    GC gc;
78
    /* GCForeground or GCBackground.  */
79
    unsigned long mask;
80
};
81
 
82
/* END CYGNUS LOCAL */
83
 
84
/*
85
 *----------------------------------------------------------------------
86
 *
87
 * Tk_GetColor --
88
 *
89
 *      Given a string name for a color, map the name to a corresponding
90
 *      XColor structure.
91
 *
92
 * Results:
93
 *      The return value is a pointer to an XColor structure that
94
 *      indicates the red, blue, and green intensities for the color
95
 *      given by "name", and also specifies a pixel value to use to
96
 *      draw in that color.  If an error occurs, NULL is returned and
97
 *      an error message will be left in interp->result.
98
 *
99
 * Side effects:
100
 *      The color is added to an internal database with a reference count.
101
 *      For each call to this procedure, there should eventually be a call
102
 *      to Tk_FreeColor so that the database is cleaned up when colors
103
 *      aren't in use anymore.
104
 *
105
 *----------------------------------------------------------------------
106
 */
107
 
108
XColor *
109
Tk_GetColor(interp, tkwin, name)
110
    Tcl_Interp *interp;         /* Place to leave error message if
111
                                 * color can't be found. */
112
    Tk_Window tkwin;            /* Window in which color will be used. */
113
    Tk_Uid name;                /* Name of color to allocated (in form
114
                                 * suitable for passing to XParseColor). */
115
{
116
    NameKey nameKey;
117
    Tcl_HashEntry *nameHashPtr;
118
    int new;
119
    TkColor *tkColPtr;
120
    Display *display = Tk_Display(tkwin);
121
 
122
    if (!initialized) {
123
        ColorInit();
124
    }
125
 
126
    /*
127
     * First, check to see if there's already a mapping for this color
128
     * name.
129
     */
130
 
131
    nameKey.name = name;
132
    nameKey.colormap = Tk_Colormap(tkwin);
133
    nameKey.display = display;
134
    nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
135
    if (!new) {
136
        tkColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr);
137
        tkColPtr->refCount++;
138
        return &tkColPtr->color;
139
    }
140
 
141
    /*
142
     * The name isn't currently known.  Map from the name to a pixel
143
     * value.
144
     */
145
 
146
    tkColPtr = TkpGetColor(tkwin, name);
147
    if (tkColPtr == NULL) {
148
        if (interp != NULL) {
149
            if (*name == '#') {
150
                Tcl_AppendResult(interp, "invalid color name \"", name,
151
                        "\"", (char *) NULL);
152
            } else {
153
                Tcl_AppendResult(interp, "unknown color name \"", name,
154
                        "\"", (char *) NULL);
155
            }
156
        }
157
        Tcl_DeleteHashEntry(nameHashPtr);
158
        return (XColor *) NULL;
159
    }
160
 
161
    /*
162
     * Now create a new TkColor structure and add it to nameTable.
163
     */
164
 
165
    tkColPtr->magic = COLOR_MAGIC;
166
    tkColPtr->gc = None;
167
    tkColPtr->screen = Tk_Screen(tkwin);
168
    tkColPtr->colormap = nameKey.colormap;
169
    tkColPtr->visual  = Tk_Visual(tkwin);
170
    tkColPtr->refCount = 1;
171
    tkColPtr->tablePtr = &nameTable;
172
    tkColPtr->hashPtr = nameHashPtr;
173
    tkColPtr->gcList = NULL;
174
    Tcl_SetHashValue(nameHashPtr, tkColPtr);
175
 
176
    return &tkColPtr->color;
177
}
178
 
179
/*
180
 *----------------------------------------------------------------------
181
 *
182
 * Tk_GetColorByValue --
183
 *
184
 *      Given a desired set of red-green-blue intensities for a color,
185
 *      locate a pixel value to use to draw that color in a given
186
 *      window.
187
 *
188
 * Results:
189
 *      The return value is a pointer to an XColor structure that
190
 *      indicates the closest red, blue, and green intensities available
191
 *      to those specified in colorPtr, and also specifies a pixel
192
 *      value to use to draw in that color.
193
 *
194
 * Side effects:
195
 *      The color is added to an internal database with a reference count.
196
 *      For each call to this procedure, there should eventually be a call
197
 *      to Tk_FreeColor, so that the database is cleaned up when colors
198
 *      aren't in use anymore.
199
 *
200
 *----------------------------------------------------------------------
201
 */
202
 
203
XColor *
204
Tk_GetColorByValue(tkwin, colorPtr)
205
    Tk_Window tkwin;            /* Window where color will be used. */
206
    XColor *colorPtr;           /* Red, green, and blue fields indicate
207
                                 * desired color. */
208
{
209
    ValueKey valueKey;
210
    Tcl_HashEntry *valueHashPtr;
211
    int new;
212
    TkColor *tkColPtr;
213
    Display *display = Tk_Display(tkwin);
214
 
215
    if (!initialized) {
216
        ColorInit();
217
    }
218
 
219
    /*
220
     * First, check to see if there's already a mapping for this color
221
     * name.
222
     */
223
 
224
    valueKey.red = colorPtr->red;
225
    valueKey.green = colorPtr->green;
226
    valueKey.blue = colorPtr->blue;
227
    valueKey.colormap = Tk_Colormap(tkwin);
228
    valueKey.display = display;
229
    valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new);
230
    if (!new) {
231
        tkColPtr = (TkColor *) Tcl_GetHashValue(valueHashPtr);
232
        tkColPtr->refCount++;
233
        return &tkColPtr->color;
234
    }
235
 
236
    /*
237
     * The name isn't currently known.  Find a pixel value for this
238
     * color and add a new structure to valueTable.
239
     */
240
 
241
    tkColPtr = TkpGetColorByValue(tkwin, colorPtr);
242
    tkColPtr->magic = COLOR_MAGIC;
243
    tkColPtr->gc = None;
244
    tkColPtr->screen = Tk_Screen(tkwin);
245
    tkColPtr->colormap = valueKey.colormap;
246
    tkColPtr->visual  = Tk_Visual(tkwin);
247
    tkColPtr->refCount = 1;
248
    tkColPtr->tablePtr = &valueTable;
249
    tkColPtr->hashPtr = valueHashPtr;
250
    tkColPtr->gcList = NULL;
251
    Tcl_SetHashValue(valueHashPtr, tkColPtr);
252
    return &tkColPtr->color;
253
}
254
 
255
/*
256
 *--------------------------------------------------------------
257
 *
258
 * Tk_NameOfColor --
259
 *
260
 *      Given a color, return a textual string identifying
261
 *      the color.
262
 *
263
 * Results:
264
 *      If colorPtr was created by Tk_GetColor, then the return
265
 *      value is the "string" that was used to create it.
266
 *      Otherwise the return value is a string that could have
267
 *      been passed to Tk_GetColor to allocate that color.  The
268
 *      storage for the returned string is only guaranteed to
269
 *      persist up until the next call to this procedure.
270
 *
271
 * Side effects:
272
 *      None.
273
 *
274
 *--------------------------------------------------------------
275
 */
276
 
277
char *
278
Tk_NameOfColor(colorPtr)
279
    XColor *colorPtr;           /* Color whose name is desired. */
280
{
281
    register TkColor *tkColPtr = (TkColor *) colorPtr;
282
    static char string[20];
283
 
284
    if ((tkColPtr->magic == COLOR_MAGIC)
285
            && (tkColPtr->tablePtr == &nameTable)) {
286
        return ((NameKey *) tkColPtr->hashPtr->key.words)->name;
287
    }
288
    sprintf(string, "#%04x%04x%04x", colorPtr->red, colorPtr->green,
289
            colorPtr->blue);
290
    return string;
291
}
292
 
293
/*
294
 *----------------------------------------------------------------------
295
 *
296
 * Tk_GCForColor --
297
 *
298
 *      Given a color allocated from this module, this procedure
299
 *      returns a GC that can be used for simple drawing with that
300
 *      color.
301
 *
302
 * Results:
303
 *      The return value is a GC with color set as its foreground
304
 *      color and all other fields defaulted.  This GC is only valid
305
 *      as long as the color exists;  it is freed automatically when
306
 *      the last reference to the color is freed.
307
 *
308
 * Side effects:
309
 *      None.
310
 *
311
 *----------------------------------------------------------------------
312
 */
313
 
314
GC
315
Tk_GCForColor(colorPtr, drawable)
316
    XColor *colorPtr;           /* Color for which a GC is desired. Must
317
                                 * have been allocated by Tk_GetColor or
318
                                 * Tk_GetColorByName. */
319
    Drawable drawable;          /* Drawable in which the color will be
320
                                 * used (must have same screen and depth
321
                                 * as the one for which the color was
322
                                 * allocated). */
323
{
324
    TkColor *tkColPtr = (TkColor *) colorPtr;
325
    XGCValues gcValues;
326
 
327
    /*
328
     * Do a quick sanity check to make sure this color was really
329
     * allocated by Tk_GetColor.
330
     */
331
 
332
    if (tkColPtr->magic != COLOR_MAGIC) {
333
        panic("Tk_GCForColor called with bogus color");
334
    }
335
 
336
    if (tkColPtr->gc == None) {
337
        gcValues.foreground = tkColPtr->color.pixel;
338
        tkColPtr->gc = XCreateGC(DisplayOfScreen(tkColPtr->screen),
339
                drawable, GCForeground, &gcValues);
340
    }
341
    return tkColPtr->gc;
342
}
343
 
344
/*
345
 *----------------------------------------------------------------------
346
 *
347
 * Tk_FreeColor --
348
 *
349
 *      This procedure is called to release a color allocated by
350
 *      Tk_GetColor.
351
 *
352
 * Results:
353
 *      None.
354
 *
355
 * Side effects:
356
 *      The reference count associated with colorPtr is deleted, and
357
 *      the color is released to X if there are no remaining uses
358
 *      for it.
359
 *
360
 *----------------------------------------------------------------------
361
 */
362
 
363
void
364
Tk_FreeColor(colorPtr)
365
    XColor *colorPtr;           /* Color to be released.  Must have been
366
                                 * allocated by Tk_GetColor or
367
                                 * Tk_GetColorByValue. */
368
{
369
    register TkColor *tkColPtr = (TkColor *) colorPtr;
370
    Screen *screen = tkColPtr->screen;
371
 
372
    /*
373
     * Do a quick sanity check to make sure this color was really
374
     * allocated by Tk_GetColor.
375
     */
376
 
377
    if (tkColPtr->magic != COLOR_MAGIC) {
378
        panic("Tk_FreeColor called with bogus color");
379
    }
380
 
381
    tkColPtr->refCount--;
382
    if (tkColPtr->refCount == 0) {
383
        if (tkColPtr->gc != None) {
384
            XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
385
            tkColPtr->gc = None;
386
        }
387
        TkpFreeColor(tkColPtr);
388
        Tcl_DeleteHashEntry(tkColPtr->hashPtr);
389
        tkColPtr->magic = 0;
390
        ckfree((char *) tkColPtr);
391
    }
392
}
393
 
394
/*
395
 *----------------------------------------------------------------------
396
 *
397
 * ColorInit --
398
 *
399
 *      Initialize the structure used for color management.
400
 *
401
 * Results:
402
 *      None.
403
 *
404
 * Side effects:
405
 *      Read the code.
406
 *
407
 *----------------------------------------------------------------------
408
 */
409
 
410
static void
411
ColorInit()
412
{
413
    initialized = 1;
414
    Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
415
    Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
416
}
417
 
418
/* CYGNUS LOCAL: Call a function on every named color.  This is used
419
   on Windows to change the colors when the user changes them via the
420
   control panel.  */
421
 
422
void
423
TkMapOverColors(func)
424
    void (*func) _ANSI_ARGS_((TkColor *));
425
{
426
    Tcl_HashEntry *nameHashPtr;
427
    Tcl_HashSearch search;
428
    TkColor *tkColPtr;
429
 
430
    nameHashPtr = Tcl_FirstHashEntry(&nameTable, &search);
431
    while (nameHashPtr != NULL) {
432
        tkColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr);
433
        (*func)(tkColPtr);
434
        nameHashPtr = Tcl_NextHashEntry(&search);
435
    }
436
}
437
 
438
/* CYGNUS LOCAL: For each color, we keep a list of GCs that use that
439
   color as the foreground or background.  This is so that we can
440
   change them on Windows when the user changes the system colors.  */
441
 
442
void
443
TkRegisterColorGC(colorPtr, display, gc, valueMask)
444
    XColor *colorPtr;
445
    Display *display;
446
    GC gc;
447
    unsigned long valueMask;
448
{
449
    TkColor *tkColPtr = (TkColor *) colorPtr;
450
    TkGCList *gcListPtr;
451
 
452
    if (tkColPtr->magic != COLOR_MAGIC) {
453
        return;
454
    }
455
 
456
    gcListPtr = (TkGCList *) ckalloc(sizeof(TkGCList));
457
    gcListPtr->display = display;
458
    gcListPtr->gc = gc;
459
    gcListPtr->mask = valueMask;
460
    gcListPtr->next = tkColPtr->gcList;
461
    tkColPtr->gcList = gcListPtr;
462
 
463
    /* Each GC added to the list counts as a reference to the color,
464
       so that we don't free the color before freeing the GC.  */
465
 
466
    tkColPtr->refCount++;
467
}
468
 
469
/* This is called when a GC with a registered color is deleted.  */
470
 
471
void
472
TkDeregisterColorGC(colorPtr, gc, valueMask)
473
    XColor *colorPtr;
474
    GC gc;
475
    unsigned long valueMask;
476
{
477
    TkColor *tkColPtr = (TkColor *) colorPtr;
478
    TkGCList **gcListPtrPtr, *gcListPtr;
479
 
480
    if (tkColPtr->magic != COLOR_MAGIC) {
481
        return;
482
    }
483
 
484
    for (gcListPtrPtr = &tkColPtr->gcList;
485
         *gcListPtrPtr != NULL;
486
         gcListPtrPtr = &(*gcListPtrPtr)->next) {
487
        if ((*gcListPtrPtr)->gc == gc && (*gcListPtrPtr)->mask == valueMask) {
488
            gcListPtr = *gcListPtrPtr;
489
            *gcListPtrPtr = gcListPtr->next;
490
            ckfree((char *) gcListPtr);
491
            Tk_FreeColor((XColor *) tkColPtr);
492
            break;
493
        }
494
    }
495
}
496
 
497
/* This is called when a color is changed by the user on Windows.  */
498
 
499
void
500
TkColorChanged(tkColPtr)
501
    TkColor *tkColPtr;
502
{
503
    TkGCList *gcListPtr;
504
    XGCValues gcValues;
505
 
506
    for (gcListPtr = tkColPtr->gcList;
507
         gcListPtr != NULL;
508
         gcListPtr = gcListPtr->next) {
509
        if (gcListPtr->mask == GCForeground) {
510
            gcValues.foreground = tkColPtr->color.pixel;
511
        } else {
512
            gcValues.background = tkColPtr->color.pixel;
513
        }
514
 
515
        XChangeGC(gcListPtr->display, gcListPtr->gc, gcListPtr->mask,
516
                  &gcValues);
517
    }
518
 
519
    if (tkColPtr->gc != None) {
520
        gcValues.foreground = tkColPtr->color.pixel;
521
        XChangeGC(DisplayOfScreen(tkColPtr->screen), tkColPtr->gc,
522
                  GCForeground, &gcValues);
523
    }
524
}

powered by: WebSVN 2.1.0

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