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