1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/color.c,v 1.25 2011/05/16 16:21:56 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_COLOR_C_
22 
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25 
26 #include "choice.e"
27 #include "cmd.e"
28 #include "color.e"
29 #include "dialog.e"
30 #include "drawing.e"
31 #include "file.e"
32 #include "font.e"
33 #include "imgproc.e"
34 #include "mainloop.e"
35 #include "mainmenu.e"
36 #include "mark.e"
37 #include "menu.e"
38 #include "menuinfo.e"
39 #include "miniline.e"
40 #include "msg.e"
41 #include "obj.e"
42 #include "page.e"
43 #include "pattern.e"
44 #include "ps.e"
45 #include "raster.e"
46 #include "rect.e"
47 #include "select.e"
48 #include "setup.e"
49 #include "stk.e"
50 #include "strtbl.e"
51 #include "text.e"
52 #include "tgcwheel.e"
53 #include "util.e"
54 #include "xpixmap.e"
55 
56 #include "xbm/upend.xbm"
57 
58 #define MAX_VERTICAL_BTNS 6
59 
60 int	maxColors=0;
61 int	defaultColorIndex=9;
62 int	colorIndex=0;
63 int	*colorPixels=NULL;
64 int	*xorColorPixels=NULL;
65 int	*colorLayerOn=NULL;
66 char	defaultColorStr[COLORSTRLEN];
67 char	myFgColorStr[COLORSTRLEN];
68 char	myBgColorStr[COLORSTRLEN];
69 char	myRubberBandColorStr[COLORSTRLEN];
70 char	**colorMenuItems=NULL;
71 XColor	*tgifColors=NULL;
72 XColor	*tgifRequestedColors=NULL;
73 XColor	myBgColor;
74 int	maxRGB=0;
75 int	colorDump=FALSE;
76 int	useLocalRGBTxt=FALSE;
77 int	printUsingRequestedColor=FALSE;
78 int	colorLayers=FALSE;
79 int	needToRedrawColorWindow=FALSE;
80 int	initColorDontReload=FALSE;
81 int	gnUpdatePixelObjCount=0;
82 
83 char	defaultBgColorStr[COLORSTRLEN];
84 int	defaultBgColorIndex=INVALID;
85 
86 char	altEditTextBgColorStr[COLORSTRLEN];
87 int	altEditTextBgIndex=INVALID;
88 char	altEditTextHighlightColorStr[COLORSTRLEN];
89 int	altEditTextHighlightIndex=INVALID;
90 int	useAltEditTextBgColor=FALSE;
91 
92 char	pngExportTransparentColor[MAXSTRING];
93 
94 static int colorWindowFirstIndex=0;
95 static int colorItemH=12;
96 
97 static int	canChangeAttrColor=FALSE;
98 static int	defaultColorIndexInXDefaults=FALSE;
99 static int	defaultColorInXDefaults=FALSE;
100 static int	allocatedMaxColors=MAXCOLORS;
101 
102 static char *defaultColorMenuItems[MAXCOLORS]={
103    /* do not translate -- these strings are color names */
104    "magenta", "red", "green", "blue", "yellow", "pink", "cyan", "CadetBlue",
105    "white", "black", "DarkSlateGray"
106 };
107 
DefaultColorArrays(Entries,ForePixels,Valid,InitRV,StatusStr)108 void DefaultColorArrays(Entries, ForePixels, Valid, InitRV, StatusStr)
109    int Entries, **ForePixels, **Valid, **InitRV;
110    char ***StatusStr;
111 {
112    register int i, *fore_pixels, pixel, *valid, *init_rv;
113 
114    pixel = myFgPixel;
115    *ForePixels = fore_pixels = (int*)malloc(Entries*sizeof(int));
116    if (*ForePixels == NULL) FailAllocMessage();
117    *Valid = valid = (int*)malloc(Entries*sizeof(int));
118    if (*Valid == NULL) FailAllocMessage();
119    *InitRV = init_rv = (int*)malloc(Entries*sizeof(int));
120    if (*InitRV == NULL) FailAllocMessage();
121    for (i=0; i < Entries; i++) {
122       *fore_pixels++ = pixel;
123       *valid++ = TRUE;
124       *init_rv++ = FALSE;
125    }
126    if (StatusStr != NULL) {
127       *StatusStr = (char**)malloc(Entries*sizeof(char*));
128       if (*StatusStr == NULL) FailAllocMessage();
129       for (i=0; i < Entries; i++) {
130          (*StatusStr)[i] = (char*)malloc((MAXSTRING+1)*sizeof(char));
131          if ((*StatusStr)[i] == NULL) FailAllocMessage();
132          *(*StatusStr)[i] = '\0';
133       }
134    }
135 }
136 
GetDrawingBgPixel(index,pixel)137 int GetDrawingBgPixel(index, pixel)
138    int index, pixel;
139 {
140    if (index != INVALID && index != BACKPAT) {
141       return pixel;
142    } else if (myFileBgColorStr == NULL) {
143       return myBgPixel;
144    } else {
145       return myFileBgPixel;
146    }
147 }
148 
GetDrawingFgPixel(index,pixel)149 int GetDrawingFgPixel(index, pixel)
150    int index, pixel;
151 {
152    if (index != INVALID && index != BACKPAT) {
153       return pixel;
154    } else if (myFileBgColorStr == NULL || myFileFgColorStr == NULL) {
155       return myFgPixel;
156    } else {
157       return myFileFgPixel;
158    }
159 }
160 
GetDrawingFgColorStr(index,pixel,color_buf,buf_sz)161 void GetDrawingFgColorStr(index, pixel, color_buf, buf_sz)
162    int index, pixel, buf_sz;
163    char *color_buf;
164 {
165    if (index != INVALID && index != BACKPAT) {
166       UtilStrCpyN(color_buf, buf_sz, colorMenuItems[index]);
167    } else if (myFileBgColorStr == NULL || myFileFgColorStr == NULL) {
168       UtilStrCpyN(color_buf, buf_sz, myFgColorStr);
169    } else {
170       UtilStrCpyN(color_buf, buf_sz, myFileFgColorStr);
171    }
172 }
173 
174 struct LocalColorRec {
175    char *name, *spec;
176    int len;
177 };
178 
179 static struct LocalColorRec *privateColorInfo=NULL;
180 
TgifParseColor(psz_color,p_color)181 int TgifParseColor(psz_color, p_color)
182    char *psz_color;
183    XColor *p_color;
184 {
185    struct LocalColorRec *ptr;
186    int len;
187 
188    if (p_color != NULL) memset(p_color, 0, sizeof(XColor));
189    if (!useLocalRGBTxt || *psz_color == '#') {
190       return (int)XParseColor(mainDisplay, mainColormap, psz_color, p_color);
191    }
192    len = strlen(psz_color);
193    for (ptr=privateColorInfo; ptr->name != NULL; ptr++) {
194       if (len == ptr->len && strcmp(psz_color, ptr->name) == 0) {
195          if (ptr->spec != NULL) {
196             return (int)XParseColor(mainDisplay, mainColormap, ptr->spec,
197                   p_color);
198          }
199          break;
200       }
201    }
202    return (int)XParseColor(mainDisplay, mainColormap, psz_color, p_color);
203 }
204 
ParseAndAllocColorByName(colorname,color,red_req,green_req,blue_req)205 int ParseAndAllocColorByName(colorname, color, red_req, green_req, blue_req)
206    char *colorname;
207    XColor *color;
208    unsigned short *red_req, *green_req, *blue_req;
209 {
210    Colormap colormap;
211 
212    if (!TgifParseColor(colorname, color)) {
213       fprintf(stderr, TgLoadString(STID_WARN_CANNOT_PARSE_NAMED_COLOR),
214             colorname);
215       fprintf(stderr, "\n");
216       return FALSE;
217    }
218    if (red_req != NULL) *red_req = color->red;
219    if (green_req != NULL) *green_req = color->green;
220    if (blue_req != NULL) *blue_req = color->blue;
221    if (!XAllocColor(mainDisplay, mainColormap, color)) {
222       if (newColormapUsed) {
223          fprintf(stderr, TgLoadString(STID_CANNOT_ALLOC_NAMED_COLOR),
224                colorname);
225          fprintf(stderr, "\n");
226          return FALSE;
227       }
228       colormap = XCopyColormapAndFree(mainDisplay, mainColormap);
229       mainColormap = colormap;
230       newColormapUsed = TRUE;
231       if (mainWindow != None) {
232          XSetWindowColormap(mainDisplay, mainWindow, mainColormap);
233       }
234       if (!XAllocColor(mainDisplay, mainColormap, color)) {
235          fprintf(stderr, TgLoadString(STID_CANNOT_ALLOC_NAMED_COLOR),
236                colorname);
237          fprintf(stderr, "\n");
238          return FALSE;
239       }
240    }
241    return TRUE;
242 }
243 
RecalcXorPixels()244 void RecalcXorPixels()
245 {
246    int i, bg_pixel;
247 
248    bg_pixel = GetDrawingBgPixel(INVALID, INVALID);
249    if (xorColorPixels != NULL) {
250       for (i=0; i < maxColors; i++) {
251          xorColorPixels[i] = colorPixels[i] ^ bg_pixel;
252       }
253    }
254 }
255 
256 static
InitLocalRGBTxt()257 void InitLocalRGBTxt()
258 {
259    char *c_ptr;
260 
261    useLocalRGBTxt = FALSE;
262    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"LocalRGBTxt")) != NULL) {
263       char *fname=UtilStrDup(c_ptr);
264       FILE *fp;
265 
266       if (fname == NULL) { FailAllocMessage(); return; }
267       if ((fp=fopen(fname, "r")) != NULL) {
268          int num_lines=0, ok=TRUE, line_num=0, info_index=0;
269          char *buf;
270 
271          while (fgets(gszMsgBox, sizeof(gszMsgBox), fp) != NULL) {
272             int len=strlen(gszMsgBox);
273 
274             if (len > 0 && gszMsgBox[len-1] != '\n') {
275                while (fgets(gszMsgBox, sizeof(gszMsgBox), fp) != NULL) {
276                   len = strlen(gszMsgBox);
277                   if (len > 0 && gszMsgBox[len-1] == '\n') break;
278                }
279             }
280             num_lines++;
281          }
282          rewind(fp);
283          if ((privateColorInfo=(struct LocalColorRec *)malloc(
284                (num_lines+1)*sizeof(struct LocalColorRec))) == NULL) {
285             FailAllocMessage();
286             ok = FALSE;
287          }
288          while ((buf=UtilGetALine(fp)) != NULL) {
289             char *red_str, *green_str, *blue_str, *color_name;
290 
291             line_num++;
292             if ((red_str=strtok(buf, " \t\n\r")) != NULL &&
293                   (green_str=strtok(NULL, " \t\n\r")) != NULL &&
294                   (blue_str=strtok(NULL, " \t\n\r")) != NULL &&
295                   (color_name=strtok(NULL, "\t\n\r")) != NULL) {
296                struct LocalColorRec *color_info_ptr;
297                int red, green, blue;
298 
299                color_info_ptr = (&privateColorInfo[info_index]);
300                while (*color_name == ' ' || *color_name == '\t') color_name++;
301                if (sscanf(red_str, "%d", &red) == 1 &&
302                      sscanf(green_str, "%d", &green) == 1 &&
303                      sscanf(blue_str, "%d", &blue) == 1 &&
304                      red >= 0 && red <= 0xff && green >= 0 && green <= 0xff &&
305                      blue >= 0 && blue <= 0xff && *color_name != '\0') {
306                   color_info_ptr->name = UtilStrDup(color_name);
307                   if (color_info_ptr->name == NULL) FailAllocMessage();
308                   color_info_ptr->len = strlen(color_info_ptr->name);
309                   sprintf(gszMsgBox, "#%02x%02x%02x", red, green, blue);
310                   color_info_ptr->spec = UtilStrDup(gszMsgBox);
311                   if (color_info_ptr->spec == NULL) FailAllocMessage();
312                   info_index++;
313                } else {
314                   fprintf(stderr,
315                         TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
316                         line_num, fname);
317                   fprintf(stderr, "\n");
318                }
319             } else {
320                fprintf(stderr,
321                      TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
322                      line_num, fname);
323                fprintf(stderr, "\n");
324             }
325             privateColorInfo[info_index].name = NULL;
326             privateColorInfo[info_index].len = 0;
327             free(buf);
328          }
329          fclose(fp);
330          if (ok) useLocalRGBTxt = TRUE;
331       } else {
332          fprintf(stderr, TgLoadString(STID_INVALID_FILE_IN_X_DEFAULT),
333                fname, TOOL_NAME, "LocalRGBTxt");
334          fprintf(stderr, "\n");
335       }
336       free(fname);
337    }
338    printUsingRequestedColor = cmdLineRequestedColor;
339    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PrintUsingRequestedColor")) !=
340          NULL && (strcmp(c_ptr, "true") == 0 || strcmp(c_ptr, "True") == 0)) {
341       printUsingRequestedColor = TRUE;
342    }
343 }
344 
345 static
InitColorFromXPixmap(pn_num_colors,pppsz_color_str)346 int InitColorFromXPixmap(pn_num_colors, pppsz_color_str)
347    int *pn_num_colors;
348    char ***pppsz_color_str;
349    /* return TRUE mean maxColors and initial colors are setup */
350 {
351    char *c_ptr, xpm_fname[MAXPATHLENGTH], *color_char=NULL, **color_str=NULL;
352    int i, ncolors=0, rc;
353 
354    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ColorFromXPixmap")) == NULL) {
355       return FALSE;
356    }
357    strncpy(xpm_fname, c_ptr, sizeof(xpm_fname));
358    rc = MyReadPixmapFile(xpm_fname, NULL, NULL, NULL, NULL, NULL,
359          NULL, NULL, NULL, &ncolors, NULL, NULL, &color_char, &color_str,
360          NULL, NULL);
361    if (rc != BitmapSuccess) {
362       fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_GET),
363             TOOL_NAME, "ColorFromXPixmap", xpm_fname);
364       fprintf(stderr, "\n");
365       return FALSE;
366    }
367    if (myReadTransparentPixmap) {
368       fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_TRANS),
369             TOOL_NAME, "ColorFromXPixmap", xpm_fname);
370       fprintf(stderr, "\n");
371       if (color_str != NULL) {
372          for (i=0; i < ncolors; i++) {
373             if (color_str[i] != NULL) {
374                free(color_str[i]);
375             }
376          }
377          free(color_str);
378       }
379       if (color_char != NULL) free(color_char);
380       return FALSE;
381    }
382    *pn_num_colors = ncolors;
383    *pppsz_color_str = color_str;
384    if (color_char != NULL) free(color_char);
385    return TRUE;
386 }
387 
388 static
DoSetAltEditTextBgColor()389 int DoSetAltEditTextBgColor()
390 {
391    int new_alloc=FALSE;
392 
393    if (*altEditTextBgColorStr == '\0') return FALSE;
394 
395    altEditTextBgIndex = QuickFindColorIndex(NULL, altEditTextBgColorStr,
396          &new_alloc, FALSE);
397    if (altEditTextBgIndex == INVALID) {
398       sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_EDIT_TEXT_BGCOLOR),
399             altEditTextBgColorStr);
400       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
401       *altEditTextBgColorStr = '\0';
402       return FALSE;
403    }
404    if (colorLayers) RedrawColorWindow();
405 
406    return TRUE;
407 }
408 
409 static
DoSetAltEditTextHighlightColor()410 int DoSetAltEditTextHighlightColor()
411 {
412    int new_alloc=FALSE;
413 
414    if (*altEditTextHighlightColorStr == '\0') return FALSE;
415 
416    altEditTextHighlightIndex = QuickFindColorIndex(NULL,
417          altEditTextHighlightColorStr, &new_alloc, FALSE);
418    if (altEditTextHighlightIndex == INVALID) {
419       sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_EDIT_TEXT_HICOLOR),
420             altEditTextHighlightColorStr);
421       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
422       *altEditTextHighlightColorStr = '\0';
423       return FALSE;
424    }
425    if (colorLayers) RedrawColorWindow();
426 
427    return TRUE;
428 }
429 
430 static
DoSetDefaultBgColor()431 int DoSetDefaultBgColor()
432 {
433    int new_alloc=FALSE;
434 
435    if (*defaultBgColorStr == '\0') return FALSE;
436 
437    defaultBgColorIndex = QuickFindColorIndex(NULL, defaultBgColorStr,
438          &new_alloc, FALSE);
439    if (defaultBgColorIndex == INVALID) {
440       sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_DEF_BGCOLOR),
441             defaultBgColorStr);
442       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
443       *defaultBgColorStr = '\0';
444       return FALSE;
445    }
446    return TRUE;
447 }
448 
449 static int std_palette8[] = { 0x00, 0xff };
450 static int std_palette27[] = { 0x00, 0x80, 0xff };
451 static int std_palette64[] = { 0x00, 0x55, 0xaa, 0xff };
452 static int std_palette216[] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
453 static char *openoffice_galaxy_palette[] = {
454       /* black */
455       "#000000",
456       "#151a1f",
457       "#29333c",
458       "#4b5a66",
459       "#8b97a0",
460       "#bec5c9",
461       "#d8dcdf",
462       "#edf1f5",
463       "#ffffff",
464       /* blue-gray */
465       "#123349",
466       "#35556b",
467       "#5382a1",
468       "#a3b8cb",
469       "#dae3ea",
470       /* more-blue-gray */
471       "#003e6d",
472       "#005a9b",
473       "#0877bc",
474       "#71c0eb",
475       "#a4cef0",
476       "#ddedfa",
477       /* blue */
478       "#063d80",
479       "#0646a2",
480       "#0852d4",
481       "#085dff",
482       "#0fa0ff",
483       "#b8f1ff",
484       /* green */
485       "#063e00",
486       "#096000",
487       "#128902",
488       "#1cbb04",
489       "#8dff1a",
490       "#cfff9e",
491       /* yellow */
492       "#b2bc00",
493       "#7f7800",
494       "#46580b",
495       "#314005",
496       "#634900",
497       "#c69200",
498       /* orange */
499       "#f26a00",
500       "#faa217",
501       "#ffc726",
502       "#ffdf24",
503       "#fff67b",
504       "#ffff9e",
505       /* red */
506       "#6d0000",
507       "#8e0000",
508       "#c70909",
509       "#ff0000",
510       "#fc5b5b",
511       "#ffa199",
512       /* purple */
513       "#2e008f",
514       "#8866cc",
515       "#c2b0e5",
516       NULL
517 };
518 static char *openoffice_google_palette[] = {
519       /* black */
520       "#000000",
521       "#262626",
522       "#404040",
523       "#575757",
524       "#747474",
525       "#909090",
526       "#a8a8a8",
527       "#c5c5c5",
528       "#e6e6e6",
529       "#ffffff",
530       /* saturated */
531       "#ff0000",
532       "#ff9900",
533       "#ffff00",
534       "#98fe00",
535       "#00ff00",
536       "#00ffff",
537       "#0035ff",
538       "#9900ff",
539       "#ff00ff",
540       "#ff0187",
541       /* red */
542       "#660000",
543       "#990000",
544       "#cc0000",
545       "#f03939",
546       "#ea9999",
547       "#f4cccc",
548       /* orange */
549       "#783f04",
550       "#b45f06",
551       "#e69138",
552       "#f6b26b",
553       "#f9cb9c",
554       "#fce5cd",
555       /* yellow */
556       "#7f6b00",
557       "#bfa000",
558       "#f1d932",
559       "#ffe766",
560       "#ffec99",
561       "#fff6cc",
562       /* light green */
563       "#2c4a00",
564       "#4c7f00",
565       "#5f9f00",
566       "#84be2d",
567       "#acdb65",
568       "#d1e7b1",
569       /* green */
570       "#1c4e13",
571       "#26761d",
572       "#5ba84f",
573       "#84c47d",
574       "#b0d7a8",
575       "#d6ead3",
576       /* cyan */
577       "#0c343d",
578       "#134f5c",
579       "#45818e",
580       "#76a5af",
581       "#a2c4c9",
582       "#d0e0e3",
583       /* blue */
584       "#073763",
585       "#0b5394",
586       "#3d85c6",
587       "#6fa8dc",
588       "#9fc5e8",
589       "#cfe2f3",
590       /* purple */
591       "#20124d",
592       "#351c75",
593       "#674ea7",
594       "#8e7cc3",
595       "#b4a7d6",
596       "#d9d2e9",
597       /* magenta */
598       "#4c114a",
599       "#741b68",
600       "#a64d9b",
601       "#c27bbd",
602       "#d5a6d4",
603       "#ead1ea",
604       /* redish */
605       "#5a002f",
606       "#94004e",
607       "#c10066",
608       "#e53b94",
609       "#e895c1",
610       "#f6d1e5",
611       NULL
612 };
613 
InitColor()614 void InitColor()
615 {
616    int i, index=0, looking_for_default_color=FALSE, tmp_max, color_from_pixmap=FALSE;
617    XColor color;
618    char buf[80], *c_ptr, fg_color[80], bg_color[80], brdr_color[80];
619    long bg_gray=(long)0;
620    int bg_allocated=FALSE, fg_allocated=FALSE, brdr_allocated=FALSE, ncolors=0;
621    int std_palette=0, need_to_handle_additional_colors=FALSE;
622    char **color_str=NULL, *additional_colors_buf=NULL;
623 
624    InitLocalRGBTxt();
625 
626    strcpy(fg_color, "Black");
627    strcpy(bg_color, "White");
628    strcpy(brdr_color, "Black");
629    if (!initColorDontReload) {
630       reverseVideo = FALSE;
631       if (cmdLineRV != INVALID) {
632          reverseVideo = cmdLineRV;
633       } else if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ReverseVideo")) !=
634             NULL) {
635          reverseVideo = FALSE;
636          if (UtilStrICmp(c_ptr, "on") == 0 || UtilStrICmp(c_ptr, "true") == 0) {
637             reverseVideo = TRUE;
638          }
639       }
640       colorDump = (!PRTGIF);
641       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialPrintInColor")) !=
642             NULL && UtilStrICmp(c_ptr, "false") == 0) {
643          colorDump = FALSE;
644       }
645    }
646    defaultColorInXDefaults = FALSE;
647    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "DefaultColor"))
648          != NULL) {
649       defaultColorInXDefaults = TRUE;
650       UtilStrCpyN(defaultColorStr, sizeof(defaultColorStr), c_ptr);
651    }
652    defaultColorIndexInXDefaults = FALSE;
653    defaultColorIndex = 9;
654    if (!defaultColorInXDefaults) {
655       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "DefaultColorIndex"))
656             != NULL) {
657          defaultColorIndexInXDefaults = TRUE;
658          defaultColorIndex = atoi(c_ptr);
659       }
660    }
661    color_from_pixmap = InitColorFromXPixmap(&ncolors, &color_str);
662    if (color_from_pixmap && ncolors > 0 && color_str != NULL) {
663       maxColors = ncolors;
664       need_to_handle_additional_colors = TRUE;
665    } else {
666       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
667             "UseMobileWebSafePalette")) != NULL) {
668          maxColors = std_palette = 216;
669       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
670             "UseStdPalette216")) != NULL) {
671          maxColors = std_palette = 216;
672       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
673             "UseStdPalette64")) != NULL) {
674          maxColors = std_palette = 64;
675       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
676             "UseStdPalette27")) != NULL) {
677          maxColors = std_palette = 27;
678       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
679             "UseStdPalette8")) != NULL) {
680          maxColors = std_palette = 8;
681       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
682             "UseOpenOfficeGalaxyPalette")) != NULL) {
683          maxColors = std_palette = 53;
684       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
685             "UseOpenOfficeGooglePalette")) != NULL) {
686          maxColors = std_palette = 80;
687       } else {
688          maxColors = MAXCOLORS;
689          if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "MaxColors")) != NULL) {
690             maxColors = atoi(c_ptr);
691             if (maxColors <= 0) {
692                fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
693                      TOOL_NAME, "MaxColors", c_ptr, MAXCOLORS);
694                fprintf(stderr, "\n");
695                maxColors = MAXCOLORS;
696             }
697          }
698       }
699       if (std_palette > 0) {
700          need_to_handle_additional_colors = TRUE;
701       }
702    }
703    if (need_to_handle_additional_colors) {
704       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AdditionalColors")) !=
705             NULL) {
706          char *buf_copy=UtilStrDup(c_ptr), *psz_state=NULL;
707 
708          if (buf_copy == NULL) FailAllocMessage();
709          UtilTrimBlanks(buf_copy);
710          additional_colors_buf = UtilStrDup(buf_copy);
711          if (additional_colors_buf == NULL) FailAllocMessage();
712          for (c_ptr=UtilStrTok(buf_copy, ",\t\n\r", &psz_state); c_ptr != NULL;
713                c_ptr=UtilStrTok(NULL, ",\t\n\r", &psz_state)) {
714             maxColors++;
715          }
716          UtilFree(buf_copy);
717       }
718    }
719    if (colorDisplay) {
720       if (((cmdLineForeground != NULL && cmdLineBackground == NULL) ||
721             (cmdLineForeground == NULL && cmdLineBackground != NULL)) &&
722             reverseVideo) {
723          fprintf(stderr, TgLoadString(STID_NORM_VIDEO_MODE_ASSUMED),
724                (cmdLineForeground == NULL ? "-bg" : "-fg"));
725          fprintf(stderr, "\n");
726          reverseVideo = FALSE;
727       }
728       if (cmdLineForeground != NULL) {
729          strcpy(fg_color, cmdLineForeground);
730       } else if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"Foreground")) !=
731             NULL) {
732          if (reverseVideo) {
733             strcpy(bg_color, c_ptr);
734          } else {
735             strcpy(fg_color, c_ptr);
736          }
737       } else if (reverseVideo) {
738          strcpy(fg_color, "white");
739       } else {
740          strcpy(fg_color, "black");
741       }
742       if (cmdLineBackground != NULL) {
743          strcpy(bg_color, cmdLineBackground);
744       } else if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"Background")) !=
745             NULL) {
746          if (reverseVideo) {
747             strcpy(fg_color, c_ptr);
748          } else {
749             strcpy(bg_color, c_ptr);
750          }
751       } else if (reverseVideo) {
752          strcpy(bg_color, "black");
753       } else {
754          strcpy(bg_color, "white");
755       }
756       if (cmdLineBorder != NULL) {
757          strcpy(brdr_color, cmdLineBorder);
758       } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
759             "BorderColor")) != NULL) {
760          strcpy(brdr_color, c_ptr);
761       } else {
762          strcpy(brdr_color, fg_color);
763       }
764    } else {
765       if (reverseVideo) {
766          strcpy(fg_color, "white");
767          strcpy(bg_color, "black");
768       } else {
769          strcpy(fg_color, "black");
770          strcpy(bg_color, "white");
771       }
772       strcpy(brdr_color, fg_color);
773    }
774 
775    if (maxColors <= 0) {
776       fprintf(stderr, "%s\n", TgLoadString(STID_ZERO_COLORS_SPECIFIED));
777       exit (-1);
778    }
779 
780    colorPixels = (int*)malloc(maxColors*sizeof(int));
781    xorColorPixels = (int*)malloc(maxColors*sizeof(int));
782    colorLayerOn = (int*)malloc(maxColors*sizeof(int));
783    colorMenuItems = (char**)malloc(maxColors*sizeof(char*));
784    if (colorPixels == NULL || xorColorPixels == NULL || colorLayerOn == NULL ||
785          colorMenuItems == NULL) {
786       FailAllocMessage();
787    }
788 
789    tgifColors = (XColor*)malloc(maxColors*sizeof(XColor));
790    tgifRequestedColors = (XColor*)malloc(maxColors*sizeof(XColor));
791    if (tgifColors == NULL || tgifRequestedColors == NULL) FailAllocMessage();
792 
793    allocatedMaxColors = maxColors;
794    for (i=0; i < allocatedMaxColors; i++) {
795       colorMenuItems[i] = (char*)malloc(COLORSTRLEN*sizeof(char));
796       if (colorMenuItems[i] == NULL) FailAllocMessage();
797    }
798    if (color_from_pixmap && ncolors > 0 && color_str != NULL) {
799       for (i=0; i < maxColors; i++) {
800          strcpy(colorMenuItems[i], color_str[i]);
801          free(color_str[i]);
802          colorLayerOn[i] = TRUE;
803       }
804       free(color_str);
805       color_str = NULL;
806    } else {
807       int r=0, g=0, b=0;
808 
809       switch (std_palette) {
810       case 0:
811          for (i=0; i < maxColors; i++) {
812             sprintf(buf, "Color%1d", i);
813             if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, buf)) != NULL) {
814                UtilStrCpyN(colorMenuItems[i], COLORSTRLEN, c_ptr);
815             } else if (i < MAXCOLORS) {
816                UtilStrCpyN(colorMenuItems[i], COLORSTRLEN,
817                      defaultColorMenuItems[i]);
818             } else {
819                fprintf(stderr, TgLoadString(STID_CANNOT_GET_X_DEFAULT),
820                      TOOL_NAME, buf);
821                fprintf(stderr, "\n");
822                exit(-1);
823             }
824             UtilTrimBlanks(colorMenuItems[i]);
825             colorLayerOn[i] = TRUE;
826          }
827          break;
828       case 8:
829          i = 0;
830          for (r=0; r < 2; r++) {
831             for (g=0; g < 2; g++) {
832                for (b=0; b < 2; b++) {
833                   sprintf(colorMenuItems[i], "#%02x%02x%02x",
834                         std_palette8[r], std_palette8[g], std_palette8[b]);
835                   colorLayerOn[i] = TRUE;
836                   i++;
837                }
838             }
839          }
840          if (!defaultColorIndexInXDefaults) {
841             if (reverseVideo) {
842                defaultColorIndex = 7;
843             } else {
844                defaultColorIndex = 0;
845             }
846          }
847          break;
848       case 27:
849          i = 0;
850          for (r=0; r < 3; r++) {
851             for (g=0; g < 3; g++) {
852                for (b=0; b < 3; b++) {
853                   sprintf(colorMenuItems[i], "#%02x%02x%02x",
854                         std_palette27[r], std_palette27[g], std_palette27[b]);
855                   colorLayerOn[i] = TRUE;
856                   i++;
857                }
858             }
859          }
860          if (!defaultColorIndexInXDefaults) {
861             if (reverseVideo) {
862                defaultColorIndex = 26;
863             } else {
864                defaultColorIndex = 0;
865             }
866          }
867          break;
868       case 64:
869          i = 0;
870          for (r=0; r < 4; r++) {
871             for (g=0; g < 4; g++) {
872                for (b=0; b < 4; b++) {
873                   sprintf(colorMenuItems[i], "#%02x%02x%02x",
874                         std_palette64[r], std_palette64[g], std_palette64[b]);
875                   colorLayerOn[i] = TRUE;
876                   i++;
877                }
878             }
879          }
880          if (!defaultColorIndexInXDefaults) {
881             if (reverseVideo) {
882                defaultColorIndex = 63;
883             } else {
884                defaultColorIndex = 0;
885             }
886          }
887          break;
888       case 216:
889          i = 0;
890          for (r=0; r < 6; r++) {
891             for (g=0; g < 6; g++) {
892                for (b=0; b < 6; b++) {
893                   sprintf(colorMenuItems[i], "#%02x%02x%02x",
894                         std_palette216[r], std_palette216[g], std_palette216[b]);
895                   colorLayerOn[i] = TRUE;
896                   i++;
897                }
898             }
899          }
900          if (!defaultColorIndexInXDefaults) {
901             if (reverseVideo) {
902                defaultColorIndex = 215;
903             } else {
904                defaultColorIndex = 0;
905             }
906          }
907          break;
908       case 53: /* OpenOffice Galaxy Palette */
909          for (i=0; i < std_palette; i++) {
910             strcpy(colorMenuItems[i], openoffice_galaxy_palette[i]);
911             colorLayerOn[i] = TRUE;
912          }
913          if (!defaultColorIndexInXDefaults) {
914             if (reverseVideo) {
915                defaultColorIndex = 8;
916             } else {
917                defaultColorIndex = 0;
918             }
919          }
920          break;
921       case 80: /* OpenOffice Google Palette */
922          for (i=0; i < std_palette; i++) {
923             strcpy(colorMenuItems[i], openoffice_google_palette[i]);
924             colorLayerOn[i] = TRUE;
925          }
926          if (!defaultColorIndexInXDefaults) {
927             if (reverseVideo) {
928                defaultColorIndex = 9;
929             } else {
930                defaultColorIndex = 0;
931             }
932          }
933          break;
934       }
935    }
936    if (need_to_handle_additional_colors && additional_colors_buf != NULL) {
937       char *psz_state=NULL;
938 
939       for (c_ptr=UtilStrTok(additional_colors_buf, ",\t\n\r", &psz_state); c_ptr != NULL;
940             c_ptr=UtilStrTok(NULL, ",\t\n\r", &psz_state)) {
941          UtilStrCpyN(colorMenuItems[i], COLORSTRLEN, c_ptr);
942          colorLayerOn[i] = TRUE;
943          i++;
944       }
945       UtilFree(additional_colors_buf);
946    }
947    if (threeDLook) {
948       static int initVryLtPixel=FALSE;
949 
950       myBlackPixel = myWhitePixel = myLtGryPixel = myDkGryPixel = INVALID;
951       myVryLtPixel = myYellowPixel = INVALID;
952       memset(&color, 0, sizeof(XColor));
953       if (ParseAndAllocColorByName("black", &color, NULL, NULL, NULL)) {
954          myBlackPixel = color.pixel;
955       }
956       if (ParseAndAllocColorByName("white", &color, NULL, NULL, NULL)) {
957          myWhitePixel = color.pixel;
958       }
959       if (ParseAndAllocColorByName("#ffff00", &color, NULL, NULL, NULL)) {
960          myYellowPixel = color.pixel;
961       }
962       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"LightGrayColor")) != NULL) {
963          if (ParseAndAllocColorByName(c_ptr, &color, NULL, NULL, NULL)) {
964             myLtGryPixel = color.pixel;
965          } else {
966             fprintf(stderr, TgLoadString(STID_INVALID_XDEF_WILL_TRY_STR),
967                   TOOL_NAME, "LightGrayColor", c_ptr, "gray75");
968          }
969       }
970       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DarkGrayColor")) != NULL) {
971          if (ParseAndAllocColorByName(c_ptr, &color, NULL, NULL, NULL)) {
972             myDkGryPixel = color.pixel;
973          } else {
974             fprintf(stderr, TgLoadString(STID_INVALID_XDEF_WILL_TRY_STR),
975                   TOOL_NAME, "DarkGrayColor", c_ptr, "gray50");
976          }
977       }
978       if (initVryLtPixel && (c_ptr=XGetDefault(mainDisplay,TOOL_NAME,
979             "VeryLightGrayColor")) != NULL) {
980          if (ParseAndAllocColorByName(c_ptr, &color, NULL, NULL, NULL)) {
981             myVryLtPixel = color.pixel;
982          } else {
983             fprintf(stderr, TgLoadString(STID_INVALID_XDEF_WILL_TRY_STR),
984                   TOOL_NAME, "VeryLightGrayColor", c_ptr, "gray95");
985          }
986       }
987       if (myLtGryPixel == INVALID && ParseAndAllocColorByName("gray75", &color,             NULL, NULL, NULL)) {
988          myLtGryPixel = color.pixel;
989       }
990       if (myDkGryPixel == INVALID && ParseAndAllocColorByName("gray50", &color,
991             NULL, NULL, NULL)) {
992          myDkGryPixel = color.pixel;
993       }
994       if (initVryLtPixel && myVryLtPixel == INVALID &&
995             ParseAndAllocColorByName("gray95", &color, NULL, NULL, NULL)) {
996          myVryLtPixel = color.pixel;
997       }
998       if (myBlackPixel == INVALID || myWhitePixel == INVALID ||
999             myLtGryPixel == INVALID || myDkGryPixel == INVALID ||
1000             (initVryLtPixel && myVryLtPixel == INVALID) ||
1001             myYellowPixel == INVALID) {
1002          fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_ALLOC_3D_COLORS));
1003          threeDLook = FALSE;
1004       }
1005    }
1006    if (colorDisplay) {
1007       index = 0;
1008       for (i=0; i < maxColors; i++) {
1009          unsigned short red_req, green_req, blue_req;
1010 
1011          if (!ParseAndAllocColorByName(colorMenuItems[i], &color,
1012                &red_req, &green_req, &blue_req)) {
1013             fprintf(stderr, TgLoadString(STID_FAIL_TO_ALLOC_COLOR_NUM),
1014                   i, colorMenuItems[i], TOOL_NAME);
1015             fprintf(stderr, "\n");
1016             exit (-1);
1017          }
1018 
1019          if (i != index) strcpy(colorMenuItems[index], colorMenuItems[i]);
1020 
1021          colorPixels[index] = color.pixel;
1022 
1023          tgifColors[index].red = color.red;
1024          tgifColors[index].green = color.green;
1025          tgifColors[index].blue = color.blue;
1026 
1027          tgifRequestedColors[index].red = red_req;
1028          tgifRequestedColors[index].green = green_req;
1029          tgifRequestedColors[index].blue = blue_req;
1030 
1031          if (UtilStrICmp(colorMenuItems[i], fg_color) == 0) {
1032             myFgPixel = color.pixel;
1033             strcpy(myFgColorStr, fg_color);
1034 
1035             fg_allocated = TRUE;
1036          }
1037          if (UtilStrICmp(colorMenuItems[i], bg_color) == 0) {
1038             myBgPixel = color.pixel;
1039             myBgColor.pixel = color.pixel;
1040             myBgColor.red = color.red;
1041             myBgColor.green = color.green;
1042             myBgColor.blue = color.blue;
1043             strcpy(myBgColorStr, bg_color);
1044 
1045             bg_allocated = TRUE;
1046             bg_gray = (((long)tgifColors[i].red)<<2) +
1047                   (((long)tgifColors[i].green)<<3) + ((long)tgifColors[i].blue);
1048          }
1049          if (UtilStrICmp(colorMenuItems[i], brdr_color) == 0) {
1050             myBorderPixel = color.pixel;
1051             brdr_allocated = TRUE;
1052          }
1053          index++;
1054       }
1055       maxColors = index;
1056       if (maxColors <= 0) {
1057          fprintf(stderr, "%s\n", TgLoadString(STID_ZERO_COLORS_SPECIFIED));
1058          exit (-1);
1059       }
1060       looking_for_default_color = FALSE;
1061       if (defaultColorInXDefaults) {
1062          looking_for_default_color = TRUE;
1063          for (i=0; i < maxColors; i++) {
1064             if (UtilStrICmp(defaultColorStr, colorMenuItems[i]) == 0) {
1065                defaultColorIndex = i;
1066                looking_for_default_color = FALSE;
1067                break;
1068             }
1069          }
1070       } else if (defaultColorIndexInXDefaults) {
1071          if (defaultColorIndexInXDefaults && defaultColorIndex >= maxColors) {
1072             fprintf(stderr, TgLoadString(STID_DEFCOLORINDEX_GE_MAXCOLORS),
1073                   TOOL_NAME, "DefaultColorIndex", TOOL_NAME, "MaxColors",
1074                   TOOL_NAME, "DefaultColorIndex");
1075             fprintf(stderr, "\n");
1076             defaultColorIndex = 0;
1077          }
1078       } else {
1079          looking_for_default_color = TRUE;
1080          for (i=0; i < maxColors; i++) {
1081             if (UtilStrICmp(fg_color, colorMenuItems[i]) == 0) {
1082                defaultColorIndex = i;
1083                looking_for_default_color = FALSE;
1084                break;
1085             }
1086          }
1087       }
1088       if (!fg_allocated) {
1089          if (!ParseAndAllocColorByName(fg_color, &color, NULL, NULL, NULL)) {
1090             fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1091                   fg_color);
1092             fprintf(stderr, "\n");
1093             exit (-1);
1094          }
1095          myFgPixel = color.pixel;
1096          strcpy(myFgColorStr, fg_color);
1097       }
1098       if (!bg_allocated) {
1099          if (!ParseAndAllocColorByName(bg_color, &color, NULL, NULL, NULL)) {
1100             fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1101                   bg_color);
1102             fprintf(stderr, "\n");
1103             exit (-1);
1104          }
1105          myBgPixel = color.pixel;
1106          myBgColor.pixel = color.pixel;
1107          myBgColor.red = color.red;
1108          myBgColor.green = color.green;
1109          myBgColor.blue = color.blue;
1110          strcpy(myBgColorStr, bg_color);
1111          if (looking_for_default_color) {
1112             bg_gray = (((long)color.red)<<2) + (((long)color.green)<<3) +
1113                   ((long)color.blue);
1114          }
1115       }
1116       if (defaultColorInXDefaults && looking_for_default_color) {
1117          if (!ParseAndAllocColorByName(defaultColorStr, &color, NULL, NULL, NULL)) {
1118             fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_GET),
1119                   TOOL_NAME, "DefaultColor", defaultColorStr);
1120             fprintf(stderr, "\n");
1121             defaultColorInXDefaults = FALSE;
1122          }
1123          for (i=0; i < maxColors; i++) {
1124             if (color.pixel == colorPixels[i]) {
1125                defaultColorIndex = i;
1126                looking_for_default_color = FALSE;
1127                break;
1128             }
1129          }
1130          if (looking_for_default_color) {
1131             int new_alloc=FALSE;
1132 
1133             index = QuickFindColorIndex(NULL, defaultColorStr, &new_alloc, FALSE);
1134             if (index == INVALID) {
1135                fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_GET),
1136                      TOOL_NAME, "DefaultColor", defaultColorStr);
1137                fprintf(stderr, "\n");
1138                defaultColorInXDefaults = FALSE;
1139             } else {
1140                defaultColorIndex = index;
1141                looking_for_default_color = FALSE;
1142             }
1143          }
1144       }
1145       if (looking_for_default_color) {
1146          long val, val1;
1147 
1148          defaultColorIndex = 0;
1149          val = (((long)tgifColors[0].red)<<2) +
1150                (((long)tgifColors[0].green)<<3) + ((long)tgifColors[0].blue);
1151          if (bg_gray >= 0x67ff9) { /* (0xffff<<1) + (0xffff<<2) + (0x7fff) */
1152             for (i=1; i < maxColors; i++) {
1153                val1 = (((long)tgifColors[i].red)<<2) +
1154                      (((long)tgifColors[i].green)<<3) +
1155                      ((long)tgifColors[i].blue);
1156                if (val > val1) {
1157                   val = val1;
1158                   defaultColorIndex = i;
1159                }
1160             }
1161          } else {
1162             for (i=1; i < maxColors; i++) {
1163                val1 = (((long)tgifColors[i].red)<<2) +
1164                      (((long)tgifColors[i].green)<<3) +
1165                      ((long)tgifColors[i].blue);
1166                if (val < val1) {
1167                   val = val1;
1168                   defaultColorIndex = i;
1169                }
1170             }
1171          }
1172       }
1173       if (!brdr_allocated) {
1174          if (!ParseAndAllocColorByName(brdr_color, &color, NULL, NULL, NULL)) {
1175             fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1176                   brdr_color);
1177             fprintf(stderr, "\n");
1178             exit (-1);
1179          }
1180          myBorderPixel = color.pixel;
1181       }
1182       for (i=0; i < maxColors; i++) {
1183          xorColorPixels[i] = colorPixels[i] ^ myBgPixel;
1184       }
1185       colorIndex = defaultColorIndex;
1186    } else {
1187       /* !colorDisplay */
1188       if (!ParseAndAllocColorByName(fg_color, &color, NULL, NULL, NULL)) {
1189          fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1190                fg_color);
1191          fprintf(stderr, "\n");
1192          exit (-1);
1193       }
1194       myFgPixel = color.pixel;
1195       strcpy(myFgColorStr, fg_color);
1196 
1197       if (!ParseAndAllocColorByName(bg_color, &color, NULL, NULL, NULL)) {
1198          fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1199                bg_color);
1200          fprintf(stderr, "\n");
1201          exit (-1);
1202       }
1203       myBgPixel = color.pixel;
1204       strcpy(myBgColorStr, bg_color);
1205 
1206       if (!ParseAndAllocColorByName(brdr_color, &color, NULL, NULL, NULL)) {
1207          fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1208                brdr_color);
1209          fprintf(stderr, "\n");
1210          exit (-1);
1211       }
1212       myBorderPixel = color.pixel;
1213 
1214       for (i=0; i < maxColors; i++) {
1215          unsigned short red_req, green_req, blue_req;
1216 
1217          if (!ParseAndAllocColorByName(colorMenuItems[i], &color,
1218                &red_req, &green_req, &blue_req)) {
1219             fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_COLOR_NUM_ABORT),
1220                   i, colorMenuItems[i]);
1221             fprintf(stderr, "\n");
1222             exit (-1);
1223          }
1224 
1225          tgifColors[i].red = color.red;
1226          tgifColors[i].green = color.green;
1227          tgifColors[i].blue = color.blue;
1228 
1229          tgifRequestedColors[i].red = red_req;
1230          tgifRequestedColors[i].green = green_req;
1231          tgifRequestedColors[i].blue = blue_req;
1232 
1233          if (UtilStrICmp(colorMenuItems[i], bg_color) == 0) {
1234             colorPixels[i] = myBgPixel;
1235          } else {
1236             colorPixels[i] = myFgPixel;
1237          }
1238          xorColorPixels[i] = myFgPixel ^ myBgPixel;
1239       }
1240       colorIndex = defaultColorIndex;
1241    }
1242    if (!ParseAndAllocColorByName("black", &color, NULL, NULL, NULL)) {
1243       fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1244             "black");
1245       fprintf(stderr, "\n");
1246       exit (-1);
1247    }
1248    tmp_max = max(((int)color.red),max(((int)color.green),((int)color.blue)));
1249 #ifndef DONTFREECOLORS
1250    XFreeColors(mainDisplay, mainColormap, &(color.pixel), 1, 0);
1251 #endif
1252    if (tmp_max > maxRGB) maxRGB = tmp_max;
1253    if (!ParseAndAllocColorByName("white", &color, NULL, NULL, NULL)) {
1254       fprintf(stderr, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR_ABORT),
1255             "white");
1256       fprintf(stderr, "\n");
1257       exit (-1);
1258    }
1259    tmp_max = max(((int)color.red),max(((int)color.green),((int)color.blue)));
1260 #ifndef DONTFREECOLORS
1261    XFreeColors(mainDisplay, mainColormap, &(color.pixel), 1, 0);
1262 #endif
1263    if (tmp_max > maxRGB) maxRGB = tmp_max;
1264    if (tmp_max == 0) {
1265       fprintf(stderr, "%s\n", TgLoadString(STID_UNEXPECTED_MAX_RGB_ZERO));
1266    }
1267    *myRubberBandColorStr = '\0';
1268    myRubberBandPixel = INVALID;
1269    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"RubberBandColor")) != NULL &&
1270             ParseAndAllocColorByName(c_ptr, &color, NULL, NULL, NULL)) {
1271       strcpy(myRubberBandColorStr, c_ptr);
1272       myRubberBandPixel = color.pixel;
1273       xorOne = myRubberBandPixel^myBgPixel;
1274    } else {
1275       xorOne = myFgPixel^myBgPixel;
1276    }
1277 
1278    xorZero = myBgPixel;
1279    if (myFgPixel == myBgPixel) {
1280       fprintf(stderr, "%s\n", TgLoadString(STID_FG_BG_SAME_COLOR_WARNING));
1281    }
1282    if (!initColorDontReload) {
1283       canChangeAttrColor = FALSE;
1284       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"CanChangeAttrColor")) !=
1285             NULL && UtilStrICmp(c_ptr, "true") == 0) {
1286          canChangeAttrColor = TRUE;
1287       }
1288       colorLayers = FALSE;
1289       if (colorDisplay && (c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
1290             "ColorLayers")) != NULL && UtilStrICmp(c_ptr, "true") == 0) {
1291          colorLayers = TRUE;
1292       }
1293       *defaultBgColorStr = '\0';
1294       defaultBgColorIndex = INVALID;
1295       if (colorDisplay && (c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
1296             "DefaultObjectBackground")) != NULL) {
1297          strcpy(defaultBgColorStr, c_ptr);
1298       } else {
1299          strcpy(defaultBgColorStr, myBgColorStr);
1300       }
1301       DoSetDefaultBgColor();
1302 
1303       *altEditTextBgColorStr = *altEditTextHighlightColorStr = '\0';
1304       altEditTextBgIndex = altEditTextHighlightIndex = INVALID;
1305       useAltEditTextBgColor = FALSE;
1306    }
1307    if (!colorDisplay) {
1308       int new_alloc=FALSE;
1309       int color_index=QuickFindColorIndex(NULL, myFgColorStr, &new_alloc, TRUE);
1310 
1311       if (color_index == INVALID) {
1312          fprintf(stderr, TgLoadString(STID_CANNOT_SET_FG_COLOR), myFgColorStr,
1313                colorMenuItems[colorIndex]);
1314          fprintf(stderr, "\n");
1315       } else {
1316          colorIndex = color_index;
1317       }
1318    }
1319    UtilStrCpyN(pngExportTransparentColor, sizeof(pngExportTransparentColor),
1320          myBgColorStr);
1321    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PNGExportTransparentColor")) != NULL) {
1322       int new_alloc=0;
1323       char spec[MAXSTRING];
1324 
1325       UtilStrCpyN(spec, sizeof(spec), c_ptr);
1326       UtilTrimBlanks(spec);
1327 
1328       if (QuickFindColorIndex(NULL, spec, &new_alloc, FALSE) == INVALID) {
1329          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_GET),
1330                TOOL_NAME, "PNGExportTransparentColor", spec);
1331          fprintf(stderr, "\n");
1332          return;
1333       }
1334       UtilStrCpyN(pngExportTransparentColor, sizeof(pngExportTransparentColor), spec);
1335    }
1336 }
1337 
1338 static
DrawAVerticalTab(color_index,x,y,skip)1339 int DrawAVerticalTab(color_index, x, y, skip)
1340    int color_index, x, y, skip;
1341 {
1342    XPoint v[5];
1343    int offset;
1344 
1345    if (skip) return colorItemH;
1346 
1347    offset = ((colorItemH-7)>>1);
1348    v[0].x = v[4].x = x;   v[0].y = v[4].y = y;
1349    v[1].x = x+scrollBarW; v[1].y = y;
1350    v[2].x = x+scrollBarW; v[2].y = y+colorItemH;
1351    v[3].x = x;            v[3].y = y+colorItemH;
1352 
1353    XSetForeground(mainDisplay, defaultGC, colorPixels[color_index]);
1354    XFillPolygon(mainDisplay, colorWindow, defaultGC, v, 5, Convex,
1355          CoordModeOrigin);
1356    XSetForeground(mainDisplay, defaultGC, myBgPixel);
1357    XFillRectangle(mainDisplay, colorWindow, defaultGC, x+offset, y+offset,
1358          7, 7);
1359    XSetForeground(mainDisplay, defaultGC, myFgPixel);
1360    XDrawRectangle(mainDisplay, colorWindow, defaultGC, x+offset, y+offset,
1361          7, 7);
1362    if (colorLayerOn[color_index]) {
1363       XDrawLine(mainDisplay, colorWindow, defaultGC, x+offset, y+offset,
1364             x+offset+7, y+offset+7);
1365       XDrawLine(mainDisplay, colorWindow, defaultGC, x+offset,
1366             y+offset+7, x+offset+7, y+offset);
1367    }
1368    if (threeDLook) {
1369       struct BBRec bbox;
1370 
1371       SetBBRec(&bbox, x, y, x+scrollBarW-windowPadding, y+colorItemH);
1372       TgDrawThreeDButton(mainDisplay, colorWindow, textMenuGC, &bbox,
1373             TGBS_RAISED, 1, TRUE);
1374    } else {
1375       XDrawRectangle(mainDisplay, colorWindow, defaultGC, x, y,
1376             scrollBarW, colorItemH);
1377    }
1378    return colorItemH;
1379 }
1380 
RedrawColorWindow()1381 void RedrawColorWindow()
1382 {
1383    int i, x=(windowPadding>>1), y=0, y_start;
1384 
1385    needToRedrawColorWindow = FALSE;
1386    if (!colorLayers || colorWindow == None) return;
1387 
1388    XClearWindow(mainDisplay, colorWindow);
1389 
1390    y_start = y = (upend_height*MAX_VERTICAL_BTNS)+(windowPadding>>1);
1391    for (i=0; i < maxColors; i++) {
1392       if (i >= colorWindowFirstIndex) {
1393          int h=0;
1394 
1395          h = DrawAVerticalTab(i, x, y, FALSE);
1396          y += h;
1397          if (y > colorWindowH) break;
1398       }
1399    }
1400    for (i=0, y=(windowPadding>>1); i < MAX_VERTICAL_BTNS; i++,
1401          y += upend_height) {
1402       XSetTSOrigin(mainDisplay, rasterGC, x, y);
1403       XSetStipple(mainDisplay, rasterGC, scrollPixmap[i+4]);
1404       XFillRectangle(mainDisplay, colorWindow, rasterGC,
1405             x, y, upend_width, upend_height);
1406       if (threeDLook) {
1407          struct BBRec bbox;
1408 
1409          SetBBRec(&bbox, x, y, x+upend_height, y+upend_height);
1410          TgDrawThreeDButton(mainDisplay, colorWindow, textMenuGC, &bbox,
1411                TGBS_RAISED, 1, FALSE);
1412       }
1413    }
1414    XSetTSOrigin(mainDisplay, rasterGC, 0, 0);
1415    if (threeDLook) {
1416       XSetForeground(mainDisplay, defaultGC, myBorderPixel);
1417       XDrawRectangle(mainDisplay, colorWindow, defaultGC, 0, 0, scrollBarW-1,
1418             colorWindowH-1);
1419       XSetForeground(mainDisplay, defaultGC, myFgPixel);
1420    }
1421 }
1422 
OneColorObject(ObjPtr,ColorIndex)1423 int OneColorObject(ObjPtr, ColorIndex)
1424    struct ObjRec *ObjPtr;
1425    int *ColorIndex;
1426 {
1427    struct ObjRec *obj_ptr=NULL;
1428    struct TextRec *text_ptr=NULL;
1429 
1430    for (obj_ptr=ObjPtr->detail.r->last; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
1431       if (ObjPtr->type == OBJ_PIN && obj_ptr != GetPinObj(ObjPtr)) {
1432          continue;
1433       }
1434       switch (obj_ptr->type) {
1435       case OBJ_POLY:
1436          if (*ColorIndex == INVALID) {
1437             if ((obj_ptr->detail.p->fill != NONEPAT &&
1438                   obj_ptr->detail.p->fill != BACKPAT) ||
1439                   (obj_ptr->detail.p->pen != NONEPAT &&
1440                   obj_ptr->detail.p->pen != BACKPAT)) {
1441                *ColorIndex = obj_ptr->color;
1442             }
1443          } else if (obj_ptr->color != *ColorIndex) {
1444             if ((obj_ptr->detail.p->fill != NONEPAT &&
1445                   obj_ptr->detail.p->fill != BACKPAT) ||
1446                   (obj_ptr->detail.p->pen != NONEPAT &&
1447                   obj_ptr->detail.p->pen != BACKPAT)) {
1448                return FALSE;
1449             }
1450          }
1451          break;
1452       case OBJ_BOX:
1453          if (*ColorIndex == INVALID) {
1454             if ((obj_ptr->detail.b->fill != NONEPAT &&
1455                   obj_ptr->detail.b->fill != BACKPAT) ||
1456                   (obj_ptr->detail.b->pen != NONEPAT &&
1457                   obj_ptr->detail.b->pen != BACKPAT)) {
1458                *ColorIndex = obj_ptr->color;
1459             }
1460          } else if (obj_ptr->color != *ColorIndex) {
1461             if ((obj_ptr->detail.b->fill != NONEPAT &&
1462                   obj_ptr->detail.b->fill != BACKPAT) ||
1463                   (obj_ptr->detail.b->pen != NONEPAT &&
1464                   obj_ptr->detail.b->pen != BACKPAT)) {
1465                return FALSE;
1466             }
1467          }
1468          break;
1469       case OBJ_OVAL:
1470          if (*ColorIndex == INVALID) {
1471             if ((obj_ptr->detail.o->fill != NONEPAT &&
1472                   obj_ptr->detail.o->fill != BACKPAT) ||
1473                   (obj_ptr->detail.o->pen != NONEPAT &&
1474                   obj_ptr->detail.o->pen != BACKPAT)) {
1475                *ColorIndex = obj_ptr->color;
1476             }
1477          } else if (obj_ptr->color != *ColorIndex) {
1478             if ((obj_ptr->detail.o->fill != NONEPAT &&
1479                   obj_ptr->detail.o->fill != BACKPAT) ||
1480                   (obj_ptr->detail.o->pen != NONEPAT &&
1481                   obj_ptr->detail.o->pen != BACKPAT)) {
1482                return FALSE;
1483             }
1484          }
1485          break;
1486       case OBJ_TEXT:
1487          text_ptr = obj_ptr->detail.t;
1488 
1489          if (*ColorIndex == INVALID) {
1490             if (text_ptr->fill != NONEPAT && text_ptr->fill != BACKPAT) {
1491                *ColorIndex = obj_ptr->color;
1492             }
1493          }
1494          if (*ColorIndex == INVALID) {
1495             if (text_ptr->pen != NONEPAT && text_ptr->pen != BACKPAT) {
1496                MiniLinesInfo *minilines=(&text_ptr->minilines);
1497 
1498                *ColorIndex = minilines->first->first_block->seg->color;
1499                if (!OnePropertyMiniLines(PROP_MASK_COLOR,
1500                      minilines->first->first_block->seg->color, minilines,
1501                      TRUE)) {
1502                   return FALSE;
1503                }
1504             }
1505          } else {
1506             if (text_ptr->fill != NONEPAT && text_ptr->fill != BACKPAT) {
1507                if (*ColorIndex != obj_ptr->color) {
1508                   return FALSE;
1509                }
1510             }
1511             if (text_ptr->pen != NONEPAT && text_ptr->pen != BACKPAT) {
1512                if (!OnePropertyMiniLines(PROP_MASK_COLOR, *ColorIndex,
1513                      &text_ptr->minilines, TRUE)) {
1514                   return FALSE;
1515                }
1516             }
1517          }
1518          break;
1519       case OBJ_POLYGON:
1520          if (*ColorIndex == INVALID) {
1521             if ((obj_ptr->detail.g->fill != NONEPAT &&
1522                   obj_ptr->detail.g->fill != BACKPAT) ||
1523                   (obj_ptr->detail.g->pen != NONEPAT &&
1524                   obj_ptr->detail.g->pen != BACKPAT)) {
1525                *ColorIndex = obj_ptr->color;
1526             }
1527          } else if (obj_ptr->color != *ColorIndex) {
1528             if ((obj_ptr->detail.g->fill != NONEPAT &&
1529                   obj_ptr->detail.g->fill != BACKPAT) ||
1530                   (obj_ptr->detail.g->pen != NONEPAT &&
1531                   obj_ptr->detail.g->pen != BACKPAT)) {
1532                return FALSE;
1533             }
1534          }
1535          break;
1536       case OBJ_ARC:
1537          if (*ColorIndex == INVALID) {
1538             if ((obj_ptr->detail.a->fill != NONEPAT &&
1539                   obj_ptr->detail.a->fill != BACKPAT) ||
1540                   (obj_ptr->detail.a->pen != NONEPAT &&
1541                   obj_ptr->detail.a->pen != BACKPAT)) {
1542                *ColorIndex = obj_ptr->color;
1543             }
1544          } else if (obj_ptr->color != *ColorIndex) {
1545             if ((obj_ptr->detail.a->fill != NONEPAT &&
1546                   obj_ptr->detail.a->fill != BACKPAT) ||
1547                   (obj_ptr->detail.a->pen != NONEPAT &&
1548                   obj_ptr->detail.a->pen != BACKPAT)) {
1549                return FALSE;
1550             }
1551          }
1552          break;
1553       case OBJ_RCBOX:
1554          if (*ColorIndex == INVALID) {
1555             if ((obj_ptr->detail.rcb->fill != NONEPAT &&
1556                   obj_ptr->detail.rcb->fill != BACKPAT) ||
1557                   (obj_ptr->detail.rcb->pen != NONEPAT &&
1558                   obj_ptr->detail.rcb->pen != BACKPAT)) {
1559                *ColorIndex = obj_ptr->color;
1560             }
1561          } else if (obj_ptr->color != *ColorIndex) {
1562             if ((obj_ptr->detail.rcb->fill != NONEPAT &&
1563                   obj_ptr->detail.rcb->fill != BACKPAT) ||
1564                   (obj_ptr->detail.rcb->pen != NONEPAT &&
1565                   obj_ptr->detail.rcb->pen != BACKPAT)) {
1566                return FALSE;
1567             }
1568          }
1569          break;
1570       case OBJ_XBM:
1571          if (*ColorIndex == INVALID) {
1572             if (obj_ptr->detail.xbm->fill != NONEPAT &&
1573                   obj_ptr->detail.xbm->fill != BACKPAT) {
1574                *ColorIndex = obj_ptr->color;
1575             }
1576          } else if (obj_ptr->color != *ColorIndex) {
1577             if (obj_ptr->detail.xbm->fill != NONEPAT &&
1578                   obj_ptr->detail.xbm->fill != BACKPAT) {
1579                return FALSE;
1580             }
1581          }
1582          break;
1583       case OBJ_XPM:
1584          if (*ColorIndex == INVALID) {
1585             *ColorIndex = obj_ptr->color;
1586          } else if (obj_ptr->color != *ColorIndex) {
1587             return FALSE;
1588          }
1589          break;
1590       case OBJ_GROUP:
1591       case OBJ_SYM:
1592       case OBJ_ICON:
1593       case OBJ_PIN:
1594          if (!OneColorObject(obj_ptr, ColorIndex)) {
1595             return FALSE;
1596          }
1597          break;
1598       }
1599    }
1600    return TRUE;
1601 }
1602 
ChangeObjColor(ObjPtr,ColorIndex)1603 int ChangeObjColor(ObjPtr, ColorIndex)
1604    struct ObjRec *ObjPtr;
1605    int ColorIndex;
1606 {
1607    register struct ObjRec *obj_ptr;
1608    register struct AttrRec *attr_ptr;
1609    int changed=FALSE, icon_color_index;
1610 
1611    switch (ObjPtr->type) {
1612    case OBJ_POLY:
1613    case OBJ_BOX:
1614    case OBJ_OVAL:
1615    case OBJ_TEXT:
1616    case OBJ_POLYGON:
1617    case OBJ_ARC:
1618    case OBJ_RCBOX:
1619    case OBJ_XBM:
1620    case OBJ_XPM:
1621       if (ObjPtr->type == OBJ_TEXT) {
1622          if (SetMiniLinesProperty(PROP_MASK_COLOR, ColorIndex,
1623                &ObjPtr->detail.t->minilines)) {
1624             InvalidateTextCache(ObjPtr->detail.t);
1625             changed = TRUE;
1626          }
1627       } else if (ObjPtr->color != ColorIndex) {
1628          ObjPtr->color = ColorIndex;
1629          if (mainDisplay != NULL) {
1630             UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
1631                   colorMenuItems[ObjPtr->color]);
1632          }
1633          if (ObjPtr->type == OBJ_XPM) {
1634             /* RecolorXPmObj(ObjPtr, ColorIndex); */
1635          }
1636          changed = TRUE;
1637       }
1638       break;
1639 
1640    case OBJ_GROUP:
1641    case OBJ_SYM:
1642       for (obj_ptr = ObjPtr->detail.r->last; obj_ptr != NULL;
1643             obj_ptr = obj_ptr->prev) {
1644          if (ChangeObjColor(obj_ptr, ColorIndex)) {
1645             changed = TRUE;
1646          }
1647       }
1648       break;
1649 
1650    case OBJ_ICON:
1651       icon_color_index = INVALID;
1652       if (OneColorObject(ObjPtr, &icon_color_index) &&
1653             icon_color_index != ColorIndex) {
1654          for (obj_ptr = ObjPtr->detail.r->last; obj_ptr != NULL;
1655                obj_ptr = obj_ptr->prev) {
1656             if (ChangeObjColor(obj_ptr, ColorIndex)) {
1657                changed = TRUE;
1658             }
1659          }
1660       }
1661       break;
1662 
1663    case OBJ_PIN:
1664       icon_color_index = INVALID;
1665       if (OneColorObject(GetPinObj(ObjPtr), &icon_color_index) &&
1666             icon_color_index != ColorIndex) {
1667          if (ChangeObjColor(GetPinObj(ObjPtr), ColorIndex)) {
1668             changed = TRUE;
1669          }
1670       }
1671       break;
1672    }
1673    if ((canChangeAttrColor || changePropertiesOfAttrs) &&
1674          ObjPtr->type != OBJ_TEXT) {
1675       for (attr_ptr=ObjPtr->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
1676          if (SetMiniLinesProperty(PROP_MASK_COLOR, ColorIndex,
1677                &attr_ptr->obj->detail.t->minilines)) {
1678             InvalidateTextCache(attr_ptr->obj->detail.t);
1679             changed = TRUE;
1680          }
1681       }
1682    }
1683    return changed;
1684 }
1685 
ChangeAllSelColor(ColorIndex,HighLight)1686 void ChangeAllSelColor(ColorIndex, HighLight)
1687    int ColorIndex, HighLight;
1688 {
1689    register struct SelRec *sel_ptr;
1690    int changed=FALSE, dont_do_obj=FALSE;
1691    int saved_sticky_menu_selection=stickyMenuSelection;
1692    int dont_check_text=FALSE;
1693    XGCValues values;
1694 
1695    if (topSel != NULL && topSel == botSel && topSel->obj->type == OBJ_XPM) {
1696       /* if the only selected object is an OBJ_XPM, chang the current color */
1697       stickyMenuSelection = TRUE;
1698       if (gnInImageProc) dont_check_text = TRUE;
1699       dont_do_obj = TRUE;
1700    }
1701    if (topSel == NULL || stickyMenuSelection) {
1702       int text_obj_created=FALSE, text_cursor_shown=FALSE;
1703 
1704       if (!dont_check_text) {
1705          if (!(curChoice == DRAWTEXT && textCursorShown)) {
1706             text_cursor_shown = textCursorShown;
1707             text_obj_created = TieLooseEnds();
1708          }
1709       }
1710       colorIndex = ColorIndex;
1711       if (colorLayers && !colorLayerOn[colorIndex]) {
1712          if (topSel == NULL) {
1713             sprintf(gszMsgBox, TgLoadString(STID_INVISIBLE_COLOR_SELECTED),
1714                   colorIndex, colorMenuItems[colorIndex]);
1715             Msg(gszMsgBox);
1716          }
1717       }
1718       ShowColor(TRUE);
1719       UpdatePinnedMenu(MENU_COLOR);
1720       if (!PRTGIF && colorLayers && needToRedrawColorWindow) {
1721          RedrawColorWindow();
1722       }
1723       if (!dont_check_text) {
1724          if (curChoice == DRAWTEXT && textCursorShown) {
1725             text_cursor_shown = TRUE;
1726             if (ChangeEditTextProperty(PROP_MASK_COLOR, colorIndex)) {
1727                curTextModified = TRUE;
1728                RedrawCurText();
1729                SetFileModified(TRUE);
1730                if (cycleThroughChoice) {
1731                   SetPushedFontValue(PUSH_COLORINDEX, colorIndex);
1732                }
1733             }
1734          } else {
1735             textCursorShown = FALSE;
1736          }
1737       }
1738       if (topSel == NULL) dont_do_obj = TRUE;
1739    }
1740    stickyMenuSelection = saved_sticky_menu_selection;
1741    sprintf(gszMsgBox, TgLoadString(STID_COLOR_SET_TO),
1742          colorMenuItems[ColorIndex]);
1743    Msg(gszMsgBox);
1744    if (dont_do_obj) return;
1745 
1746    values.foreground = colorPixels[ColorIndex];
1747    values.function = GXcopy;
1748    values.fill_style = FillSolid;
1749    XChangeGC(mainDisplay, drawGC,
1750          GCForeground | GCFunction | GCFillStyle, &values);
1751 
1752    if (HighLight) HighLightReverse();
1753    StartCompositeCmd();
1754    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1755       PrepareToReplaceAnObj(sel_ptr->obj);
1756       if (ChangeObjColor(sel_ptr->obj, ColorIndex)) {
1757          changed = TRUE;
1758          RecordReplaceAnObj(sel_ptr->obj);
1759       } else {
1760          AbortPrepareCmd(CMD_REPLACE);
1761       }
1762    }
1763    EndCompositeCmd();
1764 
1765    if (changed) {
1766       int need_to_update_sel_bbox=FALSE;
1767 
1768       if (!PRTGIF && colorLayers) {
1769          struct SelRec *next_sel;
1770 
1771          for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=next_sel) {
1772             struct ObjRec *obj_ptr=sel_ptr->obj;
1773 
1774             next_sel = sel_ptr->next;
1775             obj_ptr->tmp_parent = NULL;
1776             if (!ObjInVisibleLayer(obj_ptr)) {
1777                need_to_update_sel_bbox = TRUE;
1778                if (sel_ptr->prev == NULL) {
1779                   topSel = sel_ptr->next;
1780                } else {
1781                   sel_ptr->prev->next = sel_ptr->next;
1782                }
1783                if (sel_ptr->next == NULL) {
1784                   botSel = sel_ptr->prev;
1785                } else {
1786                   sel_ptr->next->prev = sel_ptr->prev;
1787                }
1788                free(sel_ptr);
1789             }
1790          }
1791          if (needToRedrawColorWindow) {
1792             RedrawColorWindow();
1793          }
1794       }
1795       SetFileModified(TRUE);
1796       RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1),
1797             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
1798             selRbY+GRID_ABS_SIZE(1));
1799       if (need_to_update_sel_bbox) UpdSelBBox();
1800    }
1801    if (HighLight) HighLightForward();
1802 }
1803 
SetUpColorMenuPixmap(fore_colors,init_rv,pixmap,rows,cols)1804 void SetUpColorMenuPixmap(fore_colors, init_rv, pixmap, rows, cols)
1805    int **fore_colors, **init_rv, *rows, *cols;
1806    Pixmap **pixmap;
1807 {
1808    register int i;
1809 
1810    *pixmap = (Pixmap*)malloc(maxColors*sizeof(Pixmap));
1811    *fore_colors = (int*)malloc(maxColors*sizeof(int));
1812    *init_rv = (int*)malloc(maxColors*sizeof(int));
1813    if (*pixmap == NULL || *fore_colors == NULL || *init_rv == NULL) {
1814       FailAllocMessage();
1815    }
1816    for (i=0; i < maxColors; i++) {
1817       (*pixmap)[i] = patPixmap[SOLIDPAT];
1818       (*fore_colors)[i] = colorPixels[i];
1819       (*init_rv)[i] = FALSE;
1820    }
1821    *cols = ((maxColors % 10)==0) ? (int)(maxColors/10) : (int)(maxColors/10)+1;
1822    *rows = (maxColors <= 10) ? maxColors : 10;
1823 }
1824 
RefreshColorMenu(menu)1825 void RefreshColorMenu(menu)
1826    TgMenu *menu;
1827 {
1828    int i, num_items=menu->num_items;
1829    TgMenuItem *menuitems=menu->menuitems;
1830 
1831    for (i=0; i < num_items; i++) {
1832       TgMenuItem *menu_item=(&menuitems[i]);
1833       TgMenuItem stMenuItem;
1834 
1835       memset(&stMenuItem, 0, sizeof(TgMenuItem));
1836       stMenuItem.state = TGBS_NORMAL;
1837       stMenuItem.checked = (i == colorIndex);
1838       TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
1839             &stMenuItem);
1840    }
1841 }
1842 
CreateColorMenu(parent_menu,x,y,menu_info,status_str_xlated)1843 TgMenu *CreateColorMenu(parent_menu, x, y, menu_info, status_str_xlated)
1844    TgMenu *parent_menu;
1845    int x, y;
1846    TgMenuInfo *menu_info;
1847    int status_str_xlated; /* ignored, always 0 */
1848 {
1849    int i=0;
1850    TgMenu *menu=NULL;
1851    TgMenuInfo stMenuInfo;
1852    TgMenuItemInfo *item_info=NULL;
1853 
1854    memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
1855    stMenuInfo.items = (TgMenuItemInfo*)malloc(
1856          (maxColors+1)*sizeof(TgMenuItemInfo));
1857    if (stMenuInfo.items == NULL) FailAllocMessage();
1858    memset(stMenuInfo.items, 0, (maxColors+1)*sizeof(TgMenuItemInfo));
1859    for (item_info=stMenuInfo.items, i=0; i < maxColors; item_info++, i++) {
1860       item_info->menu_str = (char*)(int*)(&colorPixels[i]);
1861       item_info->shortcut_str = NULL;
1862       sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_COLOR_TO),
1863             colorMenuItems[i]);
1864       item_info->status_str = UtilStrDup(gszMsgBox);
1865       if (item_info->status_str == NULL) FailAllocMessage();
1866       item_info->submenu_info = NULL;
1867       item_info->cmdid = CMDID_CHANGEALLSELCOLOR;
1868    }
1869    stMenuInfo.items[maxColors].cmdid = INVALID;
1870    stMenuInfo.type |= TGMUTYPE_CANSCROLL;
1871 
1872    /* the status_str has been translated in TgLoadCachedString() */
1873    menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
1874    for (item_info=stMenuInfo.items, i=0; i < maxColors; item_info++, i++) {
1875       UtilFree(item_info->status_str);
1876    }
1877    memset(stMenuInfo.items, 0, (maxColors+1)*sizeof(TgMenuItemInfo));
1878    free(stMenuInfo.items);
1879    stMenuInfo.items = NULL;
1880    if (menu != NULL) {
1881       TgMenuItem *menu_item=NULL;
1882       TgMenuItem stMenuItem;
1883 
1884       menu->track_menubar = TRUE;
1885       TgAdjustMenuGeometry(menu, 16, 16, 10);
1886       menu_item = (&menu->menuitems[colorIndex]);
1887 
1888       memset(&stMenuItem, 0, sizeof(TgMenuItem));
1889       stMenuItem.checked = TRUE;
1890       if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
1891          return TgDestroyMenu(menu, TRUE);
1892       }
1893       SetScrollableMenuFirstIndex(menu, colorIndex);
1894    }
1895    return menu;
1896 }
1897 
ColorMenu(X,Y,TrackMenubar)1898 int ColorMenu(X, Y, TrackMenubar)
1899    int X, Y, TrackMenubar;
1900 {
1901    int rc=INVALID;
1902    TgMenu *menu=(colorMenuInfo.create_proc)(NULL, X, Y, &colorMenuInfo,
1903          INVALID);
1904 
1905    activeMenu = MENU_COLOR;
1906    if (menu != NULL) {
1907       menu->track_menubar = TrackMenubar;
1908 
1909       rc = TgMenuLoop(menu);
1910       TgDestroyMenu(menu, TRUE);
1911    }
1912    return rc;
1913 }
1914 
CleanUpColors()1915 void CleanUpColors()
1916 {
1917    register int i;
1918 
1919    if (privateColorInfo != NULL) {
1920       struct LocalColorRec *ptr;
1921 
1922       for (ptr=privateColorInfo; ptr->name != NULL; ptr++) {
1923          free(ptr->name);
1924          if (ptr->spec != NULL) free(ptr->spec);
1925       }
1926       free(privateColorInfo);
1927       privateColorInfo = NULL;
1928    }
1929    if (colorLayerOn != NULL) free(colorLayerOn);
1930    if (colorPixels != NULL) free(colorPixels);
1931    if (xorColorPixels != NULL) free(xorColorPixels);
1932    colorLayerOn = colorPixels = xorColorPixels = NULL;
1933 
1934    if (tgifColors != NULL) free(tgifColors);
1935    if (tgifRequestedColors != NULL) free(tgifRequestedColors);
1936    tgifColors = tgifRequestedColors = NULL;
1937 
1938    if (colorMenuItems != NULL) {
1939       for (i=0; i < maxColors; i++) {
1940          if (colorMenuItems[i] != NULL) free(colorMenuItems[i]);
1941       }
1942       free(colorMenuItems);
1943    }
1944    colorMenuItems = NULL;
1945 
1946    maxColors = 0;
1947    defaultColorIndex = 9;
1948    colorIndex = 0;
1949 
1950    if (upend_bits == NULL) { }
1951 }
1952 
1953 static
SetAllColorLayersState(on_state)1954 void SetAllColorLayersState(on_state)
1955    int on_state;
1956 {
1957    int i, changed=FALSE;
1958 
1959    for (i=0; i < maxColors; i++) {
1960       if (colorLayerOn[i] != on_state) {
1961          changed = TRUE;
1962          colorLayerOn[i] = on_state;
1963       }
1964    }
1965    strcpy(gszMsgBox, TgLoadString(on_state ? STID_ALL_COLOR_LAYERS_VISIBLE :
1966          STID_ALL_COLOR_LAYERS_INVISIBLE));
1967    Msg(gszMsgBox);
1968    if (changed) {
1969       MakeQuiescent();
1970       RedrawColorWindow();
1971       ClearAndRedrawDrawWindow();
1972       SetCurChoice(curChoiceBeforeMakeQuiescent);
1973    }
1974 }
1975 
1976 static
HandleClickInColorWindow(button_ev)1977 void HandleClickInColorWindow(button_ev)
1978    XButtonEvent *button_ev;
1979 {
1980    int i, index, total, offset;
1981 
1982    if (threeDLook) {
1983       index = (int)((button_ev->y-1-(windowPadding>>1)) / upend_height);
1984    } else {
1985       index = (int)((button_ev->y-1) / scrollBarW);
1986    }
1987    if (index < 0) index = 0;
1988 
1989    switch (index+4) {
1990    case SCROLL_UPEND:
1991    case SCROLL_UP:
1992    case SCROLL_CHECKALL:
1993    case SCROLL_UNCHECKALL:
1994    case SCROLL_DOWN:
1995    case SCROLL_DOWNEND:
1996       if (button_ev->button != Button1) return;
1997       break;
1998    default: break;
1999    }
2000 
2001    switch (index+4) {
2002    case SCROLL_UPEND:
2003       colorWindowFirstIndex = 0;
2004       RedrawColorWindow();
2005       break;
2006    case SCROLL_UP:
2007       if (colorWindowFirstIndex > 0) {
2008          if (button_ev->state & (ShiftMask | ControlMask)) {
2009             colorWindowFirstIndex -= 10;
2010             if (colorWindowFirstIndex < 0) colorWindowFirstIndex = 0;
2011          } else {
2012             colorWindowFirstIndex--;
2013          }
2014          RedrawColorWindow();
2015       }
2016       break;
2017    case SCROLL_CHECKALL: SetAllColorLayersState(TRUE); break;
2018    case SCROLL_UNCHECKALL: SetAllColorLayersState(FALSE); break;
2019    case SCROLL_DOWN:
2020       if (colorWindowFirstIndex < maxColors-1) {
2021          if (button_ev->state & (ShiftMask | ControlMask)) {
2022             colorWindowFirstIndex += 10;
2023             if (colorWindowFirstIndex > maxColors-1) {
2024                colorWindowFirstIndex = maxColors-1;
2025             }
2026          } else {
2027             colorWindowFirstIndex++;
2028          }
2029          RedrawColorWindow();
2030       }
2031       break;
2032    case SCROLL_DOWNEND:
2033       total = colorWindowH-(upend_height*MAX_VERTICAL_BTNS);
2034       colorWindowFirstIndex = maxColors-1;
2035       for (i=maxColors-1; i >= 0; i--) {
2036          int w=DrawAVerticalTab(i, 0, 0, TRUE);
2037 
2038          total -= w;
2039          if (total > 0) {
2040             colorWindowFirstIndex = i;
2041          } else {
2042             break;
2043          }
2044       }
2045       RedrawColorWindow();
2046       break;
2047    default:
2048       offset = button_ev->y-(upend_height*MAX_VERTICAL_BTNS);
2049       for (i=0; i < maxColors; i++) {
2050          if (i >= colorWindowFirstIndex) {
2051             int h=DrawAVerticalTab(i, 0, 0, TRUE);
2052 
2053             if (h >= offset) {
2054                if (button_ev->button == Button1) {
2055                   colorLayerOn[i] = !colorLayerOn[i];
2056                   sprintf(gszMsgBox, TgLoadString(colorLayerOn[i] ?
2057                         STID_A_COLOR_LAYER_TURNED_ON :
2058                         STID_A_COLOR_LAYER_TURNED_OFF),
2059                         colorMenuItems[i], i);
2060                   SetStringStatus(gszMsgBox);
2061                   if (i == colorIndex) {
2062                      sprintf(gszMsgBox,
2063                            TgLoadString(STID_INVISIBLE_COLOR_SELECTED),
2064                            colorIndex, colorMenuItems[colorIndex]);
2065                      Msg(gszMsgBox);
2066                   }
2067                   MakeQuiescent();
2068                   RedrawColorWindow();
2069                   ClearAndRedrawDrawWindow();
2070                   SetCurChoice(curChoiceBeforeMakeQuiescent);
2071                } else if (button_ev->button == Button3) {
2072                   int save_sticky_menu_selection=stickyMenuSelection;
2073 
2074                   stickyMenuSelection = TRUE;
2075                   ChangeAllSelColor(i, TRUE);
2076                   stickyMenuSelection = save_sticky_menu_selection;
2077                }
2078                break;
2079             }
2080             offset -= h;
2081          }
2082       }
2083       break;
2084    }
2085 }
2086 
2087 static
HandleMotionInColorWindow(motion_ev)2088 void HandleMotionInColorWindow(motion_ev)
2089    XMotionEvent *motion_ev;
2090 {
2091    int i, index, offset;
2092 
2093    if (threeDLook) {
2094       index = (int)((motion_ev->y-1-(windowPadding>>1)) / upend_height);
2095    } else {
2096       index = (int)((motion_ev->y-1) / scrollBarW);
2097    }
2098    if (index < 0) index = 0;
2099 
2100    switch (index+4) {
2101    case SCROLL_UPEND:
2102    case SCROLL_UP:
2103    case SCROLL_CHECKALL:
2104    case SCROLL_UNCHECKALL:
2105    case SCROLL_DOWN:
2106    case SCROLL_DOWNEND:
2107       if (motion_ev->state & (ShiftMask | ControlMask)) {
2108          SetColorMouseStatusStrings(TRUE, index);
2109       } else {
2110          SetColorMouseStatusStrings(FALSE, index);
2111       }
2112       break;
2113    default:
2114       offset = motion_ev->y-(upend_height*MAX_VERTICAL_BTNS);
2115       for (i=0; i < maxColors; i++) {
2116          if (i >= colorWindowFirstIndex) {
2117             int h=DrawAVerticalTab(i, 0, 0, TRUE);
2118 
2119             if (h >= offset) {
2120                char left_str[80], right_str[80];
2121 
2122                sprintf(left_str, TgLoadString(colorLayerOn[i] ?
2123                      STID_TURN_COLOR_LAYER_NUM_OFF :
2124                      STID_TURN_COLOR_LAYER_NUM_ON),
2125                      colorMenuItems[i], i);
2126                sprintf(right_str, TgLoadCachedString(CSTID_SET_COLOR_TO),
2127                      colorMenuItems[i]);
2128                SetMouseStatus(left_str, TgLoadCachedString(CSTID_PARANED_NONE),
2129                      right_str);
2130                break;
2131             }
2132             offset -= h;
2133          }
2134       }
2135       break;
2136    }
2137 }
2138 
ColorEventHandler(input)2139 void ColorEventHandler(input)
2140    XEvent *input;
2141 {
2142    XEvent ev;
2143 
2144    if (!colorLayers) return;
2145 
2146    if (input->type == Expose) {
2147       while (XCheckWindowEvent(mainDisplay, colorWindow, ExposureMask, &ev)) ;
2148       RedrawColorWindow();
2149    } else if (input->type == EnterNotify) {
2150       SetMouseStatus("", "", "");
2151    } else if (input->type == MotionNotify) {
2152       while (XCheckWindowEvent(mainDisplay,colorWindow,PointerMotionMask,&ev)) ;
2153       HandleMotionInColorWindow(&input->xmotion);
2154    } else if (input->type == ButtonPress) {
2155       XButtonEvent *button_ev=(&(input->xbutton));
2156 
2157       if (button_ev->button == Button1 || button_ev->button == Button3) {
2158          HandleClickInColorWindow(button_ev);
2159       }
2160    }
2161 }
2162 
RedrawColorDummyWindow()2163 void RedrawColorDummyWindow()
2164 {
2165    XClearWindow(mainDisplay, colorDummyWindow);
2166    if (threeDLook) {
2167       struct BBRec bbox;
2168 
2169       SetBBRec(&bbox, 0, 0, scrollBarW, colorDummyWindowH);
2170       TgDrawThreeDButton(mainDisplay, colorDummyWindow, textMenuGC, &bbox,
2171             TGBS_RAISED, 2, FALSE);
2172    }
2173 }
2174 
ColorDummyEventHandler(input)2175 void ColorDummyEventHandler(input)
2176    XEvent *input;
2177 {
2178    if (!colorLayers) return;
2179 
2180    if (input->type == Expose) {
2181       XEvent ev;
2182 
2183       while (XCheckWindowEvent(mainDisplay,colorDummyWindow,ExposureMask,&ev)) ;
2184       RedrawColorDummyWindow();
2185    } else if (input->type == EnterNotify) {
2186       SetMouseStatusToAllNone();
2187    }
2188 }
2189 
2190 typedef struct tagUpdatePixelRec {
2191    int picture_changed;
2192 } UpdatePixelInfo;
2193 
2194 static
UpdatePixelForStrSeg(pStrSeg,pUserData)2195 void UpdatePixelForStrSeg(pStrSeg, pUserData)
2196    StrSegInfo *pStrSeg;
2197    void *pUserData;
2198 {
2199    UpdatePixelInfo *pupi=((UpdatePixelInfo*)pUserData);
2200    int new_alloc=FALSE;
2201    int index=QuickFindColorIndex(NULL, pStrSeg->color_str, &new_alloc, TRUE);
2202 
2203    if (index != pStrSeg->color) pupi->picture_changed = TRUE;
2204    if (index == INVALID) {
2205       sprintf(gszMsgBox,
2206             TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2207             pStrSeg->color_str, colorMenuItems[colorIndex]);
2208       Msg(gszMsgBox);
2209       allocColorFailed = TRUE;
2210       pStrSeg->color = colorIndex;
2211    } else {
2212       pStrSeg->color = index;
2213    }
2214    if (mainDisplay != NULL) {
2215       UtilStrCpyN(pStrSeg->color_str, sizeof(pStrSeg->color_str),
2216             colorMenuItems[pStrSeg->color]);
2217    }
2218 }
2219 
UpdatePixel(ObjPtr)2220 int UpdatePixel(ObjPtr)
2221    struct ObjRec *ObjPtr;
2222 {
2223    int c, i, r;
2224    int ncolors=0, new_alloc=FALSE, index=0, changed=FALSE, len=0;
2225    int picture_changed=FALSE;
2226    unsigned long pixel=0L, *from_pixels=NULL, *to_pixels=NULL;
2227    struct ObjRec *obj_ptr=NULL;
2228    struct XPmRec *xpm_ptr=NULL;
2229    struct AttrRec *attr_ptr=NULL;
2230 
2231    switch (ObjPtr->type) {
2232    case OBJ_GROUP:
2233    case OBJ_SYM:
2234    case OBJ_ICON:
2235    case OBJ_PIN:
2236       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr!=NULL;
2237             obj_ptr=obj_ptr->prev) {
2238          if (UpdatePixel(obj_ptr)) {
2239             picture_changed = TRUE;
2240          }
2241       }
2242       break;
2243    case OBJ_XPM:
2244       index = QuickFindColorIndex(NULL, ObjPtr->color_str,
2245             &new_alloc, TRUE);
2246       if (index != ObjPtr->color) picture_changed = TRUE;
2247       if (index == INVALID) {
2248          sprintf(gszMsgBox,
2249                TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2250                ObjPtr->color_str, colorMenuItems[colorIndex]);
2251          Msg(gszMsgBox);
2252          allocColorFailed = TRUE;
2253          ObjPtr->color = colorIndex;
2254       } else {
2255          ObjPtr->color = index;
2256       }
2257       if (mainDisplay != NULL) {
2258          UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2259                colorMenuItems[ObjPtr->color]);
2260       }
2261       changed = FALSE;
2262       xpm_ptr = ObjPtr->detail.xpm;
2263       ncolors = xpm_ptr->ncolors;
2264       from_pixels = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
2265       to_pixels = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
2266       if (from_pixels == NULL || to_pixels == NULL) FailAllocMessage();
2267       for (i=0; i < ncolors; i++) {
2268          from_pixels[i] = xpm_ptr->pixels[i];
2269          if (xpm_ptr->pixels[i] == (-1)) {
2270             /* transparent pixel */
2271          } else {
2272             index = QuickFindColorIndex(NULL, xpm_ptr->color_str[i],
2273                   &new_alloc, TRUE);
2274             if (index == INVALID) {
2275                sprintf(gszMsgBox,
2276                      TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2277                      xpm_ptr->color_str[i], colorMenuItems[colorIndex]);
2278                Msg(gszMsgBox);
2279                allocColorFailed = TRUE;
2280 
2281                len = strlen(colorMenuItems[colorIndex]);
2282                free(xpm_ptr->color_str[i]);
2283                xpm_ptr->color_str[i] = (char*)malloc((len+1)*sizeof(char));
2284                if (xpm_ptr->color_str[i] == NULL) FailAllocMessage();
2285                strcpy(xpm_ptr->color_str[i], colorMenuItems[colorIndex]);
2286 
2287                xpm_ptr->pixels[i] = colorPixels[colorIndex];
2288             } else {
2289                if (xpm_ptr->pixels[i] != colorPixels[index]) {
2290                   changed = TRUE;
2291                }
2292                xpm_ptr->pixels[i] = colorPixels[index];
2293             }
2294          }
2295          to_pixels[i] = xpm_ptr->pixels[i];
2296       }
2297       if (changed) {
2298          int image_w=xpm_ptr->image_w, image_h=xpm_ptr->image_h;
2299          XImage *image=xpm_ptr->image;
2300          Pixmap pixmap=xpm_ptr->pixmap;
2301 
2302          if (xpm_ptr->cached_pixmap != None) {
2303             XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
2304          }
2305          xpm_ptr->cached_pixmap = None;
2306          if (xpm_ptr->cached_bitmap != None) {
2307             XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
2308          }
2309          xpm_ptr->cached_bitmap = None;
2310          xpm_ptr->cached_color = (-1);
2311          xpm_ptr->cached_zoom = 0;
2312 
2313          sprintf(gszMsgBox, TgLoadCachedString(CSTID_UPDATING_PIXELS),
2314                ++gnUpdatePixelObjCount, image_w, image_h);
2315          SetStringStatus(gszMsgBox);
2316          XSync(mainDisplay, False);
2317          for (r=0; r<image_h; r++) {
2318             for (c=0; c<image_w; c++) {
2319                pixel = XGetPixel(image, c, r);
2320                for (i=0; i < ncolors; i++) {
2321                   if (from_pixels[i] == pixel) {
2322                      XPutPixel(image, c, r, to_pixels[i]);
2323                      break;
2324                   }
2325                }
2326             }
2327          }
2328          XPutImage(mainDisplay,pixmap,xpmGC,image,0,0,0,0,image_w,image_h);
2329          picture_changed = TRUE;
2330       }
2331       free(from_pixels);
2332       free(to_pixels);
2333       break;
2334    default:
2335       index = QuickFindColorIndex(NULL, ObjPtr->color_str,
2336             &new_alloc, TRUE);
2337       if (index != ObjPtr->color) picture_changed = TRUE;
2338       if (index == INVALID) {
2339          sprintf(gszMsgBox,
2340                TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2341                ObjPtr->color_str, colorMenuItems[colorIndex]);
2342          Msg(gszMsgBox);
2343          allocColorFailed = TRUE;
2344          ObjPtr->color = colorIndex;
2345       } else {
2346          ObjPtr->color = index;
2347       }
2348       if (mainDisplay != NULL) {
2349          UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2350                colorMenuItems[ObjPtr->color]);
2351       }
2352       if (ObjPtr->type == OBJ_TEXT) {
2353          UpdatePixelInfo upi;
2354 
2355          memset(&upi, 0, sizeof(UpdatePixelInfo));
2356          upi.picture_changed = FALSE;
2357          DoFuncOnStrSegForMiniLines(&ObjPtr->detail.t->minilines,
2358                UpdatePixelForStrSeg, &upi);
2359          if (upi.picture_changed) {
2360             picture_changed = TRUE;
2361          }
2362       }
2363       break;
2364    }
2365    for (attr_ptr=ObjPtr->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
2366       if (UpdatePixel(attr_ptr->obj)) {
2367          picture_changed = TRUE;
2368       }
2369    }
2370    return picture_changed;
2371 }
2372 
UpdateXPmObjects(ObjPtr)2373 void UpdateXPmObjects(ObjPtr)
2374    struct ObjRec *ObjPtr;
2375 {
2376    struct ObjRec *obj_ptr;
2377    struct XPmRec *xpm_ptr;
2378 
2379    switch (ObjPtr->type) {
2380    case OBJ_GROUP:
2381    case OBJ_SYM:
2382    case OBJ_ICON:
2383    case OBJ_PIN:
2384       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr!=NULL;
2385             obj_ptr=obj_ptr->prev) {
2386          UpdateXPmObjects(obj_ptr);
2387       }
2388       break;
2389    case OBJ_XPM:
2390       xpm_ptr = ObjPtr->detail.xpm;
2391       if (xpm_ptr->image == NULL) {
2392          xpm_ptr->image = XGetImage(mainDisplay, xpm_ptr->pixmap, 0, 0,
2393                xpm_ptr->image_w, xpm_ptr->image_h, AllPlanes, ZPixmap);
2394       }
2395       break;
2396    }
2397 }
2398 
FlushColormap()2399 int FlushColormap()
2400 {
2401    int changed=FALSE;
2402    struct ObjRec *obj_ptr=NULL;
2403 
2404 #ifdef DONT_FREE_COLORMAP
2405    Msg(TgLoadString(STID_COLORMAP_NOT_RESETED));
2406    return FALSE;
2407 #endif
2408    if (!newColormapUsed) {
2409       Colormap colormap=XCopyColormapAndFree(mainDisplay, mainColormap);
2410 
2411       mainColormap = colormap;
2412       newColormapUsed = TRUE;
2413       XSetWindowColormap(mainDisplay, mainWindow, mainColormap);
2414    }
2415    if (newColormapUsed) {
2416       struct PageRec *page_ptr=NULL;
2417       int saved_color_layers=FALSE;
2418       struct AttrRec *attr_ptr=NULL;
2419 
2420       for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
2421          for (obj_ptr=page_ptr->bot; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
2422             UpdateXPmObjects(obj_ptr);
2423          }
2424       }
2425       initColorDontReload = TRUE;
2426       CleanUpColors();
2427       XFreeColormap(mainDisplay, mainColormap);
2428       mainColormap = DefaultColormap(mainDisplay, mainScreen);
2429       XSetWindowColormap(mainDisplay, mainWindow, mainColormap);
2430       newColormapUsed = FALSE;
2431 
2432       saved_color_layers = colorLayers;
2433       InitColor();
2434       initColorDontReload = FALSE;
2435       colorLayers = saved_color_layers;
2436 
2437       DoSetDefaultBgColor();
2438 
2439       ShowColor(TRUE);
2440       if (myFileBgColorStr != NULL) {
2441          int saved_my_file_bg_pixel=myFileBgPixel;
2442          int saved_my_file_fg_pixel=myFileFgPixel;
2443          int ok=TRUE;
2444 
2445          if (myFileFgColorStr != NULL && !SetFileFgColor()) {
2446             if (SetFileFgColor()) {
2447                if (saved_my_file_fg_pixel != myFileFgPixel) {
2448                   changed = TRUE;
2449                }
2450             } else {
2451                ok = FALSE;
2452             }
2453          }
2454          if (ok) {
2455             if (SetFileBgColor()) {
2456                if (saved_my_file_bg_pixel != myFileBgPixel) {
2457                   changed = TRUE;
2458                }
2459             } else {
2460                ok = FALSE;
2461             }
2462          }
2463          if (!ok) {
2464             ClearBgColorInfo(FALSE);
2465             changed = TRUE;
2466          }
2467       }
2468       DoSetAltEditTextBgColor();
2469       DoSetAltEditTextHighlightColor();
2470 
2471       RecalcXorPixels();
2472 
2473       SaveStatusStrings();
2474       gnUpdatePixelObjCount = 0;
2475       for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
2476          for (obj_ptr=page_ptr->bot; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
2477             if (UpdatePixel(obj_ptr)) {
2478                changed = TRUE;
2479             }
2480          }
2481       }
2482       if (tgifObj->fattr != NULL) {
2483          for (attr_ptr=tgifObj->fattr; attr_ptr != NULL;
2484                attr_ptr=attr_ptr->next) {
2485             if (UpdatePixel(attr_ptr->obj)) {
2486                changed = TRUE;
2487             }
2488          }
2489       }
2490       RestoreStatusStrings();
2491 
2492       DestroyPinnedMenu(MENU_COLOR);
2493       if (colorLayers) {
2494          colorWindowFirstIndex = 0;
2495          RedrawColorWindow();
2496       }
2497       if (changed) ClearAndRedrawDrawWindow();
2498       return TRUE;
2499    }
2500    return FALSE;
2501 }
2502 
AddColor()2503 void AddColor()
2504 {
2505    char spec[MAXSTRING+1], *c_ptr=NULL;
2506 
2507    if (!colorDisplay) {
2508       MsgBox(TgLoadString(STID_ADDCOLOR_FOR_BW_DPY), TOOL_NAME, INFO_MB);
2509       return;
2510    }
2511    *spec = '\0';
2512    if (Dialog(TgLoadString(STID_ENTER_COLORS_TO_ADD), NULL, spec) == INVALID) {
2513       return;
2514    }
2515    UtilTrimBlanks(spec);
2516    if (*spec == '\0') return;
2517    for (c_ptr=strtok(spec, ", \t\n\r"); c_ptr != NULL && *c_ptr != '\0';
2518          c_ptr=strtok(NULL, ", \t\n\r")) {
2519       int new_alloc;
2520       int index=QuickFindColorIndex(NULL, c_ptr, &new_alloc, FALSE);
2521 
2522       if (index == INVALID) {
2523          sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR), c_ptr);
2524          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2525          return;
2526       } else {
2527          ChangeAllSelColor(index, FALSE);
2528       }
2529    }
2530 }
2531 
ChooseColor()2532 void ChooseColor()
2533 {
2534    TgColorWheel_HandleCntrlSpace(mainDisplay, drawWindow);
2535 }
2536 
SetAltEditTextBgColor()2537 void SetAltEditTextBgColor()
2538 {
2539    char spec[MAXSTRING+1];
2540 
2541    *spec = '\0';
2542    sprintf(gszMsgBox, TgLoadString(STID_ENTER_EDIT_BG_COLOR),
2543          (altEditTextBgIndex==INVALID ?
2544          (useAltEditTextBgColor ? myFgColorStr : myBgColorStr) :
2545          altEditTextBgColorStr));
2546    if (Dialog(gszMsgBox, NULL, spec) == INVALID) return;
2547    UtilTrimBlanks(spec);
2548    if (*spec == '\0') return;
2549 
2550    if (UtilStrICmp(spec, TgLoadCachedString(CSTID_NONE)) == 0) {
2551       *altEditTextBgColorStr = '\0';
2552       altEditTextBgIndex = INVALID;
2553       if (curChoice == DRAWTEXT && textCursorShown) {
2554          RedrawCurText();
2555       }
2556       return;
2557    }
2558    UtilStrCpyN(altEditTextBgColorStr, sizeof(altEditTextBgColorStr), spec);
2559    if (DoSetAltEditTextBgColor()) {
2560       if (curChoice == DRAWTEXT && textCursorShown) {
2561          if (!useAltEditTextBgColor) {
2562             useAltEditTextBgColor = TRUE;
2563             UpdatePinnedMenu(MENU_PROPERTIES);
2564          }
2565          RedrawCurText();
2566       }
2567    }
2568 }
2569 
SetAltEditTextHighlightColor()2570 void SetAltEditTextHighlightColor()
2571 {
2572    char spec[MAXSTRING+1];
2573 
2574    *spec = '\0';
2575    sprintf(gszMsgBox, TgLoadString(STID_ENTER_EDIT_HILIGHT_COLOR),
2576          (altEditTextHighlightIndex==INVALID ?
2577          (useAltEditTextBgColor ? myBgColorStr : myFgColorStr) :
2578          altEditTextHighlightColorStr));
2579    if (Dialog(gszMsgBox, NULL, spec) == INVALID) return;
2580    UtilTrimBlanks(spec);
2581    if (*spec == '\0') return;
2582 
2583    if (UtilStrICmp(spec, TgLoadCachedString(CSTID_NONE)) == 0) {
2584       *altEditTextHighlightColorStr = '\0';
2585       altEditTextHighlightIndex = INVALID;
2586       if (curChoice == DRAWTEXT && textCursorShown) {
2587          RedrawCurText();
2588       }
2589       return;
2590    }
2591    UtilStrCpyN(altEditTextHighlightColorStr,
2592          sizeof(altEditTextHighlightColorStr), spec);
2593    if (DoSetAltEditTextHighlightColor()) {
2594       RedrawCurText();
2595    }
2596 }
2597 
ToggleAltEditTextBgColor()2598 void ToggleAltEditTextBgColor()
2599 {
2600    useAltEditTextBgColor = (!useAltEditTextBgColor);
2601    RedrawCurText();
2602    UpdatePinnedMenu(MENU_PROPERTIES);
2603 }
2604 
SaveColors(FP)2605 void SaveColors(FP)
2606    FILE *FP;
2607 {
2608    int i;
2609 
2610    if (fprintf(FP, "color_info(%1d,%1d,%1d,[\n", maxColors, maxRGB,
2611          colorLayers) == EOF) {
2612       writeFileFailed = TRUE;
2613    }
2614    for (i=0; i < maxColors; i++) {
2615       if (i == maxColors-1) {
2616          if (fprintf(FP, "\t\"%s\", %1d, %1d, %1d, %1d, %1d, %1d, %1d\n",
2617                colorMenuItems[i],
2618                (int)(tgifColors[i].red), (int)(tgifColors[i].green),
2619                (int)(tgifColors[i].blue), (int)(tgifRequestedColors[i].red),
2620                (int)(tgifRequestedColors[i].green),
2621                (int)(tgifRequestedColors[i].blue),
2622                colorLayerOn==NULL ? 1 : colorLayerOn[i]) == EOF) {
2623             writeFileFailed = TRUE;
2624          }
2625       } else {
2626          if (fprintf(FP, "\t\"%s\", %1d, %1d, %1d, %1d, %1d, %1d, %1d,\n",
2627                colorMenuItems[i],
2628                (int)(tgifColors[i].red), (int)(tgifColors[i].green),
2629                (int)(tgifColors[i].blue), (int)(tgifRequestedColors[i].red),
2630                (int)(tgifRequestedColors[i].green),
2631                (int)(tgifRequestedColors[i].blue),
2632                colorLayerOn==NULL ? 1 : colorLayerOn[i]) == EOF) {
2633             writeFileFailed = TRUE;
2634          }
2635       }
2636    }
2637    if (fprintf(FP, "]).\n") == EOF) {
2638       writeFileFailed = TRUE;
2639    }
2640 }
2641 
ReadColors(FP,Inbuf)2642 int ReadColors(FP, Inbuf)
2643    FILE *FP;
2644    char *Inbuf;
2645 {
2646    char *c_ptr, *line;
2647    int index=0, max_colors=0, max_rgb=0, color_layers=FALSE;
2648 
2649    c_ptr = FindChar((int)'(', Inbuf);
2650    InitScan(c_ptr, "\t\n, ");
2651    if (GETINT("color_info", max_colors,   "maxColors") == INVALID ||
2652        GETINT("color_info", max_rgb,      "maxRGB") == INVALID ||
2653        GETINT("color_info", color_layers, "colorLayers") == INVALID) {
2654       return FALSE;
2655    }
2656    if (PRTGIF && !cmdLineOpenDisplay && cmdLineColor) {
2657       CleanUpColors();
2658       maxColors = max_colors;
2659       maxRGB = max_rgb;
2660       /* colorLayers = color_layers; */
2661       colorMenuItems = (char**)malloc(maxColors*sizeof(char*));
2662       tgifColors = (XColor*)malloc(maxColors*sizeof(XColor));
2663       if (colorMenuItems == NULL || tgifColors == NULL) FailAllocMessage();
2664       memset(colorMenuItems, 0, maxColors*sizeof(char*));
2665       memset(tgifColors, 0, maxColors*sizeof(XColor));
2666       for (index=0; index < maxColors; index++) {
2667          colorMenuItems[index] = (char*)malloc(COLORSTRLEN*sizeof(char));
2668          if (colorMenuItems[index] == NULL) FailAllocMessage();
2669          *colorMenuItems[index] = '\0';
2670       }
2671    }
2672    if (colorDisplay && (!(PRTGIF && !cmdLineOpenDisplay)) && !importingFile) {
2673       int saved_color_layers=colorLayers;
2674 
2675       colorLayers = color_layers;
2676       if (colorLayers != saved_color_layers) {
2677          if (colorLayers) {
2678             XMapWindow(mainDisplay, colorWindow);
2679             XMapWindow(mainDisplay, colorDummyWindow);
2680             Msg(TgLoadString(STID_COLOR_LAYERS_ENABLED));
2681          } else {
2682             XUnmapWindow(mainDisplay, colorWindow);
2683             XUnmapWindow(mainDisplay, colorDummyWindow);
2684             Msg(TgLoadString(STID_COLOR_LAYERS_DISABLED));
2685          }
2686          Reconfigure(TRUE);
2687       }
2688    }
2689    index = 0;
2690    while ((line=UtilGetALine(FP)) != NULL) {
2691       char color_s[40];
2692       int red=0, green=0, blue=0;
2693       int requested_red=0, requested_green=0, requested_blue=0, layer_on=FALSE;
2694 
2695       scanLineNum++;
2696       if (*line == ']') {
2697          free(line);
2698          break;
2699       }
2700       if (PRTGIF && !cmdLineOpenDisplay && cmdLineColor && index >= maxColors) {
2701          fprintf(stderr, "%s\n",
2702                TgLoadString(STID_TOO_MANY_LINES_IN_COLORINFO));
2703          free(line);
2704          break;
2705       }
2706       c_ptr = FindChar((int)'"', line);
2707       c_ptr = ParseStr(c_ptr, (int)'"', color_s, sizeof(color_s));
2708       InitScan(c_ptr, "\t\n, ");
2709       if (GETINT("color_info", red,             "red") == INVALID ||
2710           GETINT("color_info", green,           "green") == INVALID ||
2711           GETINT("color_info", blue,            "blue") == INVALID ||
2712           GETINT("color_info", requested_red,   "requested_red") == INVALID ||
2713           GETINT("color_info", requested_green, "requested_green") == INVALID ||
2714           GETINT("color_info", requested_blue,  "requested_blue") == INVALID ||
2715           GETINT("color_info", layer_on,        "layer_on") == INVALID) {
2716          return FALSE;
2717       }
2718       if (PRTGIF && !cmdLineOpenDisplay && cmdLineColor) {
2719          UtilStrCpyN(colorMenuItems[index], COLORSTRLEN*sizeof(char), color_s);
2720          if (cmdLineRequestedColor) {
2721             tgifColors[index].red = red;
2722             tgifColors[index].green = green;
2723             tgifColors[index].blue = blue;
2724          } else {
2725             tgifColors[index].red = requested_red;
2726             tgifColors[index].green = requested_green;
2727             tgifColors[index].blue = requested_blue;
2728          }
2729          index++;
2730       }
2731       if ((!(PRTGIF && !cmdLineOpenDisplay)) && !importingFile) {
2732          int new_alloc=FALSE;
2733          int cur_index=QuickFindColorIndex(NULL, color_s, &new_alloc, TRUE);
2734 
2735          if (cur_index != INVALID && cur_index < maxColors &&
2736                colorLayerOn != NULL) {
2737             colorLayerOn[cur_index] = layer_on;
2738          }
2739       }
2740       free(line);
2741    }
2742    prTgifFoundColorInfo = TRUE;
2743    return TRUE;
2744 }
2745 
DumpRGBColorLine(FP,ColorIndex,Indent,EndOfLine)2746 void DumpRGBColorLine(FP, ColorIndex, Indent, EndOfLine)
2747    FILE *FP;
2748    int ColorIndex, Indent, EndOfLine;
2749 {
2750    register int i;
2751 
2752    if (colorDump) {
2753       for (i=0; i < Indent; i++) fprintf(FP, " ");
2754       if (tgifColors[ColorIndex].red == 0 &&
2755             tgifColors[ColorIndex].green == 0 &&
2756             tgifColors[ColorIndex].blue == 0) {
2757          fprintf(FP, "0 %s", gPsCmd[PS_SETGRAY]);
2758       } else if (tgifColors[ColorIndex].red == maxRGB &&
2759             tgifColors[ColorIndex].green == maxRGB &&
2760             tgifColors[ColorIndex].blue == maxRGB) {
2761          fprintf(FP, "1 %s", gPsCmd[PS_SETGRAY]);
2762       } else {
2763          fprintf(FP, "%.3f %.3f %.3f %s",
2764                ((float)tgifColors[ColorIndex].red/maxRGB),
2765                ((float)tgifColors[ColorIndex].green/maxRGB),
2766                ((float)tgifColors[ColorIndex].blue/maxRGB),
2767                gPsCmd[PS_SETRGBCOLOR]);
2768       }
2769       fprintf(FP, "%c", EndOfLine ? '\n' : ' ');
2770    } else {
2771       for (i=0; i < Indent; i++) fprintf(FP, " ");
2772       fprintf(FP, "0 %s\n", gPsCmd[PS_SETGRAY]);
2773    }
2774 }
2775 
2776