1 /*
2 * XFrisk - The classic board game for X
3 * Copyright (C) 1993-1999 Elan Feingold (elan@aetherworks.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * $Id: colormap.c,v 1.18 2000/01/15 21:13:35 morphy Exp $
20 *
21 * $Log: colormap.c,v $
22 * Revision 1.18 2000/01/15 21:13:35 morphy
23 * Removed superfluous debug code
24 *
25 * Revision 1.17 2000/01/15 11:33:28 morphy
26 * Comments in doxygen format, minor clarity fixes in code
27 *
28 * Revision 1.16 2000/01/10 22:47:40 tony
29 * made colorstuff more private to colormap.c, only scrollbars get set wrong, rest seems to work ok now
30 *
31 * Revision 1.15 2000/01/09 20:05:02 morphy
32 * Corrections to color map loading - previously struct padding possibility was ignored
33 *
34 * Revision 1.14 2000/01/09 19:59:58 morphy
35 * Corrected bit operation brainfart
36 *
37 * Revision 1.13 2000/01/09 20:29:44 tony
38 * removed some more comments
39 *
40 * Revision 1.12 2000/01/09 19:24:36 morphy
41 * Editorial changes, removed dead code an superfluous temporary variables
42 *
43 * Revision 1.11 2000/01/08 18:49:04 tony
44 * oops
45 *
46 * Revision 1.10 2000/01/04 21:41:53 tony
47 * removed redundant stuff for jokers
48 *
49 * Revision 1.9 2000/01/02 15:59:36 tony
50 * truecolor mapiing fixed, rgbToNum was the one
51 *
52 * Revision 1.8 1999/12/26 23:13:24 tony
53 * some comments about colormaps, QueryColor().
54 * some cleaning up in COLOR_GetColormap()
55 */
56
57 /** \file
58 * Color mapping for XFrisk GUI
59 *
60 * \b See: http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/visuals.html#WHAT_VISUAL
61 *
62 * \b From: http://www.motifzone.com/resources/man/XAllocStandardColormap.html
63 *
64 * The colormap member is the colormap created by the
65 * XCreateColormap function. The red_max, green_max, and
66 * blue_max members give the maximum red, green, and blue
67 * values, respectively. Each color coefficient ranges from
68 * zero to its max, inclusive. For example, a common colormap
69 * allocation is 3/3/2 (3 planes for red, 3 planes for green,
70 * and 2 planes for blue). This colormap would have red_max =
71 * 7, green_max = 7, and blue_max = 3. An alternate allocation
72 * that uses only 216 colors is red_max = 5, green_max = 5, and
73 * blue_max = 5.
74 *
75 * The red_mult, green_mult, and blue_mult members give the
76 * scale factors used to compose a full pixel value. (See the
77 * discussion of the base_pixel members for further informa-
78 * tion.) For a 3/3/2 allocation, red_mult might be 32,
79 * green_mult might be 4, and blue_mult might be 1. For a 6-
80 * colors-each allocation, red_mult might be 36, green_mult
81 * might be 6, and blue_mult might be 1.
82 *
83 * The base_pixel member gives the base pixel value used to
84 * compose a full pixel value. Usually, the base_pixel is
85 * obtained from a call to the XAllocColorPlanes function.
86 * Given integer red, green, and blue coefficients in their
87 * appropriate ranges, one then can compute a corresponding
88 * pixel value by using the following expression:
89 *
90 * (r * red_mult + g * green_mult + b * blue_mult + base_pixel) & 0xFFFFFFFF
91 *
92 */
93
94 #include <X11/X.h>
95 #include <X11/Intrinsic.h>
96 #include <X11/StringDefs.h>
97 #include <X11/Shell.h>
98
99 #include "colormap.h"
100 #include "client.h"
101 #include "utils.h"
102 #include "riskgame.h"
103 #include "gui-vars.h"
104 #include "debug.h"
105
106
107 /* Private data */
108
109 /**
110 * Fallback resource filename for use in discovering visual properties
111 * \bug Should use a globally defined filename macro
112 */
113 static CString strResources[] = {
114 #ifdef ENGLISH
115 #include "english.res"
116 #endif
117 #ifdef FRENCH
118 #include "french.res"
119 #endif
120 NULL
121 };
122
123 /** Color index to country index mapping table */
124 static Int32 piColorToCountry[MAX_COLORS];
125
126 /** Main color map */
127 static Color pWorldColors[MAX_COLORS];
128
129 /** Flag to indicate if display is true color */
130 static Flag trueColor = FALSE;
131
132 /** Colormap used in truecolor */
133 unsigned long colormap[MAX_COLORS];
134
135 /**
136 * Country index to color index mapping
137 * 42 countries, 1 ocean, 1 lines, 3 dice, x players...
138 * They must be long because that's how XAllocColorCells fills it
139 */
140 unsigned long plCountryToColor[MAX_COLORS];
141 Colormap cmapColormap = 0;
142 Int32 iNumColors;
143 Int32 COLOR_Depth;
144
145 /* Local variables for conversion between rgb and screen values. */
146 static int redShift, greenShift, blueShift;
147 static int redMove, greenMove, blueMove;
148 static Int32 redMask, greenMask, blueMask;
149
150
151 /**
152 * Returns number of used colors
153 */
COLOR_GetNumColors(void)154 Int32 COLOR_GetNumColors(void) {
155 return iNumColors;
156 }
157
158
159 /**
160 * Sets number of used colors
161 */
COLOR_SetNumColors(Int32 iNum)162 void COLOR_SetNumColors(Int32 iNum) {
163 iNumColors = iNum;
164 }
165
166
167 /**
168 * Returns color depth
169 */
COLOR_GetDepth(void)170 Int32 COLOR_GetDepth(void) {
171 return COLOR_Depth;
172
173 }
174
175
176 /**
177 * Finds and stores RGB shift and move values
178 *
179 * \b History:
180 * \arg 31.01.98 JRXR Created.
181 *
182 */
COLOR_InitRGB(XVisualInfo * Info)183 void COLOR_InitRGB(XVisualInfo *Info)
184 {
185 Int32 r,g,b;
186 int i;
187
188 if (Info->class == TrueColor)
189 {
190 r = redMask = Info->red_mask;
191 g = greenMask = Info->green_mask;
192 b = blueMask = Info->blue_mask;
193
194 for ( i=0 ; !(r & 1) ; r=r>>1,i++ )
195 ;
196 redShift=i;
197
198 for ( i=16 ; r ; r=r>>1,i-- )
199 ;
200 redMove=i;
201
202 for ( i=0 ; !(g & 1) ; g=g>>1,i++ )
203 ;
204 greenShift=i;
205
206 for ( i=16 ; g ; g=g>>1,i-- )
207 ;
208 greenMove=i;
209
210 for ( i=0 ; !(b & 1) ; b=b>>1,i++ )
211 ;
212 blueShift=i;
213
214 for ( i=16 ; b ; b=b>>1,i-- )
215 ;
216 blueMove=i;
217 }
218 else if (Info->class == PseudoColor)
219 {
220 redMove = greenMove = blueMove = 8;
221 redMask = 0x0000ff;
222 greenMask = 0x00ff00;
223 blueMask = 0xff0000;
224 redShift = 0;
225 greenShift = 8;
226 blueShift = 16;
227 }
228 }
229
230
231 /**
232 * Separates RGB components from 32bit representation to separate 16bit variables
233 *
234 * \param Num 32bit composite RGB representation
235 * \param Red Pointer to 16bit variable for red component
236 * \param Green Pointer to 16bit variable for green component
237 * \param Blue Pointer to 16bit variable for blue component
238 *
239 * \b History:
240 * \arg 31.01.98 JRXR Created.
241 * \arg 13.01.00 MSH Commented.
242 */
COLOR_numTorgb(Int32 Num,UInt16 * Red,UInt16 * Green,UInt16 * Blue)243 void COLOR_numTorgb( Int32 Num, UInt16 *Red, UInt16 *Green, UInt16 *Blue )
244 {
245 /* Mask out component and shift it to correct position */
246 *Red = ((Num & redMask) >> redShift) << redMove;
247 *Green = ((Num & greenMask) >> greenShift) << greenMove;
248 *Blue = ((Num & blueMask) >> blueShift) << blueMove;
249 }
250
251
252 /**
253 * Combines given RGB component values to 32bit composite representation.
254 *
255 * \param Red 16bit red component
256 * \param Green 16bit green component
257 * \param Blue 16bit blue component
258 *
259 * \b History:
260 * \arg 31.01.98 JRXR Created.
261 * \arg 13.01.00 MSH Commented.
262 */
COLOR_rgbToNum(Int32 Red,Int32 Green,Int32 Blue)263 Int32 COLOR_rgbToNum(Int32 Red, Int32 Green, Int32 Blue)
264 {
265 Int32 r,g,b;
266
267 /* Separate significant bits from color components */
268 r = Red >> redMove;
269 g = Green >> greenMove;
270 b = Blue >> blueMove;
271 /* Sum up the components */
272 return (r<<redShift) | (g<<greenShift) | (b<<blueShift);
273 }
274
275
276 /**
277 * Returns flag indicating whether truecolor or pseudocolor is in use.
278 *
279 * \b History:
280 * \arg 07.08.95 JC Created.
281 * \arg 13.01.00 MSH Commented.
282 */
COLOR_IsTrueColor()283 Flag COLOR_IsTrueColor()
284 {
285 return(trueColor);
286 }
287
288
289 /**
290 * Maps color index to real color value in truecolor mode. In pseudocolor
291 * this is a dummy operation.
292 *
293 * \b History:
294 * \arg 07.08.95 JC Created.
295 * \arg 10.12.99 TdH Made it return realColor when COLOR_Depth==16
296 * \arg 09.01.00 MSH Removed dead code, this works just fine without it
297 *
298 * \bug This must go, it's silly, mapping should have been done already
299 */
COLOR_QueryColor(Int32 iColor)300 Int32 COLOR_QueryColor(Int32 iColor)
301 {
302 /* In pseudocolor etc. the index is valid 'as-is' */
303 if (!trueColor)
304 return(iColor);
305 else
306 return colormap[iColor];
307 }
308
309
310 /**
311 * Initializes player colors, turn idicator and player color edit entries
312 * to black.
313 *
314 * \b History:
315 * \arg 09.08.94 ESF Created.
316 * \arg 01.01.95 ESF Added making the player turn indicator black.
317 * \arg 13.01.00 MSH Commented.
318 *
319 * \bug Turn indicator does not need its own colormap entry
320 */
COLOR_Init(void)321 void COLOR_Init(void)
322 {
323 Int32 i;
324
325 /* Set the initial player colors to be black */
326 for (i=0; i!=MAX_PLAYERS; i++)
327 COLOR_StoreNamedColor("Black", i);
328
329 /* Set the initial player turn indicator to be black */
330 COLOR_CopyColor(COLOR_PlayerToColor(0), COLOR_DieToColor(2));
331
332 /* Set the initial player color edit color to black */
333 COLOR_CopyColor(COLOR_PlayerToColor(0), COLOR_DieToColor(3));
334 }
335
336
337 /**
338 * Selects an appropriate visual if one is available, and then builds
339 * the required X args to pass to any top-level shells. If no
340 * appropriate visual is available, then exit. If a usable PseudoColor
341 * visual exists, but there aren't enough colors available from the
342 * default colormap, then allocate a private colormap for the
343 * application. It allocates a colormap and sets up two mappings,
344 * from the index to the colors, and vice-versa.
345 *
346 * \b History:
347 * \arg 09.19.94 ESF Moved this stuff over here from gui.c.
348 * \arg 10.08.94 ESF Enhanced to reduce flashing with private colormap.
349 * \arg 17.08.95 JC True colors.
350 * \arg 29.08.95 JC If the server support TrueColor, use it.
351 * \arg 13.01.00 MSH Commented.
352 *
353 * \bug This function is specific to Frisk and sets global variables
354 * cmapColormap, hDisplay, etc. Change it evantually.
355 */
COLOR_GetColormap(void * pData,Int32 * piNumArgs,Int32 iNeededColors,Int32 argc,CString * argv)356 void COLOR_GetColormap(void *pData, Int32 *piNumArgs, Int32 iNeededColors,
357 Int32 argc, CString *argv)
358 {
359 Widget wDummy;
360 Arg *pVisualArgs = (Arg *)pData;
361 XVisualInfo Info;
362 Int32 i;
363
364
365 /* Create a dummy top level shell to learn more about the display */
366 wDummy = XtAppInitialize(&appContext, "XFrisk", NULL, 0,
367 &argc, argv, strResources, NULL, 0);
368 hDisplay = XtDisplay(wDummy);
369 trueColor = FALSE;
370 COLOR_Depth = 0;
371
372 /* See if there is a TrueColor visual with a depth of 24 bits */
373 if (XMatchVisualInfo(hDisplay, DefaultScreen(hDisplay),
374 24, TrueColor, &Info)) {
375 trueColor = TRUE;
376 COLOR_Depth = 24;
377 }
378
379 /* See if there is a TrueColor visual with a depth of 16 bits */
380 else if (XMatchVisualInfo(hDisplay, DefaultScreen(hDisplay),
381 16, TrueColor, &Info)) {
382 trueColor = TRUE;
383 COLOR_Depth = 16;
384 }
385
386 /* See if there is a TrueColor visual with a depth of 15 bits */
387 else if (XMatchVisualInfo(hDisplay, DefaultScreen(hDisplay),
388 15, TrueColor, &Info)) {
389 trueColor = TRUE;
390 COLOR_Depth = 15;
391 }
392 /* See if there is a PseudoColor visual with a depth of 8 bits */
393 else if (XMatchVisualInfo(hDisplay, DefaultScreen(hDisplay),
394 8, PseudoColor, &Info)) {
395 /* Save the visual for use in the program -- this shouldn't be here,
396 * once all of this gets cleaned up.
397 */
398
399 COLOR_InitRGB(&Info);
400 pVisual = Info.visual;
401 COLOR_Depth = 8;
402
403 /* Try to allocate the needed colors from the default colormap.
404 * If this fails, then try allocating a private colormap. If
405 * it fails, it is probably because the Display is TrueColor,
406 * or else because there aren't enough free colors in the
407 * default colormap.
408 */
409
410 cmapColormap = DefaultColormap(hDisplay, DefaultScreen(hDisplay));
411 if (!XAllocColorCells(hDisplay, cmapColormap, False, NULL, 0,
412 plCountryToColor, iNeededColors))
413 {
414 XColor xColor;
415
416 /* We must use a private colormap */
417 #ifdef ENGLISH
418 printf("CLIENT: Using a private colormap.\n");
419 #endif
420 #ifdef FRENCH
421 printf("CLIENT: Utilise une palette priv�e.\n");
422 #endif
423 cmapColormap = XCreateColormap(hDisplay,
424 RootWindowOfScreen(XtScreen(wDummy)),
425 Info.visual, AllocNone);
426
427 /* Since we only need some of the colors, copy the first bunch
428 * of colors from the default colormap, in the hope that we'll
429 * get the window manager colors, so that nasty flashing won't
430 * occur...
431 */
432
433 for (i=0; i < 256 - iNeededColors; i++)
434 {
435 xColor.pixel = i;
436 xColor.flags = DoRed | DoGreen | DoBlue;
437 XQueryColor(hDisplay,
438 XDefaultColormap(hDisplay, DefaultScreen(hDisplay)),
439 &xColor);
440 XAllocColor(hDisplay, cmapColormap, &xColor);
441 }
442
443 /* Allocate colors from this colormap */
444 if (!XAllocColorCells(hDisplay, cmapColormap, False, NULL, 0,
445 plCountryToColor, iNeededColors))
446 {
447 #ifdef ENGLISH
448 printf("CLIENT: Strange error, could not allocate colors.\n");
449 #endif
450 #ifdef FRENCH
451 printf("CLIENT: Erreur �trange, pas d'allocation de couleurs.\n");
452 #endif
453 UTIL_ExitProgram(-1);
454 }
455 }
456 }
457
458 else
459
460 {
461 /* Print an error message, deregister the client, and get out! */
462 #ifdef ENGLISH
463 printf("Fatal Error! Could not find a PseudoColor visual to use,\n"
464 " or the one found was not deep enough to\n"
465 " allocate %d colors.\n", iNeededColors);
466 #endif
467 #ifdef FRENCH
468 printf("Erreur fatale! Impossible de trouver un PseudoColor visual\n"
469 " � utiliser ou celui trouv� ne permet pas\n"
470 " d'utiliser %d couleurs.\n", iNeededColors);
471 #endif
472 UTIL_ExitProgram(0);
473 }
474
475 if (trueColor)
476 {
477 COLOR_InitRGB(&Info);
478 cmapColormap = DefaultColormap(hDisplay, DefaultScreen(hDisplay));
479
480 /* to make it work with pseudocolor as well as truecolor
481 * in pseudocolor it gets another mapping
482 **/
483 for(i=0; i < MAX_COLORS; i++)
484 plCountryToColor[i] = i;
485
486 /* Set up the arguments */
487 *piNumArgs = 0;
488 XtSetArg(pVisualArgs[*piNumArgs], XtNvisual, Info.visual);
489 (*piNumArgs)++;
490 XtSetArg(pVisualArgs[*piNumArgs], XtNdepth, Info.depth);
491 (*piNumArgs)++;
492 }
493
494 else
495 {
496 /* Set up the arguments */
497 *piNumArgs = 0;
498 XtSetArg(pVisualArgs[*piNumArgs], XtNvisual, pVisual);
499 (*piNumArgs)++;
500 XtSetArg(pVisualArgs[*piNumArgs], XtNdepth, 8);
501 (*piNumArgs)++;
502 XtSetArg(pVisualArgs[*piNumArgs], XtNcolormap, cmapColormap);
503 (*piNumArgs)++;
504 }
505
506 /* Set up mapping from color to country. With this set up,
507 * we have bidirectional mapping, from country to color and from
508 * color to country.
509 */
510 memset(piColorToCountry, (Byte)0, sizeof(Int32)*MAX_COLORS);
511 for(i=0; i < iNeededColors; i++)
512 piColorToCountry[plCountryToColor[i]] = i;
513
514 /* We don't need this anymore */
515 XtDestroyWidget(wDummy);
516 }
517
518
519 /**
520 * Reads color map from raw byte array (originally read from file),
521 * separating RGB values to structure fields.
522 *
523 * \b History:
524 * \arg 05.12.94 ESF Created.
525 * \arg 09.01.00 MSH Corrected to take struct padding into account.
526 * \arg 13.01.00 MSH Commented.
527 */
COLOR_SetWorldColormap(Byte * rawmap)528 void COLOR_SetWorldColormap(Byte *rawmap)
529 {
530 Int32 i;
531
532 for(i = 0; i < iNumColors; i++)
533 {
534 pWorldColors[i].r = *rawmap++;
535 pWorldColors[i].g = *rawmap++;
536 pWorldColors[i].b = *rawmap++;
537 }
538 }
539
540
541 /**
542 * Sets colormap entries in pseudocolor or redraws map with real
543 * colors instead of colormap indexes in truecolor.
544 *
545 * \b History:
546 * \arg 05.12.94 ESF Created.
547 * \arg 08.03.94 ESF Fixed loop bug.
548 * \arg 17.08.95 JC True colors.
549 * \arg 29.08.95 JC Moved.
550 * \arg 02.01.00 TdH Fixed truecolors in colormap
551 */
COLOR_SetWorldColors(void)552 void COLOR_SetWorldColors(void)
553 {
554 XColor xColor;
555 Int32 i ;
556 unsigned long c;
557
558
559 /* Now read in the colormap, store it, and setup the screen.
560 * Note that color == country here.
561 * background is #42, lines #43
562 */
563
564 for (i=0; i < iNumColors; i++) {
565 colormap[i] = COLOR_rgbToNum(pWorldColors[i].r * 256,
566 pWorldColors[i].g * 256 ,
567 pWorldColors[i].b * 256);
568 }
569 if (trueColor) {
570 Int32 x, y, i;
571 for (y = 0; y < pMapImage->height; y++) {
572 for (x = 0; x < pMapImage->width; x++) {
573 /* this returns *index* of color from the original worldmap */
574 c = XGetPixel(pMapImage, x, y);
575 /* needed for compatibility with pseudocolor.
576 * it's one on one in truecolor
577 * country that belongs to this pixelvalue */
578 i = COLOR_ColorToCountry(c);
579 c = COLOR_QueryColor(i);
580 XSetForeground(hDisplay, hGC, c);
581 XDrawPoint(hDisplay, pixMapImage, hGC, x, y);
582 }
583 }
584 XCopyArea(hDisplay, pixMapImage, hWindow, hGC,
585 0, 0, pMapImage->width, pMapImage->height, 0, 0);
586 } else {
587 for (i=0; i < iNumColors; i++)
588 {
589 xColor.flags = DoRed | DoGreen | DoBlue;
590 xColor.pixel = COLOR_CountryToColor(i);
591 xColor.red = pWorldColors[i].r << 8;
592 xColor.green = pWorldColors[i].g << 8;
593 xColor.blue = pWorldColors[i].b << 8;
594
595 D_Assert(xColor.pixel<=MAX_COLORS, "Pixel out of range.");
596 XStoreColor(hDisplay, cmapColormap, &xColor);
597 }
598 }
599
600 XFlush(hDisplay);
601 }
602
603
604 /**
605 * Maps die index to color index.
606 *
607 * \bug Should map to real color value instead of just index.
608 *
609 * \b History:
610 * \arg 03.04.94 ESF Created.
611 * \arg 03.05.94 ESF Fixed bug, wrong offset.
612 * \arg 08.28.94 ESF Fixed bug, wrong argument.
613 * \arg 13.01.00 MSH Commented.
614 */
COLOR_DieToColor(Int32 iDie)615 Int32 COLOR_DieToColor(Int32 iDie)
616 {
617 D_Assert(iDie>=0 && iDie<MAX_PLAYERS,
618 "Wrong range for die color.");
619 return (plCountryToColor[NUM_COUNTRIES+2+MAX_PLAYERS+iDie]);
620 }
621
622
623 /**
624 * Maps country index to color index.
625 *
626 * \bug Should map to real color value instead of just index.
627 *
628 * \b History:
629 * \arg 02.05.94 ESF Created.
630 * \arg 05.05.94 ESF Fixed for new colormap scheme.
631 * \arg 13.01.00 MSH Commented.
632 */
COLOR_CountryToColor(Int32 iCountry)633 Int32 COLOR_CountryToColor(Int32 iCountry)
634 {
635 /* It's +2 because of the two reserved colors for ocean and lines */
636 D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES+2,
637 "Country out of range.");
638 return(plCountryToColor[iCountry]);
639 }
640
641
642 /**
643 * Maps player index to color index.
644 *
645 * \bug Should map to real color value instead of just index.
646 *
647 * \b History:
648 * \arg 02.05.94 ESF Created.
649 * \arg 13.01.00 MSH Commented; removed irrelevant bug comment.
650 */
COLOR_PlayerToColor(Int32 iPlayer)651 Int32 COLOR_PlayerToColor(Int32 iPlayer)
652 {
653 D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS,
654 "Player out of range.");
655 return (plCountryToColor[NUM_COUNTRIES+2+iPlayer]);
656 }
657
658
659 /**
660 * Change color of given country to the one of given player.
661 *
662 * \bug Redrawing country image doesn't belong to this module!
663 *
664 * \b History:
665 * \arg 02.05.94 ESF Created.
666 * \arg 02.05.94 ESF Factored out color changing code.
667 * \arg 13.01.00 MSH Commented.
668 */
COLOR_ColorCountry(Int32 iCountry,Int32 iPlayer)669 void COLOR_ColorCountry(Int32 iCountry, Int32 iPlayer)
670 {
671 D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES &&
672 iPlayer>=0 && iPlayer<MAX_PLAYERS,
673 "Bad range for ColorCountry().");
674 COLOR_CopyColor(COLOR_PlayerToColor(iPlayer),
675 COLOR_CountryToColor(iCountry));
676 if (COLOR_IsTrueColor())
677 {
678 Int32 x, y, i, j;
679 UInt32 c;
680
681 c = COLOR_CountryToColor(iCountry);
682 x = RISK_GetTextXOfCountry(iCountry) - 200;
683 y = RISK_GetTextYOfCountry(iCountry) - 75;
684 XSetForeground(hDisplay, hGC, COLOR_QueryColor(c));
685 for (i = 0 ; i < 150 && y+i< pMapImage->height ; i++) {
686 if(y+i<0)
687 continue;
688 for (j = 0; j < 300 && x+j < pMapImage->width ; j++) {
689 if(x+j<0)
690 continue;
691 if (XGetPixel(pMapImage, x+j, y+i) == c)
692 XDrawPoint(hDisplay, pixMapImage, hGC, x+j, y+i);
693 }
694 }
695 XCopyArea(hDisplay, pixMapImage, hWindow, hGC,
696 x, y, 300, 150, x, y);
697 }
698 }
699
700
701 /**
702 * Maps color index to country index.
703 *
704 * \b History:
705 * \arg 02.05.94 ESF Created.
706 * \arg 05.05.94 ESF Fixed for new colormap scheme.
707 */
COLOR_ColorToCountry(Int32 iColor)708 Int32 COLOR_ColorToCountry(Int32 iColor)
709 {
710 D_Assert(iColor>=0 && iColor<MAX_COLORS,
711 "Color out of range.");
712 return(piColorToCountry[iColor]);
713 }
714
715
716 /**
717 * Copy value in colormap from colormap[src] to colormap[dst]
718 *
719 * \b History:
720 * \arg 02.05.94 ESF Created.
721 * \arg 17.08.95 JC True colors.
722 * \arg 13.01.00 MSH Fixed comments.
723 * \arg 13.01.00 MSH Fixed logic in truecolor.
724 */
COLOR_CopyColor(Int32 iSrc,Int32 iDst)725 void COLOR_CopyColor(Int32 iSrc, Int32 iDst)
726 {
727 XColor xColor;
728
729 D_Assert(iSrc>=COLOR_CountryToColor(0) &&
730 iSrc<=COLOR_DieToColor(3), "Source color out of range.");
731 D_Assert(iDst>=COLOR_CountryToColor(0) &&
732 iDst<=COLOR_DieToColor(3), "Dest. color out of range.");
733
734 if(trueColor)
735 {
736 colormap[iDst] = colormap[iSrc];
737 }
738 else
739 {
740 xColor.flags = DoRed | DoGreen | DoBlue;
741 xColor.pixel = iSrc;
742 XQueryColor(hDisplay, cmapColormap, &xColor);
743
744 xColor.pixel = iDst;
745 XStoreColor(hDisplay, cmapColormap, &xColor);
746 }
747
748 XFlush(hDisplay);
749 }
750
751
752 /**
753 * Set color of given player to given color string.
754 *
755 * \b History:
756 * \arg 05.03.94 ESF Created.
757 * \arg 04.06.95 ESF Fixed bug, store closest displayable color.
758 * \arg 17.08.95 JC true colors.
759 */
COLOR_StoreNamedColor(CString strPlayerColor,Int32 iPlayer)760 void COLOR_StoreNamedColor(CString strPlayerColor, Int32 iPlayer)
761 {
762 XColor xColor, xColorClosest;
763
764 D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS,
765 "Player out of range.");
766 D_Assert(cmapColormap!=0, "Colormap is not there!");
767
768 /* Get the closest color we can display on this screen */
769 XLookupColor(hDisplay, cmapColormap, strPlayerColor,
770 &xColor, &xColorClosest);
771
772 /* Store it */
773 colormap[COLOR_PlayerToColor(iPlayer)] =
774 COLOR_rgbToNum(xColorClosest.red, xColorClosest.green,
775 xColorClosest.blue);
776
777 if (!trueColor)
778 {
779 xColorClosest.flags = DoRed | DoGreen | DoBlue;
780 xColorClosest.pixel = COLOR_PlayerToColor(iPlayer);
781 XStoreColor(hDisplay, cmapColormap, &xColorClosest);
782 }
783 }
784
785
786 /**
787 * Change color.
788 * \param iColorNum Index of color to change
789 * \param iRed Red component of new color
790 * \param iGreen Green component of new color
791 * \param iBlue Blue component of new color
792 *
793 * \b History
794 * \arg 01.22.95 ESF Created.
795 * \arg 17.08.95 JC True colors.
796 * \arg 13.01.00 MSH Fixed comments, faulty assertion range
797 * \arg 13.01.00 MSH Fixed function logic on trueColor flag
798 */
COLOR_StoreColor(Int32 iColorNum,Int32 iRed,Int32 iGreen,Int32 iBlue)799 void COLOR_StoreColor(Int32 iColorNum, Int32 iRed, Int32 iGreen, Int32 iBlue)
800 {
801 XColor xColor;
802 Int32 c = COLOR_rgbToNum(iRed, iGreen, iBlue);
803
804 D_Assert(iColorNum && iColorNum <= MAX_COLORS, "Color out of range!");
805
806 if (trueColor)
807 {
808 colormap[iColorNum] = c;
809 }
810 else
811 {
812 xColor.pixel = iColorNum;/* seems wrong!! this range ??*/
813 xColor.flags = DoRed | DoGreen | DoBlue;
814 xColor.red = iRed;
815 xColor.green = iGreen;
816 xColor.blue = iBlue;
817 XStoreColor(hDisplay, cmapColormap, &xColor);
818 }
819 }
820
821
822 /**
823 * Returns colormap entry to separate 16bit components
824 * \param iColor Colormap index
825 * \param iRed Pointer to red component variable
826 * \param iGreen Pointer to green component variable
827 * \param iBlue Pointer to blue component variable
828 *
829 * \b History:
830 * \arg 02.12.95 ESF Created.
831 * \arg 13.01.00 MSH Commented; fixed bogus assert range
832 */
COLOR_GetColor(Int32 iColor,UInt16 * iRed,UInt16 * iGreen,UInt16 * iBlue)833 void COLOR_GetColor(Int32 iColor, UInt16 *iRed, UInt16 *iGreen, UInt16 *iBlue)
834 {
835 D_Assert(iColor && iColor <= MAX_COLORS, "Color out of range!");
836
837 COLOR_numTorgb(colormap[iColor], iRed, iGreen, iBlue);
838 }
839
840 /* EOF */
841