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

Contents of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkwincolor.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 98 - (show annotations) (download)
Sun Dec 18 00:57:31 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: text/plain
File size: 16761 byte(s)
Reorganization.
1 /* $Header$ */
2
3 /*
4 * tkWinColor.c --
5 *
6 * Functions to map color names to system color values.
7 *
8 * Copyright (c) 1995 Sun Microsystems, Inc.
9 * Copyright (c) 1994 Software Research Associates, 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: tkwincolor.c,v 1.1.1.1 2001/06/13 05:12:03 dtashley Exp $
15 */
16
17 #include "tkWinInt.h"
18 #include "tkColor.h"
19
20 /*
21 * The following structure is used to keep track of each color that is
22 * allocated by this module.
23 */
24
25 typedef struct WinColor {
26 TkColor info; /* Generic color information. */
27 int index; /* Index for GetSysColor(), -1 if color
28 * is not a "live" system color. */
29 } WinColor;
30
31 /*
32 * The sysColors array contains the names and index values for the
33 * Windows indirect system color names. In use, all of the names
34 * will have the string "System" prepended, but we omit it in the table
35 * to save space.
36 */
37
38 typedef struct {
39 char *name;
40 int index;
41 } SystemColorEntry;
42
43
44 static SystemColorEntry sysColors[] = {
45 "3dDarkShadow", COLOR_3DDKSHADOW,
46 "3dLight", COLOR_3DLIGHT,
47 "ActiveBorder", COLOR_ACTIVEBORDER,
48 "ActiveCaption", COLOR_ACTIVECAPTION,
49 "AppWorkspace", COLOR_APPWORKSPACE,
50 "Background", COLOR_BACKGROUND,
51 "ButtonFace", COLOR_BTNFACE,
52 "ButtonHighlight", COLOR_BTNHIGHLIGHT,
53 "ButtonShadow", COLOR_BTNSHADOW,
54 "ButtonText", COLOR_BTNTEXT,
55 "CaptionText", COLOR_CAPTIONTEXT,
56 "DisabledText", COLOR_GRAYTEXT,
57 "GrayText", COLOR_GRAYTEXT,
58 "Highlight", COLOR_HIGHLIGHT,
59 "HighlightText", COLOR_HIGHLIGHTTEXT,
60 "InactiveBorder", COLOR_INACTIVEBORDER,
61 "InactiveCaption", COLOR_INACTIVECAPTION,
62 "InactiveCaptionText", COLOR_INACTIVECAPTIONTEXT,
63 "InfoBackground", COLOR_INFOBK,
64 "InfoText", COLOR_INFOTEXT,
65 "Menu", COLOR_MENU,
66 "MenuText", COLOR_MENUTEXT,
67 "Scrollbar", COLOR_SCROLLBAR,
68 "Window", COLOR_WINDOW,
69 "WindowFrame", COLOR_WINDOWFRAME,
70 "WindowText", COLOR_WINDOWTEXT,
71 NULL, 0
72 };
73
74 typedef struct ThreadSpecificData {
75 int ncolors;
76 } ThreadSpecificData;
77 static Tcl_ThreadDataKey dataKey;
78
79 /*
80 * Forward declarations for functions defined later in this file.
81 */
82
83 static int FindSystemColor _ANSI_ARGS_((const char *name,
84 XColor *colorPtr, int *indexPtr));
85 static int GetColorByName _ANSI_ARGS_((char *name, XColor *color));
86 static int GetColorByValue _ANSI_ARGS_((char *value, XColor *color));
87
88 /*
89 *----------------------------------------------------------------------
90 *
91 * FindSystemColor --
92 *
93 * This routine finds the color entry that corresponds to the
94 * specified color.
95 *
96 * Results:
97 * Returns non-zero on success. The RGB values of the XColor
98 * will be initialized to the proper values on success.
99 *
100 * Side effects:
101 * None.
102 *
103 *----------------------------------------------------------------------
104 */
105
106 static int
107 FindSystemColor(name, colorPtr, indexPtr)
108 const char *name; /* Color name. */
109 XColor *colorPtr; /* Where to store results. */
110 int *indexPtr; /* Out parameter to store color index. */
111 {
112 int l, u, r, i;
113 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
114 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
115
116 /*
117 * Count the number of elements in the color array if we haven't
118 * done so yet.
119 */
120
121 if (tsdPtr->ncolors == 0) {
122 SystemColorEntry *ePtr;
123 int version;
124
125 version = LOBYTE(LOWORD(GetVersion()));
126 for (ePtr = sysColors; ePtr->name != NULL; ePtr++) {
127 if (version < 4) {
128 if (ePtr->index == COLOR_3DDKSHADOW) {
129 ePtr->index = COLOR_BTNSHADOW;
130 } else if (ePtr->index == COLOR_3DLIGHT) {
131 ePtr->index = COLOR_BTNHIGHLIGHT;
132 }
133 }
134 tsdPtr->ncolors++;
135 }
136 }
137
138 /*
139 * Perform a binary search on the sorted array of colors.
140 */
141
142 l = 0;
143 u = tsdPtr->ncolors - 1;
144 while (l <= u) {
145 i = (l + u) / 2;
146 r = strcasecmp(name, sysColors[i].name);
147 if (r == 0) {
148 break;
149 } else if (r < 0) {
150 u = i-1;
151 } else {
152 l = i+1;
153 }
154 }
155 if (l > u) {
156 return 0;
157 }
158
159 *indexPtr = sysColors[i].index;
160 colorPtr->pixel = GetSysColor(sysColors[i].index);
161 /*
162 * x257 is (value<<8 + value) to get the properly bit shifted
163 * and padded value. [Bug: 4919]
164 */
165 colorPtr->red = GetRValue(colorPtr->pixel) * 257;
166 colorPtr->green = GetGValue(colorPtr->pixel) * 257;
167 colorPtr->blue = GetBValue(colorPtr->pixel) * 257;
168 colorPtr->flags = DoRed|DoGreen|DoBlue;
169 colorPtr->pad = 0;
170 return 1;
171 }
172
173 /*
174 *----------------------------------------------------------------------
175 *
176 * TkpGetColor --
177 *
178 * Allocate a new TkColor for the color with the given name.
179 *
180 * Results:
181 * Returns a newly allocated TkColor, or NULL on failure.
182 *
183 * Side effects:
184 * May invalidate the colormap cache associated with tkwin upon
185 * allocating a new colormap entry. Allocates a new TkColor
186 * structure.
187 *
188 *----------------------------------------------------------------------
189 */
190
191 TkColor *
192 TkpGetColor(tkwin, name)
193 Tk_Window tkwin; /* Window in which color will be used. */
194 Tk_Uid name; /* Name of color to allocated (in form
195 * suitable for passing to XParseColor). */
196 {
197 WinColor *winColPtr;
198 XColor color;
199 int index = -1; /* -1 indicates that this is not an indirect
200 * sytem color. */
201
202 /*
203 * Check to see if it is a system color or an X color string. If the
204 * color is found, allocate a new WinColor and store the XColor and the
205 * system color index.
206 */
207
208 if (((strncasecmp(name, "system", 6) == 0)
209 && FindSystemColor(name+6, &color, &index))
210 || XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name,
211 &color)) {
212 winColPtr = (WinColor *) ckalloc(sizeof(WinColor));
213 winColPtr->info.color = color;
214 winColPtr->index = index;
215
216 XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
217 &winColPtr->info.color);
218 return (TkColor *) winColPtr;
219 }
220 return (TkColor *) NULL;
221 }
222
223 /*
224 *----------------------------------------------------------------------
225 *
226 * TkpGetColorByValue --
227 *
228 * Given a desired set of red-green-blue intensities for a color,
229 * locate a pixel value to use to draw that color in a given
230 * window.
231 *
232 * Results:
233 * The return value is a pointer to an TkColor structure that
234 * indicates the closest red, blue, and green intensities available
235 * to those specified in colorPtr, and also specifies a pixel
236 * value to use to draw in that color.
237 *
238 * Side effects:
239 * May invalidate the colormap cache for the specified window.
240 * Allocates a new TkColor structure.
241 *
242 *----------------------------------------------------------------------
243 */
244
245 TkColor *
246 TkpGetColorByValue(tkwin, colorPtr)
247 Tk_Window tkwin; /* Window in which color will be used. */
248 XColor *colorPtr; /* Red, green, and blue fields indicate
249 * desired color. */
250 {
251 WinColor *tkColPtr = (WinColor *) ckalloc(sizeof(WinColor));
252
253 tkColPtr->info.color.red = colorPtr->red;
254 tkColPtr->info.color.green = colorPtr->green;
255 tkColPtr->info.color.blue = colorPtr->blue;
256 tkColPtr->info.color.pixel = 0;
257 tkColPtr->index = -1;
258 XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin), &tkColPtr->info.color);
259 return (TkColor *) tkColPtr;
260 }
261
262 /*
263 *----------------------------------------------------------------------
264 *
265 * TkpFreeColor --
266 *
267 * Release the specified color back to the system.
268 *
269 * Results:
270 * None
271 *
272 * Side effects:
273 * Invalidates the colormap cache for the colormap associated with
274 * the given color.
275 *
276 *----------------------------------------------------------------------
277 */
278
279 void
280 TkpFreeColor(tkColPtr)
281 TkColor *tkColPtr; /* Color to be released. Must have been
282 * allocated by TkpGetColor or
283 * TkpGetColorByValue. */
284 {
285 Screen *screen = tkColPtr->screen;
286
287 XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,
288 &tkColPtr->color.pixel, 1, 0L);
289 }
290
291 /*
292 *----------------------------------------------------------------------
293 *
294 * TkWinIndexOfColor --
295 *
296 * Given a color, return the system color index that was used
297 * to create the color.
298 *
299 * Results:
300 * If the color was allocated using a system indirect color name,
301 * then the corresponding GetSysColor() index is returned.
302 * Otherwise, -1 is returned.
303 *
304 * Side effects:
305 * None.
306 *
307 *----------------------------------------------------------------------
308 */
309
310 int
311 TkWinIndexOfColor(colorPtr)
312 XColor *colorPtr;
313 {
314 register WinColor *winColPtr = (WinColor *) colorPtr;
315 if (winColPtr->info.magic == COLOR_MAGIC) {
316 return winColPtr->index;
317 }
318 return -1;
319 }
320
321 /*
322 *----------------------------------------------------------------------
323 *
324 * XAllocColor --
325 *
326 * Find the closest available color to the specified XColor.
327 *
328 * Results:
329 * Updates the color argument and returns 1 on success. Otherwise
330 * returns 0.
331 *
332 * Side effects:
333 * Allocates a new color in the palette.
334 *
335 *----------------------------------------------------------------------
336 */
337
338 int
339 XAllocColor(display, colormap, color)
340 Display* display;
341 Colormap colormap;
342 XColor* color;
343 {
344 TkWinColormap *cmap = (TkWinColormap *) colormap;
345 PALETTEENTRY entry, closeEntry;
346 HDC dc = GetDC(NULL);
347
348 entry.peRed = (color->red) >> 8;
349 entry.peGreen = (color->green) >> 8;
350 entry.peBlue = (color->blue) >> 8;
351 entry.peFlags = 0;
352
353 if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
354 unsigned long sizePalette = GetDeviceCaps(dc, SIZEPALETTE);
355 UINT newPixel, closePixel;
356 int new, refCount;
357 Tcl_HashEntry *entryPtr;
358 UINT index;
359
360 /*
361 * Find the nearest existing palette entry.
362 */
363
364 newPixel = RGB(entry.peRed, entry.peGreen, entry.peBlue);
365 index = GetNearestPaletteIndex(cmap->palette, newPixel);
366 GetPaletteEntries(cmap->palette, index, 1, &closeEntry);
367 closePixel = RGB(closeEntry.peRed, closeEntry.peGreen,
368 closeEntry.peBlue);
369
370 /*
371 * If this is not a duplicate, allocate a new entry. Note that
372 * we may get values for index that are above the current size
373 * of the palette. This happens because we don't shrink the size of
374 * the palette object when we deallocate colors so there may be
375 * stale values that match in the upper slots. We should ignore
376 * those values and just put the new color in as if the colors
377 * had not matched.
378 */
379
380 if ((index >= cmap->size) || (newPixel != closePixel)) {
381 if (cmap->size == sizePalette) {
382 color->red = closeEntry.peRed * 257;
383 color->green = closeEntry.peGreen * 257;
384 color->blue = closeEntry.peBlue * 257;
385 entry = closeEntry;
386 if (index >= cmap->size) {
387 OutputDebugString("XAllocColor: Colormap is bigger than we thought");
388 }
389 } else {
390 cmap->size++;
391 ResizePalette(cmap->palette, cmap->size);
392 SetPaletteEntries(cmap->palette, cmap->size - 1, 1, &entry);
393 }
394 }
395
396 color->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);
397 entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,
398 (char *) color->pixel, &new);
399 if (new) {
400 refCount = 1;
401 } else {
402 refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;
403 }
404 Tcl_SetHashValue(entryPtr, (ClientData)refCount);
405 } else {
406
407 /*
408 * Determine what color will actually be used on non-colormap systems.
409 */
410
411 color->pixel = GetNearestColor(dc,
412 RGB(entry.peRed, entry.peGreen, entry.peBlue));
413 color->red = GetRValue(color->pixel) * 257;
414 color->green = GetGValue(color->pixel) * 257;
415 color->blue = GetBValue(color->pixel) * 257;
416 }
417
418 ReleaseDC(NULL, dc);
419 return 1;
420 }
421
422 /*
423 *----------------------------------------------------------------------
424 *
425 * XFreeColors --
426 *
427 * Deallocate a block of colors.
428 *
429 * Results:
430 * None.
431 *
432 * Side effects:
433 * Removes entries for the current palette and compacts the
434 * remaining set.
435 *
436 *----------------------------------------------------------------------
437 */
438
439 void
440 XFreeColors(display, colormap, pixels, npixels, planes)
441 Display* display;
442 Colormap colormap;
443 unsigned long* pixels;
444 int npixels;
445 unsigned long planes;
446 {
447 TkWinColormap *cmap = (TkWinColormap *) colormap;
448 COLORREF cref;
449 UINT count, index, refCount;
450 int i;
451 PALETTEENTRY entry, *entries;
452 Tcl_HashEntry *entryPtr;
453 HDC dc = GetDC(NULL);
454
455 /*
456 * We don't have to do anything for non-palette devices.
457 */
458
459 if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
460
461 /*
462 * This is really slow for large values of npixels.
463 */
464
465 for (i = 0; i < npixels; i++) {
466 entryPtr = Tcl_FindHashEntry(&cmap->refCounts,
467 (char *) pixels[i]);
468 if (!entryPtr) {
469 panic("Tried to free a color that isn't allocated.");
470 }
471 refCount = (int) Tcl_GetHashValue(entryPtr) - 1;
472 if (refCount == 0) {
473 cref = pixels[i] & 0x00ffffff;
474 index = GetNearestPaletteIndex(cmap->palette, cref);
475 GetPaletteEntries(cmap->palette, index, 1, &entry);
476 if (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) {
477 count = cmap->size - index;
478 entries = (PALETTEENTRY *) ckalloc(sizeof(PALETTEENTRY)
479 * count);
480 GetPaletteEntries(cmap->palette, index+1, count, entries);
481 SetPaletteEntries(cmap->palette, index, count, entries);
482 ckfree((char *) entries);
483 cmap->size--;
484 } else {
485 panic("Tried to free a color that isn't allocated.");
486 }
487 Tcl_DeleteHashEntry(entryPtr);
488 } else {
489 Tcl_SetHashValue(entryPtr, (ClientData)refCount);
490 }
491 }
492 }
493 ReleaseDC(NULL, dc);
494 }
495
496 /*
497 *----------------------------------------------------------------------
498 *
499 * XCreateColormap --
500 *
501 * Allocate a new colormap.
502 *
503 * Results:
504 * Returns a newly allocated colormap.
505 *
506 * Side effects:
507 * Allocates an empty palette and color list.
508 *
509 *----------------------------------------------------------------------
510 */
511
512 Colormap
513 XCreateColormap(display, w, visual, alloc)
514 Display* display;
515 Window w;
516 Visual* visual;
517 int alloc;
518 {
519 char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
520 LOGPALETTE *logPalettePtr;
521 PALETTEENTRY *entryPtr;
522 TkWinColormap *cmap;
523 Tcl_HashEntry *hashPtr;
524 int new;
525 UINT i;
526 HPALETTE sysPal;
527
528 /*
529 * Allocate a starting palette with all of the reserved colors.
530 */
531
532 logPalettePtr = (LOGPALETTE *) logPalBuf;
533 logPalettePtr->palVersion = 0x300;
534 sysPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
535 logPalettePtr->palNumEntries = GetPaletteEntries(sysPal, 0, 256,
536 logPalettePtr->palPalEntry);
537
538 cmap = (TkWinColormap *) ckalloc(sizeof(TkWinColormap));
539 cmap->size = logPalettePtr->palNumEntries;
540 cmap->stale = 0;
541 cmap->palette = CreatePalette(logPalettePtr);
542
543 /*
544 * Add hash entries for each of the static colors.
545 */
546
547 Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
548 for (i = 0; i < logPalettePtr->palNumEntries; i++) {
549 entryPtr = logPalettePtr->palPalEntry + i;
550 hashPtr = Tcl_CreateHashEntry(&cmap->refCounts, (char*) PALETTERGB(
551 entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue), &new);
552 Tcl_SetHashValue(hashPtr, (ClientData)1);
553 }
554
555 return (Colormap)cmap;
556 }
557
558 /*
559 *----------------------------------------------------------------------
560 *
561 * XFreeColormap --
562 *
563 * Frees the resources associated with the given colormap.
564 *
565 * Results:
566 * None.
567 *
568 * Side effects:
569 * Deletes the palette associated with the colormap. Note that
570 * the palette must not be selected into a device context when
571 * this occurs.
572 *
573 *----------------------------------------------------------------------
574 */
575
576 void
577 XFreeColormap(display, colormap)
578 Display* display;
579 Colormap colormap;
580 {
581 TkWinColormap *cmap = (TkWinColormap *) colormap;
582 if (!DeleteObject(cmap->palette)) {
583 panic("Unable to free colormap, palette is still selected.");
584 }
585 Tcl_DeleteHashTable(&cmap->refCounts);
586 ckfree((char *) cmap);
587 }
588
589 /*
590 *----------------------------------------------------------------------
591 *
592 * TkWinSelectPalette --
593 *
594 * This function sets up the specified device context with a
595 * given palette. If the palette is stale, it realizes it in
596 * the background unless the palette is the current global
597 * palette.
598 *
599 * Results:
600 * Returns the previous palette selected into the device context.
601 *
602 * Side effects:
603 * May change the system palette.
604 *
605 *----------------------------------------------------------------------
606 */
607
608 HPALETTE
609 TkWinSelectPalette(dc, colormap)
610 HDC dc;
611 Colormap colormap;
612 {
613 TkWinColormap *cmap = (TkWinColormap *) colormap;
614 HPALETTE oldPalette;
615
616 oldPalette = SelectPalette(dc, cmap->palette,
617 (cmap->palette == TkWinGetSystemPalette()) ? FALSE : TRUE);
618 RealizePalette(dc);
619 return oldPalette;
620 }
621
622 /* End of tkwincolor.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25