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: colorEdit.c,v 1.21 2000/01/22 22:11:35 morphy Exp $
20 *
21 * $Log: colorEdit.c,v $
22 * Revision 1.21 2000/01/22 22:11:35 morphy
23 * Comment changes
24 *
25 * Revision 1.20 2000/01/22 22:46:54 tony
26 * now updates example image when color entered in text inputline
27 *
28 * Revision 1.19 2000/01/18 18:55:02 morphy
29 * Reordered parameters passed to XawScrollbarSetThumb
30 *
31 * Revision 1.18 2000/01/16 18:49:29 tony
32 * scrollbar still screwed
33 *
34 * Revision 1.17 2000/01/12 19:33:26 tony
35 * moving around, commenting, scrollbars,edit box still no good
36 *
37 * Revision 1.16 2000/01/10 22:47:40 tony
38 * made colorstuff more private to colormap.c, only scrollbars get set wrong, rest seems to work ok now
39 *
40 * Revision 1.15 2000/01/10 00:19:56 tony
41 * and one more
42 *
43 * Revision 1.14 2000/01/10 00:01:44 tony
44 * and more..
45 *
46 * Revision 1.13 2000/01/09 22:44:12 morphy
47 * Fixes and optimizations in example image drawing
48 *
49 * Revision 1.12 2000/01/09 21:47:48 morphy
50 * Moved drawing of example country image to separate function
51 *
52 * Revision 1.11 2000/01/09 21:20:33 morphy
53 * Merged in fix for example image background color
54 *
55 * Revision 1.10 2000/01/09 21:55:10 tony
56 * made iCountry static, little fix in scrollbars
57 *
58 * Revision 1.9 2000/01/09 20:58:38 tony
59 * some comment
60 *
61 * Revision 1.8 2000/01/05 23:21:35 tony
62 * changed CARD_ to CARDS_
63 *
64 * Revision 1.7 2000/01/04 21:41:53 tony
65 * removed redundant stuff for jokers
66 */
67
68 /** \file Change color of player */
69
70 #include <X11/X.h>
71 #include <X11/Intrinsic.h>
72 #include <X11/StringDefs.h>
73 #include <X11/Shell.h>
74 #include <X11/Xaw/Scrollbar.h>
75 #include <X11/Xaw/Form.h>
76 #include <X11/Xaw/Command.h>
77 #include <X11/Xaw/AsciiText.h>
78
79 #include "colorEdit.h"
80 #include "dice.h"
81 #include "callbacks.h"
82 #include "colormap.h"
83 #include "client.h"
84 #include "utils.h"
85 #include "cards.h"
86 #include "riskgame.h"
87 #include "gui-vars.h"
88 #include "debug.h"
89 #include "riskgame.h"
90 #include "viewStats.h"
91
92
93 /* Local functions */
94 static void COLEDIT_Cancel(void);
95 static void COLEDIT_ScrollbarMoved(void);
96 static void COLEDIT_UpdateExampleImage(Int32 iColor);
97
98 /* Action tables */
99 static XtActionsRec actionTable[] =
100 {
101 { "updateColor", (XtActionProc)COLEDIT_UpdateColorWithInput },
102 { "colorEditCancel", (XtActionProc)COLEDIT_Cancel },
103 { NULL, NULL }
104 };
105
106 /* Widgets */
107 static Widget wColorEditShell;
108 static Widget wColorEditForm;
109 static Widget wColorEditLabel;
110 static Widget wRedScrollbar, wBlueScrollbar, wGreenScrollbar;
111 static Widget wSampleCountryForm;
112 static Widget wColorInputLabel, wColorInputText;
113 static Widget wColorOK, wColorCancel;
114
115 /* Color editing related things */
116 #define COLOR_EDIT_OK 1
117 #define COLOR_EDIT_CANCEL 0
118 #define COLOR_EDIT_INPROGRESS -1
119
120 static Int32 iQueryResult = COLOR_EDIT_OK;
121 static Pixmap pixSampleImage;/**< sample image */
122 static XImage *pScaledSample;
123 Int32 iCountry;/**< index of country clicked on*/
124 Int32 iglobalColor;/**< index of color */
125
126
127 /**
128 * \b History:
129 * \arg 01.22.95 ESF Created.
130 * \arg 01.24.95 ESF Changed to get coordinates manually.
131 * \arg 01.25.95 ESF Added check that the country was not empty.
132 * \arg 12.07.95 ESF Fixed a bug -- don't allow editing of ocean.
133 */
COLEDIT_MapShiftClick(void)134 void COLEDIT_MapShiftClick(void)
135 {
136 Int32 iColor;
137 Int32 x, y, xRoot, yRoot;
138 UInt32 uiButtons;
139 Window winDummy1, winDummy2;
140
141 if (!XQueryPointer(hDisplay, hWindow, &winDummy1, &winDummy2,
142 &xRoot, &yRoot, &x, &y, &uiButtons))
143 {
144 /* Pointer has somehow left window */
145 return;
146 }
147
148 /* Get the coordinates of the mouse */
149 iColor = XGetPixel(pMapImage, x, y);
150 iCountry = COLOR_ColorToCountry(iColor);
151
152 /* See if there is a player on the country
153 * no idea why?
154 */
155 if (iCountry<0 || iCountry>=NUM_COUNTRIES ||
156 RISK_GetOwnerOfCountry(iCountry) == -1 ||
157 RISK_GetNumArmiesOfCountry(iCountry) == 0)
158 return;
159
160 /* Edit this color */
161 COLEDIT_EditColor(iColor, TRUE);/* ok here */
162 }
163
COLEDIT_Ok(void)164 void COLEDIT_Ok(void) { iQueryResult = COLOR_EDIT_OK; }
COLEDIT_Cancel(void)165 void COLEDIT_Cancel(void) { iQueryResult = COLOR_EDIT_CANCEL; }
166
167
168 /**
169 * Set scrollbars and text input box to given color
170 *
171 * \b History:
172 * \arg 01.22.95 ESF Created.
173 * \arg 18.08.95 JC Modified to call COLOR_GetColor.
174 * \arg 18.01.00 MSH Reordered X..SetThumb parameters.
175 */
COLEDIT_InitDialogWithColor(Int32 iColorNum)176 void COLEDIT_InitDialogWithColor (Int32 iColorNum)
177 {
178 float f;
179 UInt16 r, g, b;
180 char buf[256];
181
182 COLOR_GetColor(iColorNum, &r, &g, &b);
183
184 f = 1.0 - ((float)r)/65535.0;
185 XawScrollbarSetThumb(wRedScrollbar, f, 0.05);
186
187 f = 1.0 - ((float)g)/65535.0;
188 XawScrollbarSetThumb(wGreenScrollbar, f, 0.05);
189
190 f = 1.0 - ((float)b)/65535.0;
191 XawScrollbarSetThumb(wBlueScrollbar, f, 0.05);
192
193 /* Display the name of the color */
194 snprintf(buf, sizeof(buf), "#%02x%02x%02x",
195 r/256, g/256, b/256);
196 XtVaSetValues(wColorInputText,
197 XtNstring, buf,
198 XtNinsertPosition, strlen(buf),
199 NULL);
200 }
201
202
203 /**
204 * Build the X dialog structure. Called from gui.c
205 *
206 * \b History:
207 * \arg 01.21.95 ESF Created.
208 */
COLEDIT_BuildDialog(void)209 void COLEDIT_BuildDialog(void)
210 {
211 Widget wColorDummy;
212
213 /* Add Actions */
214 XtAppAddActions(appContext, actionTable, XtNumber(actionTable));
215
216 wColorEditShell = XtCreatePopupShell("wColorEditShell",
217 transientShellWidgetClass,
218 wToplevel, pVisualArgs, iVisualCount);
219 wColorEditForm = XtCreateManagedWidget("wColorEditForm", formWidgetClass,
220 wColorEditShell, NULL, 0);
221 /* The label for the dialog */
222 wColorEditLabel = XtCreateManagedWidget("wColorEditLabel", labelWidgetClass,
223 wColorEditForm, NULL, 0);
224
225 /* The three (RGB) scrollbars */
226 wRedScrollbar = XtCreateManagedWidget("wRedScrollbar",
227 scrollbarWidgetClass,
228 wColorEditForm, NULL, 0);
229 XtAddCallback(wRedScrollbar, XtNjumpProc,
230 (XtCallbackProc)COLEDIT_ScrollbarMoved, NULL);
231 XawScrollbarSetThumb(wRedScrollbar, 0.0, 0.05);
232 wGreenScrollbar = XtCreateManagedWidget("wGreenScrollbar",
233 scrollbarWidgetClass,
234 wColorEditForm, NULL, 0);
235 XtAddCallback(wGreenScrollbar, XtNjumpProc,
236 (XtCallbackProc)COLEDIT_ScrollbarMoved, NULL);
237 XawScrollbarSetThumb(wGreenScrollbar, 0.0, 0.05);
238 wBlueScrollbar = XtCreateManagedWidget("wBlueScrollbar",
239 scrollbarWidgetClass,
240 wColorEditForm, NULL, 0);
241 XtAddCallback(wBlueScrollbar, XtNjumpProc,
242 (XtCallbackProc)COLEDIT_ScrollbarMoved, NULL);
243 XawScrollbarSetThumb(wBlueScrollbar, 0.0, 0.05);
244
245 /* A sample country in the chosen color */
246 wSampleCountryForm = XtCreateManagedWidget("wSampleCountryForm",
247 labelWidgetClass,
248 wColorEditForm, NULL, 0);
249
250 /* Input text label */
251 wColorInputLabel = XtCreateManagedWidget("wColorInputLabel",
252 labelWidgetClass,
253 wColorEditForm, NULL, 0);
254
255 /* The actual widget for inputting text */
256 wColorInputText = XtVaCreateManagedWidget("wColorInputText",
257 asciiTextWidgetClass,
258 wColorEditForm,
259 XtNeditType, XawtextEdit, NULL);
260
261 /* This is used to align the OK/Cancel buttons */
262 wColorDummy = XtCreateManagedWidget("wColorDummy", formWidgetClass,
263 wColorEditForm, NULL, 0);
264
265 /* The buttons */
266 wColorOK = XtCreateManagedWidget("wColorOK",
267 commandWidgetClass,
268 wColorEditForm, NULL, 0);
269 XtAddCallback(wColorOK, XtNcallback, (XtCallbackProc)COLEDIT_Ok, NULL);
270 wColorCancel = XtCreateManagedWidget("wColorCancel",
271 commandWidgetClass,
272 wColorEditForm, NULL, 0);
273 XtAddCallback(wColorCancel, XtNcallback, (XtCallbackProc)COLEDIT_Cancel,
274 NULL);
275 }
276
277
278 /** Cleanup macro for the function COLEDIT_EditColor */
279 #define COLEDIT_CloseColorDialog() \
280 UTIL_DisplayError(""); \
281 XtSetKeyboardFocus(wToplevel, wToplevel); \
282 XtRemoveGrab(wColorEditShell); \
283 XtUnrealizeWidget(wColorEditShell);
284
285
286 /**
287 * Displays the dialog with given color. Called by player add and
288 * registration routines.
289 *
290 * \b History:
291 * \arg 01.22.95 ESF Created.
292 * \arg 01.26.95 ESF Fixed last few bugs.
293 * \arg 23.08.95 JC Use of COLOR_Depth.
294 * \arg 12.07.95 ESF Made the editable color be the dice color.
295 */
COLEDIT_EditColor(Int32 iColorNum,Flag fStoreColor)296 String COLEDIT_EditColor(Int32 iColorNum, Flag fStoreColor)
297 {
298 XEvent xEvent;
299 Int32 x, y;
300 CString strNewColor=NULL;
301
302 D_Assert(iColorNum >= COLOR_CountryToColor(0) && iColorNum <= COLOR_DieToColor(3),
303 "Asked to edit bogus color!");
304
305 /* Center the new shell */
306 UTIL_CenterShell(wColorEditShell, wToplevel, &x, &y);
307 XtVaSetValues(wColorEditShell,
308 XtNallowShellResize, False,
309 XtNx, x,
310 XtNy, y,
311 XtNborderWidth, 1,
312 #ifdef ENGLISH
313 XtNtitle, "Edit Color",
314 #endif
315 #ifdef FRENCH
316 XtNtitle, "Edition des couleurs",
317 #endif
318 NULL);
319
320 /* Initialize the scrollbars to represent the right color */
321 COLEDIT_InitDialogWithColor(iColorNum);
322
323 /* TdH looks wrong */
324 iCountry = COLOR_ColorToCountry(iColorNum);
325
326 /* If the country requested was not a valid country, then
327 * pick a random country for the caller.
328 */
329
330 if (iCountry >= NUM_COUNTRIES || iCountry < 0)
331 iCountry = rand() % NUM_COUNTRIES;
332
333 /* Hide the dice */
334 DICE_Hide();
335
336 /* Put the country on the sample */
337 pScaledSample = CARDS_GetCountryImage(iCountry,
338 iColorNum,
339 COLOR_CountryToColor(NUM_COUNTRIES));
340
341 /* Scale it to the sample country form */
342 pScaledSample = CARDS_ScaleImage(pScaledSample, 100, 100);
343
344 /* Set the initial color of the sample country
345 * TdH: to check!
346 */
347 COLOR_CopyColor(iColorNum, iColorNum);
348
349 /* Dump it on the sample country location */
350 pixSampleImage = XCreatePixmap(hDisplay, pixMapImage, 140, 140, COLOR_GetDepth());
351 XSetForeground(hDisplay, hGC, COLOR_QueryColor(COLOR_CountryToColor(NUM_COUNTRIES)));
352 XFillRectangle(hDisplay, pixSampleImage, hGC, 0, 0, 140, 140);
353 XtVaSetValues(wSampleCountryForm, XtNbackground,
354 COLOR_QueryColor(COLOR_CountryToColor(NUM_COUNTRIES)), NULL);
355 COLEDIT_UpdateExampleImage(iColorNum);
356
357 /* Popup the color editing dialog */
358 XtMapWidget(wColorEditShell);
359 XtAddGrab(wColorEditShell, True, True);
360 XtSetKeyboardFocus(wToplevel, wColorEditShell);
361 XtSetKeyboardFocus(wColorEditShell, wColorInputText);
362
363 /* Look until user presses one of the buttons */
364 iQueryResult = COLOR_EDIT_INPROGRESS;/* TdH: why this read?? */
365 while (iQueryResult == COLOR_EDIT_INPROGRESS)
366 {
367 /* pass events */
368 XNextEvent(hDisplay, &xEvent);
369 XtDispatchEvent(&xEvent);
370 }
371
372 if (iQueryResult == COLOR_EDIT_OK)
373 {
374 Int32 i;
375
376 /* Just in case the player typed a color name in and then hit "Ok"
377 * update the color in the country in the last second that the dialog
378 * is up, so that when we copy the color out of there it will be the
379 * color that the player typed in.
380 */
381
382 COLEDIT_UpdateColorWithInput();
383
384 /* Get the color from the text widget. If the player moved the
385 * scrollbars, then the color will have been written in here.
386 * If the player typed something in, it will be in here.
387 */
388
389 XtVaGetValues(wColorInputText, XtNstring, &strNewColor, NULL);
390
391 /* Are we trying to store the color? */
392 if (fStoreColor) {
393 /* Sanity check */
394 if (iCountry < 0 || iCountry >= NUM_COUNTRIES ||
395 RISK_GetOwnerOfCountry(iCountry) == -1 ||
396 RISK_GetNumArmiesOfCountry(iCountry) <= 0) {
397 (void)UTIL_PopupDialog("Error",
398 "Cannot set new value for color!",
399 1, "Ok", NULL, NULL);
400 } else {
401 Int32 iOwner = RISK_GetOwnerOfCountry(iCountry);
402 Flag isTrueColor = COLOR_IsTrueColor();
403
404 /* And also the actual color for the player */
405 COLOR_StoreNamedColor(strNewColor, iOwner);
406
407 /* Set all the countries that the player owns to be new color */
408 for (i=0; i!=NUM_COUNTRIES; i++)
409 if (RISK_GetOwnerOfCountry(i) == iOwner) {
410 COLOR_CopyColor(COLOR_DieToColor(0),
411 COLOR_CountryToColor(i));
412
413 if (isTrueColor) {
414 COLOR_ColorCountry(i, iOwner);
415 UTIL_DarkenCountry(i);
416 }
417 }
418 if (isTrueColor)
419 STAT_RenderSlot(STAT_PlayerToSlot(iOwner), iOwner);
420
421 /* If the player whose color changed is the current
422 * player, then recolor the current player indicator.
423 * Also, the dice really need to change color too
424 * (thanks, Kirsten, for reminding me about this -- who
425 * says English majors can't program?) For now punt on
426 * the dice.
427 */
428
429 if (RISK_GetOwnerOfCountry(iCountry) == iCurrentPlayer)
430 COLOR_CopyColor(COLOR_DieToColor(0), COLOR_DieToColor(2));
431 }
432 }
433 }
434
435 XDestroyImage(pScaledSample);
436
437 COLEDIT_CloseColorDialog();
438 return strNewColor;
439 }
440
441
442 /**
443 * Updates color value and text box based on scrollbar movement.
444 * Called during X event handling from the scrollbar widget.
445 *
446 * \b History:
447 * \arg 01.22.95 ESF Created.
448 */
COLEDIT_ScrollbarMoved(void)449 void COLEDIT_ScrollbarMoved(void)
450 {
451 float r, g, b;
452 XColor xColor;
453 char buf[256];
454
455 XtVaGetValues(wRedScrollbar, XtNtopOfThumb, &r, NULL);
456 XtVaGetValues(wGreenScrollbar, XtNtopOfThumb, &g, NULL);
457 XtVaGetValues(wBlueScrollbar, XtNtopOfThumb, &b, NULL);
458
459 /* Setup the new color */
460 xColor.red = (Int32)((1.0-r)*65535.0);
461 xColor.green = (Int32)((1.0-g)*65535.0);
462 xColor.blue = (Int32)((1.0-b)*65535.0);
463
464 /* Color the sample country with the new color
465 */
466 COLOR_StoreColor(COLOR_DieToColor(0), xColor.red, xColor.green, xColor.blue);
467 COLEDIT_UpdateExampleImage(COLOR_DieToColor(0));
468 XFlush(hDisplay);
469
470 /* Display the name of the color */
471 snprintf(buf, sizeof(buf), "#%02x%02x%02x",
472 xColor.red/256, xColor.green/256, xColor.blue/256);
473 XtVaSetValues(wColorInputText,
474 XtNstring, buf,
475 XtNinsertPosition, strlen(buf),
476 NULL);
477 }
478
479
480 /**
481 * Parse value from input box, update scrollbars and example
482 * country image to reflect change. Uses XParseColor to
483 * handle named colors listed in rgb.txt
484 *
485 * \b History:
486 * \arg 01.23.95 ESF Created.
487 */
COLEDIT_UpdateColorWithInput(void)488 void COLEDIT_UpdateColorWithInput(void)
489 {
490 CString strColor;
491 float r, g, b;
492 XColor xColor1, xColor2;
493 char buf[256];
494
495 /* Get the color from the text widget */
496 XtVaGetValues(wColorInputText, XtNstring, &strColor, NULL);
497
498 /* Also get the color from the scrollbars. */
499 XtVaGetValues(wRedScrollbar, XtNtopOfThumb, &r, NULL);
500 XtVaGetValues(wGreenScrollbar, XtNtopOfThumb, &g, NULL);
501 XtVaGetValues(wBlueScrollbar, XtNtopOfThumb, &b, NULL);
502 snprintf(buf, sizeof(buf), "#%02x%02x%02x",
503 (Int32)((1.0-r)*65535.0)/256,
504 (Int32)((1.0-g)*65535.0)/256,
505 (Int32)((1.0-b)*65535.0)/256);
506
507 /* Adjust for the screen */
508 xColor1.flags = DoRed | DoGreen | DoBlue;
509 (void)XParseColor(hDisplay, cmapColormap, buf, &xColor1);
510
511
512 /* Is it a valid color? */
513 if (XParseColor(hDisplay, cmapColormap, strColor, &xColor2))
514 {
515 /* If they match, then take this to mean the same as the "Ok" button. */
516 if (xColor1.red == xColor2.red &&
517 xColor1.green == xColor2.green &&
518 xColor1.blue == xColor2.blue) {
519 COLEDIT_Ok();
520 } else {
521 COLOR_StoreColor(COLOR_DieToColor(0),
522 xColor2.red, xColor2.green, xColor2.blue);
523 COLEDIT_InitDialogWithColor(COLOR_DieToColor(0));
524 COLEDIT_UpdateExampleImage(COLOR_DieToColor(0));
525 }
526 } else
527 #ifdef ENGLISH
528 (void)UTIL_PopupDialog("Error", "That color does not exist!",
529 1, "Ok", NULL, NULL);
530 #endif
531 #ifdef FRENCH
532 (void)UTIL_PopupDialog("Erreur", "Cette couleur n'existe pas!",
533 1, "Ok", NULL, NULL);
534 #endif
535 }
536
537
538 /**
539 * Draw example country image with given color.
540 *
541 * \b History:
542 * \tag 09.01.00 MSH Created.
543 */
COLEDIT_UpdateExampleImage(Int32 iColor)544 static void COLEDIT_UpdateExampleImage(Int32 iColor)
545 {
546 Int32 x, y;
547
548 if (COLOR_IsTrueColor())
549 {
550 XSetForeground(hDisplay, hGC, COLOR_QueryColor(iColor));
551 for (y = 0; y < pScaledSample->height; y++)
552 for (x = 0; x < pScaledSample->width; x++)
553 {
554 if (XGetPixel(pScaledSample, x, y) == NUM_COUNTRIES)
555 continue;
556 XDrawPoint(hDisplay, pixSampleImage, hGC,
557 (140-pScaledSample->width)/2 + x,
558 (140-pScaledSample->height)/2 + y);
559 }
560 }
561 else
562 {
563 XPutImage(hDisplay, pixSampleImage, hGC, pScaledSample, 0, 0,
564 (140-pScaledSample->width)/2, (140-pScaledSample->height)/2, 140, 140);
565 }
566
567 XtVaSetValues(wSampleCountryForm, XtNbitmap, pixSampleImage, NULL);
568 }
569
570 /* EOF */
571