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/xpixmap.c,v 1.89 2011/05/16 16:22:00 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_XPIXMAP_C_
22 
23 #include "tgifdefs.h"
24 
25 #include "attr.e"
26 #include "auxtext.e"
27 #include "choice.e"
28 #include "cmd.e"
29 #include "color.e"
30 #include "cursor.e"
31 #include "cutpaste.e"
32 #include "dialog.e"
33 #include "drawing.e"
34 #include "dup.e"
35 #include "file.e"
36 #include "font.e"
37 #include "grid.e"
38 #include "hash.e"
39 #include "http.e"
40 #include "imgproc.e"
41 #include "import.e"
42 #include "mainloop.e"
43 #include "mainmenu.e"
44 #include "mark.e"
45 #include "move.e"
46 #include "msg.e"
47 #include "names.e"
48 #include "obj.e"
49 #include "page.e"
50 #include "pattern.e"
51 #include "pngtrans.e"
52 #include "ps.e"
53 #include "raster.e"
54 #include "rect.e"
55 #include "select.e"
56 #include "setup.e"
57 #include "stretch.e"
58 #include "strtbl.e"
59 #include "util.e"
60 #include "xbitmap.e"
61 #include "xpixmap.e"
62 #include "z_intrf.e"
63 
64 struct BucketRec {
65    int pixel, index, color_index;
66    char s[40];
67 };
68 
69 #define XPM_BUCKETS 67
70 #define XPM_BUCKET_INC 10
71 
72 #define TYPE_PPM3 3
73 #define TYPE_PPM5 5
74 #define TYPE_PPM6 6
75 
76 GC xpmGC=NULL;
77 
78 int newColormapUsed=FALSE;
79 int allocColorFailed=FALSE;
80 int myReadTransparentPixmap=FALSE;
81 
82 int xpmIsArray=FALSE;
83 long xpmArraySeek=(-1L);
84 
85 int xpmHasTooManyColorsForPrinting=FALSE;
86 
87 int hasReadHexString=FALSE;
88 
89 PngHeaderInfo gPngHeaderInfo;
90 
91 double rotatedSine[4]={ 0.0, 1.0, 0.0, -1.0 };
92 double rotatedCosine[4]={ 1.0, 0.0, -1.0, 0.0 };
93 
94 static Pixmap dummyPixmap=None;
95 
96 /* do not translate -- program constants */
97 static char hexValue[]="0123456789abcdef";
98 
99 static int askForXPmSpec=FALSE;
100 static int guessXPmBgColor=FALSE;
101 static int littleEndianPpm6=FALSE;
102 
103 static struct BucketRec **xpmBucket=NULL;
104 static int *xpmBucketSize=NULL;
105 static int *xpmBucketMaxSize=NULL;
106 
107 static int shownXPmErrorMessage=FALSE;
108 
109 static TgHash gColorsHashForPrinting;
110 static int gnColorsHashForPrintingValid=FALSE;
111 
ResetXPmErrorMessage()112 void ResetXPmErrorMessage()
113 {
114    shownXPmErrorMessage = FALSE;
115 }
116 
InitXPm()117 void InitXPm()
118 {
119    register int i;
120    XGCValues values;
121    char *c_ptr;
122 
123    dummyPixmap = XCreatePixmap(mainDisplay, mainWindow, 1, 1, mainDepth);
124 
125    values.foreground = myFgPixel;
126    values.background = myBgPixel;
127    values.function = GXcopy;
128    values.fill_style = FillSolid;
129    xpmGC = XCreateGC(mainDisplay, dummyPixmap,
130          GCForeground | GCBackground | GCFunction | GCFillStyle, &values);
131 
132    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AskForXPmSpec")) != NULL) {
133       if (UtilStrICmp(c_ptr, "true") == 0) {
134          askForXPmSpec = TRUE;
135       } else {
136          askForXPmSpec = FALSE;
137       }
138    }
139    guessXPmBgColor = FALSE;
140    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GuessXPmBgColor"))!=NULL) {
141       if (UtilStrICmp(c_ptr, "true") == 0) {
142          guessXPmBgColor = TRUE;
143       }
144    }
145    littleEndianPpm6 = FALSE;
146    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"LittleEndianPpm6"))!=NULL) {
147       if (UtilStrICmp(c_ptr, "true") == 0) {
148          littleEndianPpm6 = TRUE;
149       }
150    }
151    newColormapUsed = FALSE;
152 
153    xpmBucket =
154          (struct BucketRec **)malloc(XPM_BUCKETS*sizeof(struct BucketRec *));
155    xpmBucketSize = (int*)malloc((XPM_BUCKETS+1)*sizeof(int));
156    xpmBucketMaxSize = (int*)malloc(XPM_BUCKETS*sizeof(int));
157    if (xpmBucket == NULL || xpmBucketSize == NULL || xpmBucketMaxSize == NULL) {
158       FailAllocMessage();
159    }
160    for (i=0; i < XPM_BUCKETS; i++) {
161       xpmBucket[i] =
162             (struct BucketRec *)malloc(XPM_BUCKET_INC*sizeof(struct BucketRec));
163       if (xpmBucket[i] == NULL) FailAllocMessage();
164       xpmBucketSize[i] = 0;
165       xpmBucketMaxSize[i] = XPM_BUCKET_INC;
166    }
167    xpmBucketSize[XPM_BUCKETS] = INVALID;
168 
169    memset(&gPngHeaderInfo, 0, sizeof(PngHeaderInfo));
170 }
171 
CleanUpXPm()172 void CleanUpXPm()
173 {
174    register int i;
175 
176    if (xpmGC != NULL) XFreeGC(mainDisplay, xpmGC);
177    XFreePixmap(mainDisplay, dummyPixmap);
178 
179    askForXPmSpec = FALSE;
180    for (i = 0; i < XPM_BUCKETS; i++) free(xpmBucket[i]);
181    free(xpmBucket);
182    free(xpmBucketSize);
183    free(xpmBucketMaxSize);
184    xpmBucket = NULL;
185    xpmBucketSize = xpmBucketMaxSize = NULL;
186 }
187 
IsLinkedJpegObj(obj_ptr)188 int IsLinkedJpegObj(obj_ptr)
189    struct ObjRec *obj_ptr;
190 {
191    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
192    int real_type=xpm_ptr->real_type, linked_jpeg=xpm_ptr->linked_jpeg;
193    char *jpeg_filename=xpm_ptr->filename;
194 
195    /* if the object is a linked JPEG file, will not perform imageproc */
196    return (real_type == XPM_JPEG && linked_jpeg && jpeg_filename != NULL);
197 }
198 
IsPpmTrueObj(real_type,ppm_data_compress,ppm_data)199 int IsPpmTrueObj(real_type, ppm_data_compress, ppm_data)
200    int real_type, ppm_data_compress;
201    char *ppm_data;
202 {
203    return (real_type == PPM_TRUE &&
204          (ppm_data_compress == PPM_JPEG_COMPRESS ||
205          ppm_data_compress == PPM_DATA_DEFLATED) && ppm_data != NULL);
206 }
207 
ObjHasIndexedTransPixel(obj_ptr,pn_index)208 int ObjHasIndexedTransPixel(obj_ptr, pn_index)
209    struct ObjRec *obj_ptr;
210    int *pn_index;
211 {
212    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
213    int i=0, ncolors=xpm_ptr->ncolors, *pixels=xpm_ptr->pixels;
214 
215    switch (xpm_ptr->real_type) {
216    case XPM_XPM:
217       for (i=0; i < ncolors; i++) {
218          if (pixels[i] == (-1)) {
219             if (pn_index != NULL) *pn_index = i;
220             return TRUE;
221          }
222       }
223       break;
224    case XPM_JPEG: break;
225    case PPM_TRUE: break;
226    }
227    return FALSE;
228 }
229 
ObjHasTrueColorTransPixel(obj_ptr,puch_trans_color_r,puch_trans_color_g,puch_trans_color_b)230 int ObjHasTrueColorTransPixel(obj_ptr, puch_trans_color_r, puch_trans_color_g,
231       puch_trans_color_b)
232    struct ObjRec *obj_ptr;
233    unsigned char *puch_trans_color_r, *puch_trans_color_g, *puch_trans_color_b;
234 {
235    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
236 
237    switch (xpm_ptr->real_type) {
238    case XPM_XPM: break;
239    case XPM_JPEG: break;
240    case PPM_TRUE:
241       if (((PRTGIF && !cmdLineOpenDisplay) || fullTrueColorMode) && xpm_ptr->has_transparent_color) {
242          if (puch_trans_color_r != NULL) *puch_trans_color_r = xpm_ptr->transparent_color[0];
243          if (puch_trans_color_g != NULL) *puch_trans_color_g = xpm_ptr->transparent_color[1];
244          if (puch_trans_color_b != NULL) *puch_trans_color_b = xpm_ptr->transparent_color[2];
245          return TRUE;
246       }
247       break;
248    }
249    return FALSE;
250 }
251 
ObjHasTransPixel(obj_ptr)252 int ObjHasTransPixel(obj_ptr)
253    struct ObjRec *obj_ptr;
254 {
255    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
256 
257    switch (xpm_ptr->real_type) {
258    case XPM_XPM: return ObjHasIndexedTransPixel(obj_ptr, NULL);
259    case XPM_JPEG: break;
260    case PPM_TRUE: return ObjHasTrueColorTransPixel(obj_ptr, NULL, NULL, NULL);
261    }
262    return FALSE;
263 }
264 
265 #define xpmpixelhash(X) (((X)==(-1)) ? (XPM_BUCKETS-1) : ((X)%XPM_BUCKETS))
266 
267 static
xpmcharhash(chars_per_pixel,color_char)268 int xpmcharhash(chars_per_pixel, color_char)
269    int chars_per_pixel;
270    char *color_char;
271 {
272    register int i, val=0;
273 
274    for (i = 0; i < chars_per_pixel; i++) val = (val<<1)+(int)(color_char[i]);
275    return (xpmpixelhash(val));
276 }
277 
BuildXPmBuckets(ncolors,pixels,dump_index_to_color_index,chars_per_pixel,color_char,pxtii)278 int BuildXPmBuckets(ncolors, pixels, dump_index_to_color_index, chars_per_pixel,
279       color_char, pxtii)
280    int ncolors, *pixels, *dump_index_to_color_index, chars_per_pixel;
281    char *color_char;
282    XpmTransIndexInfo *pxtii;
283 {
284    register int *ptr=NULL, i;
285    int bucket=0;
286 
287    if (xpmBucketSize == NULL) {
288       xpmBucket =
289             (struct BucketRec **)malloc(XPM_BUCKETS*sizeof(struct BucketRec *));
290       xpmBucketSize = (int*)malloc((XPM_BUCKETS+1)*sizeof(int));
291       xpmBucketMaxSize = (int*)malloc(XPM_BUCKETS*sizeof(int));
292       if (xpmBucket==NULL || xpmBucketSize==NULL || xpmBucketMaxSize==NULL) {
293          FailAllocMessage();
294       }
295       for (i=0; i < XPM_BUCKETS; i++) {
296          xpmBucket[i] = (struct BucketRec *)malloc(
297                XPM_BUCKET_INC*sizeof(struct BucketRec));
298          if (xpmBucket[i] == NULL) FailAllocMessage();
299          xpmBucketSize[i] = 0;
300          xpmBucketMaxSize[i] = XPM_BUCKET_INC;
301       }
302       xpmBucketSize[XPM_BUCKETS] = INVALID;
303    }
304 
305    for (ptr = xpmBucketSize; *ptr != INVALID; ptr++) *ptr = 0;
306 
307    if (chars_per_pixel == INVALID) {
308       /* build the hash table according to the pixels */
309       for (i=0; i < ncolors; i++) {
310          if (pxtii != NULL) {
311             if (pxtii->has_transparent_pixel && pixels[i] == INVALID) {
312 #ifdef _TGIF_DBG /* debug, do not translate */
313                TgAssert(pxtii->found_transparent_pixel == FALSE ||
314                      pxtii->transparent_pixel_index == i,
315                      "more than one transparent pixel in BuildXPmBuckets()",
316                      NULL);
317 #endif /* _TGIF_DBG */
318                pxtii->found_transparent_pixel = TRUE;
319                pxtii->transparent_pixel_index = i;
320                if (pxtii->dump_index_to_color_index != NULL) {
321                   pxtii->dump_index_to_color_index[i] = INVALID;
322                }
323             } else if (pxtii->dump_index_to_color_index != NULL) {
324                int pixel=pixels[i], found_index=INVALID;
325 
326                if (HashLookUpInt(&gColorsHashForPrinting,
327                      (char*)(&pixel), sizeof(int), &found_index)) {
328                   pxtii->dump_index_to_color_index[i] = found_index;
329                } else {
330                   pxtii->dump_index_to_color_index[i] = INVALID;
331 #ifdef _TGIF_DBG /* debug, do not translate */
332                   TgAssert(FALSE,
333                         "invalid found_index in BuildXPmBuckets()", NULL);
334 #endif /* _TGIF_DBG */
335                }
336             }
337          }
338          bucket = xpmpixelhash(pixels[i]);
339          if (xpmBucketSize[bucket] == xpmBucketMaxSize[bucket]) {
340             xpmBucket[bucket] = (struct BucketRec *)realloc(xpmBucket[bucket],
341                   (xpmBucketMaxSize[bucket]+XPM_BUCKET_INC) *
342                   sizeof(struct BucketRec));
343             xpmBucketMaxSize[bucket] += XPM_BUCKET_INC;
344          }
345          xpmBucket[bucket][xpmBucketSize[bucket]].index = i;
346          xpmBucket[bucket][xpmBucketSize[bucket]].pixel = pixels[i];
347          if (dump_index_to_color_index == NULL) {
348             xpmBucket[bucket][xpmBucketSize[bucket]].color_index = BAD;
349          } else {
350             xpmBucket[bucket][xpmBucketSize[bucket]].color_index =
351                   dump_index_to_color_index[i];
352          }
353          (xpmBucketSize[bucket])++;
354       }
355    } else {
356       /* build the hash table according to the color_char */
357       if (chars_per_pixel >= 9) {
358          sprintf(gszMsgBox, TgLoadString(STID_INVALID_CH_PER_PIX_IN_FUNC),
359                chars_per_pixel, "BuildXPmBuckets()");
360          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
361          return FALSE;
362       }
363       for (i=0; i < ncolors; i++) {
364          bucket = xpmcharhash(chars_per_pixel, &color_char[i*chars_per_pixel]);
365          if (xpmBucketSize[bucket] == xpmBucketMaxSize[bucket]) {
366             xpmBucket[bucket] = (struct BucketRec *)realloc(xpmBucket[bucket],
367                   (xpmBucketMaxSize[bucket]+XPM_BUCKET_INC) *
368                   sizeof(struct BucketRec));
369             xpmBucketMaxSize[bucket] += XPM_BUCKET_INC;
370          }
371          xpmBucket[bucket][xpmBucketSize[bucket]].index = i;
372          strncpy(xpmBucket[bucket][xpmBucketSize[bucket]].s,
373                &color_char[i*chars_per_pixel], chars_per_pixel);
374          (xpmBucketSize[bucket])++;
375       }
376    }
377    return TRUE;
378 }
379 
XPmLookUp(pixel,chars_per_pixel,color_char,pn_color_index_return)380 int XPmLookUp(pixel, chars_per_pixel, color_char, pn_color_index_return)
381    int pixel, chars_per_pixel, *pn_color_index_return;
382    char *color_char;
383 {
384    register int i;
385    register struct BucketRec *ptr;
386    int size, bucket;
387 
388    if (chars_per_pixel == INVALID) {
389       /* hash according to the pixels */
390       bucket = xpmpixelhash(pixel);
391       size = xpmBucketSize[bucket];
392       for (i = 0, ptr = xpmBucket[bucket]; i < size; i++, ptr++) {
393          if (ptr->pixel == pixel) {
394             if (pn_color_index_return != NULL) {
395                *pn_color_index_return = ptr->color_index;
396             }
397             return (ptr->index);
398          }
399       }
400    } else {
401       /* hash according to the color_char */
402       bucket = xpmcharhash(chars_per_pixel, color_char);
403 
404       size = xpmBucketSize[bucket];
405       for (i=0, ptr=xpmBucket[bucket]; i < size; i++, ptr++) {
406          if (strncmp(color_char, ptr->s, chars_per_pixel) == 0) {
407             if (pn_color_index_return != NULL) {
408                *pn_color_index_return = ptr->color_index;
409             }
410             return (ptr->index);
411          }
412       }
413    }
414    return INVALID;
415 }
416 
MakeCachedPixmap(ObjPtr)417 void MakeCachedPixmap(ObjPtr)
418    struct ObjRec *ObjPtr;
419 {
420    register int c, r;
421    int w, h, flip, target_percent;
422    int num_cols, num_rows, image_w, image_h, watch_cursor;
423    int start_col, start_row, do_msg;
424    struct XPmRec *xpm_ptr=ObjPtr->detail.xpm;
425    struct MtrxRec mtrx;
426    Pixmap dest_pixmap=None, dest_bitmap=None;
427    XImage *src_image=NULL, *src_bitmap_image=NULL;
428    XImage *dest_image=NULL, *dest_bitmap_image=NULL;
429 
430    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
431    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
432    num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
433    num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
434 
435    if (ObjPtr->ctm==NULL && xpm_ptr->cached_pixmap!=None &&
436          xpm_ptr->cached_color!=(-1) && xpm_ptr->cached_color==ObjPtr->color &&
437          xpm_ptr->cached_zoomed==zoomedIn && xpm_ptr->cached_zoom==zoomScale &&
438          xpm_ptr->cached_w==num_cols && xpm_ptr->cached_h==num_rows &&
439          xpm_ptr->cached_flip==xpm_ptr->flip)
440       return;
441 
442    if ((w>>zoomScale)==0 || (h>>zoomScale)==0) {
443       if (xpm_ptr->cached_pixmap != None) {
444          XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
445       }
446       if (xpm_ptr->cached_bitmap != None) {
447          XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
448       }
449       xpm_ptr->cached_pixmap = None;
450       xpm_ptr->cached_bitmap = None;
451       xpm_ptr->cached_color = (-1);
452       return;
453    }
454    watch_cursor = watchCursorOnMainWindow;
455    if (!watch_cursor && !RedrawDuringScrolling()) {
456       SetWatchCursor(drawWindow);
457       SetWatchCursor(mainWindow);
458    } else {
459       CheckInterrupt(TRUE);
460    }
461    src_image = xpm_ptr->image;
462    src_bitmap_image = xpm_ptr->bitmap_image;
463    flip = xpm_ptr->flip;
464    image_w = xpm_ptr->image_w;
465    image_h = xpm_ptr->image_h;
466    if (xpm_ptr->cached_pixmap != None) {
467       XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
468    }
469    xpm_ptr->cached_pixmap = None;
470    if (xpm_ptr->cached_bitmap != None) {
471       XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
472    }
473    xpm_ptr->cached_bitmap = None;
474    xpm_ptr->cached_color = (-1);
475    if (xpm_ptr->clip_mask != None) {
476       XFreePixmap(mainDisplay, xpm_ptr->clip_mask);
477    }
478    xpm_ptr->clip_mask = None;
479 
480    if (src_image == NULL) {
481       src_image = xpm_ptr->image = XGetImage(mainDisplay, xpm_ptr->pixmap,
482             0, 0, image_w, image_h, AllPlanes, ZPixmap);
483    }
484    if (src_bitmap_image == NULL) {
485       src_bitmap_image = xpm_ptr->bitmap_image = XGetImage(mainDisplay,
486             xpm_ptr->bitmap, 0, 0, image_w, image_h, 1, ZPixmap);
487    }
488    do_msg = (((num_rows*num_cols)>=0x4000) && !RedrawDuringScrolling());
489    if (do_msg) {
490       SaveStatusStrings();
491       SetStringStatus(TgLoadCachedString(CSTID_CACHING_PIXMAP));
492       XSync(mainDisplay, False);
493    }
494    dest_pixmap = XCreatePixmap(mainDisplay, dummyPixmap, num_cols, num_rows,
495          mainDepth);
496    dest_bitmap = XCreatePixmap(mainDisplay, dummyBitmap, num_cols, num_rows,
497          1);
498    XFillRectangle(mainDisplay,dest_pixmap,xpmGC,0,0,num_cols,num_rows);
499    XSetForeground(mainDisplay,xbmGC,1);
500    XFillRectangle(mainDisplay,dest_bitmap,xbmGC,0,0,num_cols,num_rows);
501    XSetForeground(mainDisplay,xbmGC,0);
502    dest_image = XGetImage(mainDisplay, dest_pixmap, 0, 0, num_cols, num_rows,
503          AllPlanes, ZPixmap);
504    dest_bitmap_image = XGetImage(mainDisplay, dest_bitmap, 0, 0,
505          num_cols, num_rows, 1, ZPixmap);
506 
507    if (ObjPtr->ctm == NULL) {
508       mtrx.image_w = (float)image_w; mtrx.image_h = (float)image_h;
509       mtrx.w = (float)num_cols; mtrx.h = (float)num_rows;
510       mtrx.rotate = ROTATE0; mtrx.flip = flip;
511 
512       CalcTransform(&mtrx);
513 
514       start_col = (mtrx.transformed_w >= 0.0) ? 0 : (-num_cols)+1;
515       start_row = (mtrx.transformed_h >= 0.0) ? 0 : (-num_rows)+1;
516 
517       target_percent = 5;
518       for (r=0; r < num_rows; r++) {
519          double part_x, part_y;
520 
521          if (do_msg && ((r & 0xf) == 0)) {
522             int percent=(r*10000/num_rows)/100;
523 
524             if (percent >= target_percent) {
525                sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
526                      percent);
527                SetStringStatus(gszMsgBox);
528                XSync(mainDisplay, False);
529                while (target_percent <= percent) target_percent += 5;
530             }
531          }
532          part_x = ((double)(r+start_row)+0.5)*(mtrx.rev_m[1][0]);
533          part_y = ((double)(r+start_row)+0.5)*(mtrx.rev_m[1][1]);
534          for (c=0; c < num_cols; c++) {
535             double x, y;
536 
537             x = part_x+((double)(c+start_col)+0.5)*(mtrx.rev_m[0][0]);
538             y = part_y+((double)(c+start_col)+0.5)*(mtrx.rev_m[0][1]);
539             if (x >= ((double)0) && x < ((double)image_w) &&
540                   y >= ((double)0) && y < ((double)image_h)) {
541                int new_x=(int)x, new_y=(int)y;
542 
543                if (XGetPixel(src_bitmap_image,new_x,new_y) != 0) {
544                   XPutPixel(dest_image, c, r, XGetPixel(src_image,new_x,new_y));
545                } else {
546                   XPutPixel(dest_bitmap_image, c, r, 0);
547                   XPutPixel(dest_image, c, r, colorPixels[ObjPtr->color]);
548                }
549             }
550          }
551       }
552    } else {
553       Pixmap clip_mask;
554       XImage *clip_mask_image;
555       int bg_pixel=GetDrawingBgPixel(INVALID, INVALID);
556       int abs_offset_x=ObjPtr->obbox.ltx-ObjPtr->x;
557       int abs_offset_y=ObjPtr->obbox.lty-ObjPtr->y;
558 
559       clip_mask = XCreatePixmap(mainDisplay,dummyBitmap,num_cols,num_rows,1);
560       XSetForeground(mainDisplay, xbmGC, 1);
561       XFillRectangle(mainDisplay, clip_mask, xbmGC, 0, 0, num_cols, num_rows);
562       XSetForeground(mainDisplay, xbmGC, 0);
563       clip_mask_image = XGetImage(mainDisplay, clip_mask, 0, 0,
564             num_cols, num_rows, 1, ZPixmap);
565 
566       target_percent = 5;
567       for (r=0; r < num_rows; r++) {
568          int y=abs_offset_y+ABS_SIZE(r);
569          double dy=((double)y)+0.5;
570 
571          if (do_msg && ((r & 0xf) == 0)) {
572             int percent=(r*10000/num_rows)/100;
573 
574             if (percent >= target_percent) {
575                sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
576                      percent);
577                SetStringStatus(gszMsgBox);
578                XSync(mainDisplay, False);
579                while (target_percent <= percent) target_percent += 5;
580             }
581          }
582          for (c=0; c < num_cols; c++) {
583             int x=abs_offset_x+ABS_SIZE(c);
584             double dx=((double)x)+0.5;
585             double new_dx=(double)0, new_dy=(double)0;
586 
587             ReverseTransformDoublePointThroughCTM(dx, dy, ObjPtr->ctm,
588                   &new_dx, &new_dy);
589             new_dx += (double)(ObjPtr->x-ObjPtr->orig_obbox.ltx);
590             new_dy += (double)(ObjPtr->y-ObjPtr->orig_obbox.lty);
591             if (new_dx >= ((double)0) && new_dx < ((double)image_w) &&
592                   new_dy >= ((double)0) && new_dy < ((double)image_h)) {
593                int new_x=(int)new_dx, new_y=(int)new_dy;
594 
595                if (new_x < 0) new_x = 0;
596                if (new_x >= image_w) new_x = image_w-1;
597                if (new_y < 0) new_y = 0;
598                if (new_y >= image_h) new_y = image_h-1;
599                if (XGetPixel(src_bitmap_image,new_x,new_y) != 0) {
600                   XPutPixel(dest_image, c, r, XGetPixel(src_image,new_x,new_y));
601                } else {
602                   XPutPixel(clip_mask_image, c, r, 0);
603                   XPutPixel(dest_image, c, r, bg_pixel);
604                }
605             } else {
606                XPutPixel(clip_mask_image, c, r, 0);
607             }
608          }
609       }
610       XPutImage(mainDisplay, clip_mask, xbmGC, clip_mask_image, 0, 0, 0, 0,
611             num_cols, num_rows);
612       xpm_ptr->clip_mask = clip_mask;
613       XDestroyImage(clip_mask_image);
614       memcpy(&xpm_ptr->cached_ctm, ObjPtr->ctm, sizeof(struct XfrmMtrxRec));
615    }
616    if (do_msg) {
617       SetStringStatus(TgLoadCachedString(CSTID_FINISHED_CACHEING_PIXMAP));
618       XSync(mainDisplay, False);
619    }
620    XPutImage(mainDisplay, dest_pixmap, xpmGC, dest_image, 0, 0, 0, 0,
621          num_cols, num_rows);
622    XPutImage(mainDisplay, dest_bitmap, xbmGC, dest_bitmap_image, 0, 0, 0, 0,
623          num_cols, num_rows);
624    if (do_msg) RestoreStatusStrings();
625 
626    xpm_ptr->cached_pixmap = dest_pixmap;
627    xpm_ptr->cached_bitmap = dest_bitmap;
628    xpm_ptr->cached_zoomed = zoomedIn;
629    xpm_ptr->cached_zoom = zoomScale;
630    xpm_ptr->cached_flip = xpm_ptr->flip;
631    xpm_ptr->cached_w = num_cols;
632    xpm_ptr->cached_h = num_rows;
633    xpm_ptr->cached_color = ObjPtr->color;
634 
635    if (dest_image != NULL) XDestroyImage(dest_image);
636    if (dest_bitmap_image != NULL) XDestroyImage(dest_bitmap_image);
637 
638    if (!watch_cursor && !RedrawDuringScrolling()) {
639       SetDefaultCursor(mainWindow);
640       ShowCursor();
641    } else {
642       CheckInterrupt(TRUE);
643    }
644 }
645 
ExtractPixmap(orig_pixmap,orig_image,orig_bitmap,orig_bitmap_image,x,y,w,h,pixmap,image,bitmap,bitmap_image)646 int ExtractPixmap(orig_pixmap, orig_image, orig_bitmap, orig_bitmap_image,
647       x, y, w, h, pixmap, image, bitmap, bitmap_image)
648    Pixmap orig_pixmap, orig_bitmap, *pixmap, *bitmap;
649    XImage *orig_image, *orig_bitmap_image, **image, **bitmap_image;
650    int x, y, w, h;
651 {
652    register int j, i;
653    XImage *src_image=NULL, *src_bitmap_image=NULL;
654 
655    SetWatchCursor(drawWindow);
656    SetWatchCursor(mainWindow);
657 
658    *pixmap = XCreatePixmap(mainDisplay, dummyPixmap, w, h, mainDepth);
659    *bitmap = XCreatePixmap(mainDisplay, dummyBitmap, w, h, 1);
660    *image = (*pixmap==None ? NULL : XGetImage(mainDisplay, *pixmap, 0, 0, w, h,
661          AllPlanes, ZPixmap));
662    *bitmap_image = (*bitmap==None ? NULL : XGetImage(mainDisplay, *bitmap, 0, 0,
663          w, h, 1, ZPixmap));
664    if (orig_image != NULL && x == 0 && y == 0) {
665       src_image = orig_image;
666    } else {
667       src_image = XGetImage(mainDisplay, orig_pixmap, x, y, w, h, AllPlanes,
668             ZPixmap);
669    }
670    if (orig_bitmap_image != NULL && x == 0 && y == 0) {
671       src_bitmap_image = orig_bitmap_image;
672    } else {
673       src_bitmap_image = XGetImage(mainDisplay, orig_bitmap, x, y, w, h, 1,
674             ZPixmap);
675    }
676    if (*pixmap == None || *bitmap == None || *image==NULL ||
677          *bitmap_image==NULL || src_image==NULL || src_bitmap_image==NULL) {
678       if (*pixmap == None) {
679          FailAllocPixmapMessage(w, h);
680       } else if (*bitmap == None) {
681          FailAllocBitmapMessage(w, h);
682       } else {
683          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
684                INFO_MB);
685       }
686       if (*pixmap != None) XFreePixmap(mainDisplay, *pixmap);
687       if (*bitmap != None) XFreePixmap(mainDisplay, *bitmap);
688       if (*image != NULL) XDestroyImage(*image);
689       if (*bitmap_image != NULL) XDestroyImage(*bitmap_image);
690       if (orig_image != NULL) XDestroyImage(src_image);
691       if (orig_bitmap_image != NULL) XDestroyImage(src_bitmap_image);
692       if (!(orig_image != NULL && x==0 && y==0) && src_image != NULL) {
693          XDestroyImage(src_image);
694       }
695       if (!(orig_bitmap_image != NULL && x==0 && y==0) &&
696             src_bitmap_image != NULL) {
697          XDestroyImage(src_bitmap_image);
698       }
699       *pixmap = *bitmap = None;
700       *image = *bitmap_image = NULL;
701       SetDefaultCursor(mainWindow);
702       SetDefaultCursor(drawWindow);
703       return FALSE;
704    }
705    for (i = 0; i < h; i++) {
706       for (j = 0; j < w; j++) {
707          XPutPixel(*image, j, i, XGetPixel(src_image, j, i));
708          XPutPixel(*bitmap_image, j, i, XGetPixel(src_bitmap_image, j, i));
709       }
710    }
711    XPutImage(mainDisplay, *pixmap, xpmGC, *image, 0, 0, 0, 0, w, h);
712    XPutImage(mainDisplay, *bitmap, xbmGC, *bitmap_image, 0, 0, 0, 0, w, h);
713    SetDefaultCursor(mainWindow);
714    SetDefaultCursor(drawWindow);
715 
716    if (!(orig_image != NULL && x == 0 && y == 0)) XDestroyImage(src_image);
717    if (!(orig_bitmap_image != NULL && x == 0 && y == 0)) {
718       XDestroyImage(src_bitmap_image);
719    }
720    return TRUE;
721 }
722 
CutXPixmap(ObjPtrToCut,pAbsX,pAbsY,pAbsW,pAbsH)723 struct ObjRec *CutXPixmap(ObjPtrToCut, pAbsX, pAbsY, pAbsW, pAbsH)
724    struct ObjRec *ObjPtrToCut; /* if NULL, use topSel->obj */
725    int *pAbsX, *pAbsY, *pAbsW, *pAbsH;
726    /*
727     * if (ObjPtrToCut != NULL) {
728     *    return new_obj_ptr if cut was done successfully
729     *    return ObjPtrToCut if there is no need to cut anything
730     *    return NULL if something is wrong and object needs to be deleted
731     * }
732     * Note: if ObjPtrToCut is not NULL, then ObjPtrToCut is topSel->obj and
733     *         it's called from CropImage() with topSel->obj->ctm != NULL
734     *         with fullTrueColorMode == TRUE && HasZlibSupport() == TRUE
735     */
736 {
737    register int j, i;
738    int w, h, chars_per_pixel, ncolors=0, *pixels=NULL, len;
739    int ltx, lty, rbx, rby, new_w, new_h;
740    int src_x=0, src_y=0, src_w=0, src_h=0, image_w=0, image_h=0;
741    char *color_char, **color_str;
742    float h_scale=1.0, v_scale=1.0, mag=1.0;
743    Pixmap dest_pixmap=None, dest_bitmap=None;
744    XImage *dest_image=NULL, *dest_bitmap_image=NULL;
745    struct ObjRec *obj_ptr=topSel->obj, *new_obj_ptr=NULL;
746    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm, *new_xpm_ptr=NULL;
747 
748    src_x = 0;
749    src_y = 0;
750    if (ObjPtrToCut != NULL && pAbsX != NULL && pAbsY != NULL && pAbsW != NULL &&
751          pAbsH != NULL) {
752       obj_ptr = ObjPtrToCut;
753       xpm_ptr = obj_ptr->detail.xpm;
754       image_w = xpm_ptr->image_w;
755       image_h = xpm_ptr->image_h;
756       src_x = *pAbsX;
757       src_y = *pAbsY;
758       src_w = *pAbsW;
759       src_h = *pAbsH;
760       if (src_x==0 && src_y==0 && src_w==image_w && src_h==image_h &&
761             mag==1.0) {
762          return obj_ptr;
763       }
764       if (src_w==0 || src_h==0) {
765          MsgBox(TgLoadString(STID_XPM_CANT_HAVE_0_W_OR_H), TOOL_NAME, INFO_MB);
766          return NULL;
767       }
768    } else {
769       src_w = image_w = xpm_ptr->image_w;
770       src_h = image_h = xpm_ptr->image_h;
771       mag = 1.0;
772 
773       h_scale = ((float)((float)(obj_ptr->obbox.rbx-obj_ptr->obbox.ltx)) /
774             ((float)image_w));
775       v_scale = ((float)((float)(obj_ptr->obbox.rby-obj_ptr->obbox.lty)) /
776             ((float)image_h));
777 
778       if (pAbsX == NULL && pAbsY == NULL && pAbsW == NULL && pAbsH == NULL) {
779          char mag_spec[MAXSTRING];
780 
781          sprintf(gszMsgBox, TgLoadString(STID_ENTER_GEOM_SPEC_ORIG_SIZE),
782                image_w, image_h);
783          *mag_spec = '\0';
784          Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL),
785                mag_spec);
786          UtilTrimBlanks(mag_spec);
787          if (*mag_spec == '\0') return obj_ptr;
788 
789          ParseCutSpec(mag_spec, image_w, image_h, &mag, &src_x, &src_y, &src_w,
790                &src_h);
791       } else {
792          src_x = *pAbsX;
793          src_y = *pAbsY;
794          src_w = *pAbsW;
795          src_h = *pAbsH;
796       }
797       if (src_x==0 && src_y==0 && src_w==image_w && src_h==image_h &&
798             mag==1.0) {
799          return obj_ptr;
800       }
801       if (src_w==0 || src_h==0) {
802          MsgBox(TgLoadString(STID_XPM_CANT_HAVE_0_W_OR_H), TOOL_NAME, INFO_MB);
803          return NULL;
804       }
805       PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
806    }
807    if (!ExtractPixmap(xpm_ptr->pixmap, xpm_ptr->image, xpm_ptr->bitmap,
808          xpm_ptr->bitmap_image, src_x, src_y, src_w, src_h,
809          &dest_pixmap, &dest_image, &dest_bitmap, &dest_bitmap_image)) {
810       if (ObjPtrToCut == NULL || pAbsX == NULL || pAbsY == NULL ||
811             pAbsW == NULL || pAbsH == NULL) {
812          AbortPrepareCmd(CMD_REPLACE);
813       }
814       return NULL;
815    }
816    if ((xpm_ptr->real_type == XPM_JPEG || xpm_ptr->real_type == PPM_TRUE) &&
817          fullTrueColorMode && HasZlibSupport()) {
818       char tmp_fname[MAXPATHLENGTH];
819 
820       if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
821          if (ObjPtrToCut == NULL || pAbsX == NULL || pAbsY == NULL ||
822                pAbsW == NULL || pAbsH == NULL) {
823             AbortPrepareCmd(CMD_REPLACE);
824          }
825          return NULL;
826       }
827       if (DumpXImageToPpmFile(dest_image, src_w, src_h, tmp_fname, TRUE)) {
828          char deflated_fname[MAXPATHLENGTH];
829          unsigned int data_size=0;
830          char *ppm_data=NULL;
831 
832          snprintf(deflated_fname, sizeof(deflated_fname), "%s.ppm.z",
833                tmp_fname);
834          ppm_data = ReadFileIntoBuf(deflated_fname, &data_size);
835          unlink(deflated_fname);
836          unlink(tmp_fname);
837          if (ppm_data) {
838             new_obj_ptr = CreatePpmTrueObjFromImage(dest_image, src_w, src_h,
839                   ppm_data, data_size);
840          }
841       }
842       XFreePixmap(mainDisplay, dest_pixmap);
843       XFreePixmap(mainDisplay, dest_bitmap);
844       XDestroyImage(dest_image);
845       XDestroyImage(dest_bitmap_image);
846       dest_pixmap = dest_bitmap = None;
847       dest_image = dest_bitmap_image = NULL;
848 
849       if (new_obj_ptr == NULL) {
850          if (ObjPtrToCut == NULL || pAbsX == NULL || pAbsY == NULL ||
851                pAbsW == NULL || pAbsH == NULL) {
852             AbortPrepareCmd(CMD_REPLACE);
853          }
854          return NULL;
855       }
856       MoveObj(new_obj_ptr, obj_ptr->x, obj_ptr->y);
857    }
858    sprintf(gszMsgBox, TgLoadCachedString(CSTID_NEW_XPM_SIZE_IS_W_X_H),
859          src_w, src_h);
860    Msg(gszMsgBox);
861    if (ObjPtrToCut != NULL && pAbsX != NULL && pAbsY != NULL && pAbsW != NULL &&
862          pAbsH != NULL) {
863       return new_obj_ptr;
864    } else {
865       UnlinkObj(obj_ptr);
866 
867       ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
868       HighLightReverse();
869 
870       w = new_w = (int)(((float)src_w) * mag);
871       h = new_h = (int)(((float)src_h) * mag);
872    }
873    if (new_obj_ptr == NULL) {
874       new_obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
875       if (new_obj_ptr == NULL) FailAllocMessage();
876       memset(new_obj_ptr, 0, sizeof(struct ObjRec));
877       DupObjBasics(obj_ptr, new_obj_ptr);
878 
879       new_xpm_ptr = (struct XPmRec *)malloc(sizeof(struct XPmRec));
880       if (new_xpm_ptr == NULL) FailAllocMessage();
881       memset(new_xpm_ptr, 0, sizeof(struct XPmRec));
882       new_obj_ptr->detail.xpm = new_xpm_ptr;
883 
884       new_xpm_ptr->image_w = src_w;
885       new_xpm_ptr->image_h = src_h;
886       new_xpm_ptr->pixmap = dest_pixmap;
887       new_xpm_ptr->image = dest_image;
888       new_xpm_ptr->bitmap = dest_bitmap;
889       new_xpm_ptr->bitmap_image = dest_bitmap_image;
890       new_xpm_ptr->data = NULL;
891       new_xpm_ptr->fill = xpm_ptr->fill;
892       new_xpm_ptr->flip = xpm_ptr->flip;
893       new_xpm_ptr->cached_zoom = 0;
894       new_xpm_ptr->cached_pixmap = None;
895       new_xpm_ptr->cached_bitmap = None;
896       new_xpm_ptr->cached_flip = 0;
897       new_xpm_ptr->cached_w = 0;
898       new_xpm_ptr->cached_h = 0;
899       new_xpm_ptr->cached_color = (-1);
900 
901       chars_per_pixel = new_xpm_ptr->chars_per_pixel = xpm_ptr->chars_per_pixel;
902       new_xpm_ptr->first_pixel_is_bg = xpm_ptr->first_pixel_is_bg;
903 
904       ncolors = new_xpm_ptr->ncolors = xpm_ptr->ncolors;
905       color_char = new_xpm_ptr->color_char =
906             (char*)malloc((ncolors*chars_per_pixel)*sizeof(char));
907       if (color_char == NULL) FailAllocMessage();
908       color_str = new_xpm_ptr->color_str =
909             (char**)malloc(ncolors*sizeof(char*));
910       if (color_str == NULL) FailAllocMessage();
911       pixels = new_xpm_ptr->pixels = (int*)malloc(ncolors*sizeof(int));
912       if (pixels == NULL) FailAllocMessage();
913       for (i = 0; i < ncolors; i++) {
914          pixels[i] = xpm_ptr->pixels[i];
915 
916          for (j = 0; j < chars_per_pixel; j++) {
917             color_char[i*chars_per_pixel+j] =
918                   xpm_ptr->color_char[i*chars_per_pixel+j];
919          }
920          len = strlen(xpm_ptr->color_str[i]);
921          color_str[i] = (char*)malloc((len+1)*sizeof(char));
922          if (color_str[i] == NULL) FailAllocMessage();
923          strcpy(color_str[i], xpm_ptr->color_str[i]);
924       }
925       new_w = round(h_scale * ((float)w));
926       new_h = round(v_scale * ((float)h));
927 
928       new_obj_ptr->obbox.ltx = obj_ptr->obbox.ltx;
929       new_obj_ptr->obbox.lty = obj_ptr->obbox.lty;
930       new_obj_ptr->obbox.rbx = new_obj_ptr->bbox.rbx = obj_ptr->obbox.ltx+new_w;
931       new_obj_ptr->obbox.rby = new_obj_ptr->bbox.rby = obj_ptr->obbox.lty+new_h;
932 
933       AdjObjBBox(new_obj_ptr);
934    }
935    topSel->obj = botSel->obj = new_obj_ptr;
936    AddObj(NULL, topObj, new_obj_ptr);
937    if (pAbsX != NULL && pAbsY != NULL) {
938       MoveObj(new_obj_ptr, *pAbsX, *pAbsY);
939    }
940    RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
941    FreeObj(obj_ptr);
942 
943    UpdSelBBox();
944    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
945          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
946          selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
947          selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
948    HighLightForward();
949    SetFileModified(TRUE);
950    justDupped = FALSE;
951 
952    return new_obj_ptr;
953 }
954 
955 static
SaveXPmColors(FP,def_color_index,xpm_ptr,ncolors,chars_per_pixel,color_char,color_str,pixels)956 void SaveXPmColors(FP, def_color_index, xpm_ptr, ncolors, chars_per_pixel,
957       color_char, color_str, pixels)
958    FILE *FP;
959    int def_color_index, ncolors, chars_per_pixel, *pixels;
960    struct XPmRec *xpm_ptr;
961    char *color_char, **color_str;
962 {
963    register int i, j;
964    int cur_pixel, found_index;
965 
966    if (!colorDisplay && xpm_ptr->red != NULL) {
967       for (i=0; i < ncolors; i++) {
968          if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
969          for (j=0; j < chars_per_pixel; j++) {
970             if (fprintf(FP, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
971                writeFileFailed = TRUE;
972             }
973          }
974          if (i == ncolors-1) {
975             if (fprintf(FP, "\", \"%s\", %1d, %1d, %1d],[\n", color_str[i],
976                   (int)(xpm_ptr->red[i]), (int)(xpm_ptr->green[i]),
977                   (int)(xpm_ptr->blue[i])) == EOF) {
978                writeFileFailed = TRUE;
979             }
980          } else {
981             if (fprintf(FP, "\", \"%s\", %1d, %1d, %1d,\n", color_str[i],
982                   (int)(xpm_ptr->red[i]), (int)(xpm_ptr->green[i]),
983                   (int)(xpm_ptr->blue[i])) == EOF) {
984                writeFileFailed = TRUE;
985             }
986          }
987       }
988    } else {
989       for (i=0; i < ncolors; i++) {
990          found_index = def_color_index;
991          cur_pixel = pixels[i];
992          if (cur_pixel != (-1)) {
993             for (j=0; j < maxColors; j++) {
994                if (colorPixels[j] == cur_pixel) {
995                   found_index = j;
996                   break;
997                }
998             }
999          }
1000          if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
1001          for (j = 0; j < chars_per_pixel; j++) {
1002             if (fprintf(FP, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
1003                writeFileFailed = TRUE;
1004             }
1005          }
1006          if (i == ncolors-1) {
1007             if (fprintf(FP, "\", \"%s\", %1d, %1d, %1d],[\n", color_str[i],
1008                   (int)(10000*((int)tgifColors[found_index].red)/maxRGB),
1009                   (int)(10000*((int)tgifColors[found_index].green)/maxRGB),
1010                   (int)(10000*((int)tgifColors[found_index].blue)/maxRGB)) ==
1011                   EOF) {
1012                writeFileFailed = TRUE;
1013             }
1014          } else {
1015             if (fprintf(FP, "\", \"%s\", %1d, %1d, %1d,\n", color_str[i],
1016                   (int)(10000*((int)tgifColors[found_index].red)/maxRGB),
1017                   (int)(10000*((int)tgifColors[found_index].green)/maxRGB),
1018                   (int)(10000*((int)tgifColors[found_index].blue)/maxRGB)) ==
1019                   EOF) {
1020                writeFileFailed = TRUE;
1021             }
1022          }
1023       }
1024    }
1025 }
1026 
1027 static
PrTgifDumpOldXPmObj(FP,ObjPtr,pmtrx)1028 void PrTgifDumpOldXPmObj(FP, ObjPtr, pmtrx)
1029    FILE *FP;
1030    struct ObjRec *ObjPtr;
1031    struct MtrxRec *pmtrx;
1032 {
1033    int row=0, i=0, index=0, col=0, j=0, num_nibbles=0, nibble_count=0;
1034    int ltx=0, lty=0, rbx=0, rby=0, w=0, h=0, image_w=0, image_h=0;
1035    int ncolors=0, *pixels=NULL, flip=0, orig_x=0, orig_y=0;
1036    int chars_per_pixel=0, x=0, y=0;
1037    int h_blocks=0, v_blocks=0, block_w=0, block_h=0, bit_count=0, data=0;
1038    char *xpm_data=NULL, bg_char[2];
1039    Pixmap pixmap, bitmap=(Pixmap)0;
1040    struct XPmRec *xpm_ptr=NULL;
1041 
1042    bg_char[0] = bg_char[1] = '\0';
1043 
1044    ltx = ObjPtr->obbox.ltx;
1045    lty = ObjPtr->obbox.lty;
1046    rbx = ObjPtr->obbox.rbx;
1047    rby = ObjPtr->obbox.rby;
1048 
1049    xpm_ptr = ObjPtr->detail.xpm;
1050 
1051    pixmap = xpm_ptr->pixmap;
1052    bitmap = xpm_ptr->bitmap;
1053    pixels = xpm_ptr->pixels;
1054    ncolors = xpm_ptr->ncolors;
1055    flip = xpm_ptr->flip;
1056    image_w = xpm_ptr->image_w;
1057    image_h = xpm_ptr->image_h;
1058 
1059    w = rbx - ltx;
1060    h = rby - lty;
1061 
1062    orig_x = (pmtrx->transformed_w >= 0.0) ? ltx : ltx+w;
1063    orig_y = (pmtrx->transformed_h >= 0.0) ? lty : lty+h;
1064 
1065    xpm_data = xpm_ptr->data;
1066    chars_per_pixel = xpm_ptr->chars_per_pixel;
1067 
1068    fprintf(stderr, "%s\n", TgLoadString(STID_WARN_XPM_ALL_NON_BG_BE_BLACK));
1069    switch (chars_per_pixel) {
1070    case 1:
1071       bg_char[0] = xpm_ptr->color_char[0];
1072       bg_char[1] = '\0';
1073       if (*bg_char != '`' && *bg_char != ' ') {
1074          bg_char[0] = bg_char[1] = '\0';
1075       }
1076       break;
1077    case 2:
1078       bg_char[0] = xpm_ptr->color_char[0];
1079       bg_char[1] = xpm_ptr->color_char[1];
1080       if (!(bg_char[0] == '`' && bg_char[1] == '`') &&
1081             !(bg_char[0] == ' ' && bg_char[1] == ' ')) {
1082          bg_char[0] = '\0';
1083       }
1084       break;
1085    }
1086 
1087    h_blocks = ((image_w&0xff) == 0) ? (image_w>>8) : ((image_w>>8)+1);
1088    v_blocks = ((image_h&0xff) == 0) ? (image_h>>8) : ((image_h>>8)+1);
1089 
1090    fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
1091    fprintf(FP, "   %1d %1d %s %.3f %.3f %s %1d %s\n\n",
1092          orig_x, orig_y, gPsCmd[PS_TRANSLATE],
1093          pmtrx->dump_h_scale, pmtrx->dump_v_scale, gPsCmd[PS_SCALE],
1094          pmtrx->degree, gPsCmd[PS_ROTATE]);
1095 
1096    for (row=0; row < v_blocks; row++) {
1097       y = row<<8;
1098       block_h = (row == v_blocks-1) ? image_h-y : 0x100;
1099 
1100       for (col=0; col < h_blocks; col++) {
1101          x = col<<8;
1102          block_w = (col == h_blocks-1) ? image_w-x : 0x100;
1103 
1104          num_nibbles = ((block_w%4) == 0) ? (int)(block_w>>2) :
1105                (int)(block_w>>2)+1;
1106 
1107          fprintf(FP, "   %s\n", gPsCmd[PS_GSAVE]);
1108          fprintf(FP, "   %1d %1d %s\n", x, y, gPsCmd[PS_TRANSLATE]);
1109          fprintf(FP, "   %1d %1d true [1 0 0 1 0 0]\n   {<", block_w,
1110                block_h);
1111 
1112          nibble_count = 0;
1113          for (i=0; i < block_h; i++) {
1114             bit_count = 0;
1115             data = 0;
1116             for (j=0; j < block_w; j++) {
1117                switch (chars_per_pixel) {
1118                case 1:
1119                   data = (xpm_data[(i+y)*image_w+j+x] != *bg_char) ?
1120                         (data<<1) | 1 : (data<<1);
1121                   break;
1122                case 2:
1123                   index = ((i+y)*image_w+j+x)*chars_per_pixel;
1124                   data = (xpm_data[index] == bg_char[0] &&
1125                         xpm_data[index+1] == bg_char[1]) ?
1126                         (data<<1) : (data<<1) | 1;
1127                   break;
1128                }
1129                if (++bit_count == 4) {
1130                   if (nibble_count++ == 64) {
1131                      nibble_count = 1;
1132                      fprintf(FP, "\n     ");
1133                   }
1134                   fprintf(FP, "%c", hexValue[data]);
1135                   bit_count = 0;
1136                   data = 0;
1137                }
1138             }
1139             if ((block_w % 4) != 0) {
1140                data <<= (4 - (block_w % 4));
1141                if (nibble_count++ == 64) {
1142                   nibble_count = 1;
1143                   fprintf(FP, "\n     ");
1144                }
1145                fprintf(FP, "%c", hexValue[data]);
1146             }
1147             if ((num_nibbles & 0x1) == 1) {
1148                if (nibble_count++ == 64) {
1149                   nibble_count = 1;
1150                   fprintf(FP, "\n     ");
1151                }
1152                fprintf(FP, "0");
1153             }
1154          }
1155          fprintf(FP, ">}\n");
1156          fprintf(FP, "   %s\n", gPsCmd[PS_IMAGEMASK]);
1157          fprintf(FP, "   %s\n", gPsCmd[PS_GRESTORE]);
1158          if (row!=v_blocks-1 || col!=h_blocks-1) fprintf(FP, "\n");
1159       }
1160    }
1161    fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
1162    fprintf(FP, "\n");
1163 }
1164 
1165 static
MalformedPpmMessage(tmp_fname)1166 int MalformedPpmMessage(tmp_fname)
1167    char *tmp_fname;
1168 {
1169    sprintf(gszMsgBox, TgLoadString(STID_CANT_IMPORT_GIVEN_PPM_MALFORM),
1170          tmp_fname);
1171    if (PRTGIF) {
1172       fprintf(stderr, "%s\n", gszMsgBox);
1173    } else {
1174       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1175    }
1176    return FALSE;
1177 }
1178 
1179 static
ReadPpmHeaderStr(ppm_fp,tmp_fname,buf,sz_buf)1180 int ReadPpmHeaderStr(ppm_fp, tmp_fname, buf, sz_buf)
1181    FILE *ppm_fp;
1182    char *tmp_fname, *buf;
1183    int sz_buf;
1184 {
1185    int i=0, write_index=0;
1186 
1187    for (i=0; i < sz_buf-1; i++) {
1188       char ch='\0';
1189 
1190       if (fread(&ch, sizeof(char), 1, ppm_fp) != 1) {
1191          /* failed */
1192          break;
1193       }
1194       if (i == 0 && ch == '#') {
1195          /* skip a comment line */
1196          char *line_buf=UtilGetALine(ppm_fp);
1197 
1198          if (line_buf != NULL) {
1199             UtilFree(line_buf);
1200             i = (-1);
1201          } else {
1202             break;
1203          }
1204       } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
1205          if (write_index != 0) {
1206             buf[write_index++] = '\0';
1207             return TRUE;
1208          }
1209       } else {
1210          buf[write_index++] = ch;
1211       }
1212    }
1213    return MalformedPpmMessage(tmp_fname);
1214 }
1215 
1216 static
ReadPpmHeader(ppm_fp,tmp_fname,pn_format,pn_w,pn_h,pn_max_val)1217 int ReadPpmHeader(ppm_fp, tmp_fname, pn_format, pn_w, pn_h, pn_max_val)
1218    FILE *ppm_fp;
1219    char *tmp_fname;
1220    int *pn_format, *pn_w, *pn_h, *pn_max_val;
1221 {
1222    char buf[MAXSTRING];
1223 
1224    if (!ReadPpmHeaderStr(ppm_fp, tmp_fname, buf, sizeof(buf))) {
1225       return FALSE;
1226    }
1227    if (strcmp(buf, "P3") == 0) {
1228       if (pn_format != NULL) *pn_format = TYPE_PPM3;
1229    } else if (strcmp(buf, "P6") == 0) {
1230       if (pn_format != NULL) *pn_format = TYPE_PPM6;
1231    } else if (strcmp(buf, "P5") == 0) {
1232       if (pn_format != NULL) *pn_format = TYPE_PPM5;
1233    } else {
1234       return MalformedPpmMessage(tmp_fname);
1235    }
1236    if (!ReadPpmHeaderStr(ppm_fp, tmp_fname, buf, sizeof(buf))) {
1237       return FALSE;
1238    }
1239    if (sscanf(buf, "%d", pn_w) != 1) {
1240       return MalformedPpmMessage(tmp_fname);
1241    }
1242    if (!ReadPpmHeaderStr(ppm_fp, tmp_fname, buf, sizeof(buf))) {
1243       return FALSE;
1244    }
1245    if (sscanf(buf, "%d", pn_h) != 1) {
1246       return MalformedPpmMessage(tmp_fname);
1247    }
1248    if (!ReadPpmHeaderStr(ppm_fp, tmp_fname, buf, sizeof(buf))) {
1249       return FALSE;
1250    }
1251    if (sscanf(buf, "%d", pn_max_val) != 1) {
1252       return MalformedPpmMessage(tmp_fname);
1253    }
1254    return TRUE;
1255 }
1256 
1257 static
DumpPpm6File(FP,image_w,image_h,tmp_fname)1258 void DumpPpm6File(FP, image_w, image_h, tmp_fname)
1259    FILE *FP;
1260    int image_w, image_h;
1261    char *tmp_fname;
1262 {
1263    FILE *ppm_fp=fopen(tmp_fname, "r");
1264    int format=0, w=0, h=0, max_val=0, row=0, col=0;
1265 
1266    if (ppm_fp == NULL) {
1267       FailToOpenMessage(tmp_fname, "r", NULL);
1268       return;
1269    }
1270    if (!ReadPpmHeader(ppm_fp, tmp_fname, &format, &w, &h, &max_val)) {
1271       fclose(ppm_fp);
1272       return;
1273    }
1274    if (w != image_w || h != image_h) {
1275       sprintf(gszMsgBox, TgLoadString(STID_PPM6_DIM_NOT_MATCH), w, h, tmp_fname,
1276             image_w, image_h);
1277       if (PRTGIF) {
1278          fprintf(stderr, "%s\n", gszMsgBox);
1279       } else {
1280          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1281       }
1282       fclose(ppm_fp);
1283       return;
1284    }
1285    if (max_val != 255 && max_val != 65535) {
1286       sprintf(gszMsgBox, TgLoadString(STID_UNSUP_PPM6_MAX_VAL), max_val,
1287             tmp_fname);
1288       if (PRTGIF) {
1289          fprintf(stderr, "%s\n", gszMsgBox);
1290       } else {
1291          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1292       }
1293       fclose(ppm_fp);
1294       return;
1295    }
1296    for (row=0; row < image_h; row++) {
1297       for (col=0; col < image_w; col++) {
1298          unsigned char buf[4];
1299 
1300          if (format == TYPE_PPM6) {
1301             if (max_val == 65535) {
1302                unsigned char r_buf[2], g_buf[2], b_buf[2];
1303 
1304                if (fread(r_buf, sizeof(char), 2, ppm_fp) != 2 ||
1305                      fread(g_buf, sizeof(char), 2, ppm_fp) != 2 ||
1306                      fread(b_buf, sizeof(char), 2, ppm_fp) != 2) {
1307                   MalformedPpmMessage(tmp_fname);
1308                   fclose(ppm_fp);
1309                   return;
1310                }
1311                if (littleEndianPpm6) {
1312                   buf[0] = r_buf[1];
1313                   buf[1] = g_buf[1];
1314                   buf[2] = b_buf[1];
1315                } else {
1316                   buf[0] = r_buf[0];
1317                   buf[1] = g_buf[0];
1318                   buf[2] = b_buf[0];
1319                }
1320             } else {
1321                if (fread(buf, sizeof(char), 3, ppm_fp) != 3) {
1322                   MalformedPpmMessage(tmp_fname);
1323                   fclose(ppm_fp);
1324                   return;
1325                }
1326             }
1327          } else if (format == TYPE_PPM5) {
1328             if (max_val == 65535) {
1329                unsigned char g_buf[2];
1330 
1331                if (fread(g_buf, sizeof(char), 2, ppm_fp) != 2) {
1332                   MalformedPpmMessage(tmp_fname);
1333                   fclose(ppm_fp);
1334                   return;
1335                }
1336                if (littleEndianPpm6) {
1337                   buf[0] = buf[1] = buf[2] = g_buf[1];
1338                } else {
1339                   buf[0] = buf[1] = buf[2] = g_buf[0];
1340                }
1341             } else {
1342                if (fread(buf, sizeof(char), 1, ppm_fp) != 1) {
1343                   MalformedPpmMessage(tmp_fname);
1344                   fclose(ppm_fp);
1345                   return;
1346                }
1347                buf[1] = buf[2] = buf[0];
1348             }
1349          } else {
1350             int red=0, green=0, blue=0;
1351 
1352             if (fscanf(FP, "%d %d %d", &red, &green, &blue) != 3) {
1353                MalformedPpmMessage(tmp_fname);
1354                fclose(ppm_fp);
1355                return;
1356             }
1357 	    buf[0] = (unsigned char)(red & 0x0ff);
1358             buf[1] = (unsigned char)(green & 0x0ff);
1359             buf[2] = (unsigned char)(blue & 0x0ff);
1360          }
1361          buf[3] = '\0';
1362          if (!colorDump) {
1363             double dr=(double)0, dg=(double)0, db=(double)0, dgray=(double)0;
1364             int igray=0;
1365 
1366             dr = (double)(unsigned int)(buf[0]);
1367             dg = (double)(unsigned int)(buf[1]);
1368             db = (double)(unsigned int)(buf[2]);
1369             dgray = (0.299*dr)+(0.587*dg)+(0.114*db);
1370             igray = round(dgray);
1371             if (igray > 255) igray = 255;
1372             if (igray < 0) igray = 0;
1373             buf[0] = buf[1] = buf[2] = (unsigned char)(igray & 0x0ff);
1374          }
1375          fprintf(FP, "%02x%02x%02x", (unsigned int)(buf[0]),
1376                (unsigned int)(buf[1]), (unsigned int)(buf[2]));
1377          if (col%12 == 11) fprintf(FP, "\n   ");
1378       }
1379       if (col%12 != 11) fprintf(FP, "\n");
1380       if (row != image_h-1) fprintf(FP, "   ");
1381    }
1382    fclose(ppm_fp);
1383 }
1384 
1385 static
ObjHasXpmObj(ObjPtr)1386 int ObjHasXpmObj(ObjPtr)
1387    struct ObjRec *ObjPtr;
1388 {
1389    switch (ObjPtr->type) {
1390    case OBJ_XPM:
1391       if (!colorLayers || ObjInVisibleLayer(ObjPtr)) {
1392          return TRUE;
1393       }
1394       return FALSE;
1395 
1396    case OBJ_SYM:
1397    case OBJ_ICON:
1398    case OBJ_GROUP:
1399       if (!colorLayers || ObjInVisibleLayer(ObjPtr)) {
1400          struct ObjRec *obj_ptr=ObjPtr->detail.r->last;
1401 
1402          for ( ; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1403             obj_ptr->tmp_parent = ObjPtr;
1404             if (ObjHasXpmObj(obj_ptr)) return TRUE;
1405          }
1406          return TRUE;
1407       }
1408       return FALSE;
1409    case OBJ_PIN:
1410       if (!colorLayers || ObjInVisibleLayer(ObjPtr)) {
1411          struct ObjRec *obj_ptr=GetPinObj(ObjPtr);
1412 
1413          for ( ; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1414             obj_ptr->tmp_parent = ObjPtr;
1415             if (ObjHasXpmObj(obj_ptr)) return TRUE;
1416          }
1417          return TRUE;
1418       }
1419       return FALSE;
1420 
1421    default: break;
1422    }
1423    return FALSE;
1424 }
1425 
1426 static
PageHasXpmObj(page_ptr)1427 int PageHasXpmObj(page_ptr)
1428    struct PageRec *page_ptr;
1429 {
1430    struct ObjRec *obj_ptr=NULL;
1431 
1432    for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1433       obj_ptr->tmp_parent = NULL;
1434       if (ObjHasXpmObj(obj_ptr)) return TRUE;
1435    }
1436    return FALSE;
1437 }
1438 
1439 static
FileHasXpmObj()1440 int FileHasXpmObj()
1441 {
1442    struct PageRec *page_ptr=NULL;
1443 
1444    for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
1445       if (PageHasXpmObj(page_ptr)) return TRUE;
1446    }
1447    return FALSE;
1448 }
1449 
1450 static
HashAllColorPixels()1451 void HashAllColorPixels()
1452 {
1453    int i=0;
1454 
1455    for (i=0; i < maxColors; i++) {
1456       int pixel=colorPixels[i];
1457 
1458       HashStoreInt(&gColorsHashForPrinting, (char*)(&pixel), sizeof(int), i);
1459    }
1460 }
1461 
CleanUpCachedColorsForPrinting()1462 void CleanUpCachedColorsForPrinting()
1463 {
1464    if (gnColorsHashForPrintingValid) {
1465       CleanUpHash(&gColorsHashForPrinting);
1466       gnColorsHashForPrintingValid = FALSE;
1467    }
1468 }
1469 
CacheColorsForPrinting()1470 void CacheColorsForPrinting()
1471 {
1472    XColor *saved_tgif_colors=tgifColors;
1473 
1474    if (PRTGIF && !cmdLineOpenDisplay) return;
1475    if (!FileHasXpmObj()) return;
1476 
1477    gnColorsHashForPrintingValid = TRUE;
1478    InitHash(&gColorsHashForPrinting, TG_HASH_SIZE_LARGE);
1479 
1480    if (printUsingRequestedColor) tgifColors = tgifRequestedColors;
1481 
1482    HashAllColorPixels();
1483 
1484    if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
1485 }
1486 
1487 typedef struct tagImagePixelInfo {
1488    int image_w, image_h;
1489    int **image_pixels;
1490    /*
1491     * transparent is not used for now because the only to create a pixmap
1492     *       object with too many colors is to import a XPM object
1493     * we assume that people just use JPEG and GIF import
1494     */
1495    unsigned char **transparent;
1496 } ImagePixelInfo;
1497 
1498 static
FreeImagePixels(pipi)1499 void FreeImagePixels(pipi)
1500    ImagePixelInfo *pipi;
1501 {
1502    int row=0, image_h=pipi->image_h;
1503    int **image_pixels=NULL;
1504    unsigned char **transparent=NULL;
1505 
1506    if (pipi == NULL) return;
1507 
1508    image_pixels = pipi->image_pixels;
1509    transparent = pipi->transparent;
1510 
1511    if (image_pixels != NULL) {
1512       for (row=0; row < image_h; row++) {
1513          if (image_pixels[row] != NULL) free(image_pixels[row]);
1514       }
1515       free(image_pixels);
1516    }
1517    if (transparent != NULL) {
1518       for (row=0; row < image_h; row++) {
1519          if (transparent[row] != NULL) free(transparent[row]);
1520       }
1521       free(transparent);
1522    }
1523    memset(pipi, 0, sizeof(ImagePixelInfo));
1524 }
1525 
1526 static
SetAColorByteInfoByXpmRGB(pcb,xpm_ptr,pixel_index)1527 void SetAColorByteInfoByXpmRGB(pcb, xpm_ptr, pixel_index)
1528    ColorBytes *pcb;
1529    struct XPmRec *xpm_ptr;
1530    int pixel_index;
1531 {
1532    double red=0, green=0, blue=0;
1533    int r=0, g=0, b=0;
1534 
1535    red = ((double)255) * ((double)(xpm_ptr->red[pixel_index])) /
1536          ((double)10000.0);
1537    green = ((double)255) * ((double)(xpm_ptr->green[pixel_index])) /
1538          ((double)10000.0);
1539    blue = ((double)255) * ((double)(xpm_ptr->blue[pixel_index])) /
1540          ((double)10000.0);
1541 
1542    r = round(red);
1543    g = round(green);
1544    b = round(blue);
1545 
1546    if (r > 255) r = 255;
1547    if (g > 255) g = 255;
1548    if (b > 255) b = 255;
1549 
1550    if (r < 0) r = 0;
1551    if (g < 0) g = 0;
1552    if (b < 0) b = 0;
1553 
1554    pcb->r = (unsigned char)(r & 0x0ff);
1555    pcb->g = (unsigned char)(g & 0x0ff);
1556    pcb->b = (unsigned char)(b & 0x0ff);
1557 
1558    pcb->valid = TRUE;
1559 }
1560 
1561 static
SetAColorByteByXpmRGB(pcb,xpm_ptr,index,table_size)1562 void SetAColorByteByXpmRGB(pcb, xpm_ptr, index, table_size)
1563    ColorBytes *pcb;
1564    struct XPmRec *xpm_ptr;
1565    int index, table_size;
1566 {
1567 #ifdef _TGIF_DBG /* debug, do not translate */
1568    TgAssert(index >= 0 && index < table_size,
1569          "index out of range in SetAColorByteByXpmRGB()", NULL);
1570 #endif /* _TGIF_DBG */
1571    if (pcb[index].valid) return;
1572 
1573    SetAColorByteInfoByXpmRGB(&pcb[index], xpm_ptr, index);
1574 }
1575 
1576 static
SetAColorByteByMaxRGB(pcb,xpm_color_index,global_color_index,table_size)1577 void SetAColorByteByMaxRGB(pcb, xpm_color_index, global_color_index, table_size)
1578    ColorBytes *pcb;
1579    int xpm_color_index, global_color_index, table_size;
1580 {
1581 #ifdef _TGIF_DBG /* debug, do not translate */
1582    TgAssert(xpm_color_index >= 0 && xpm_color_index < table_size,
1583          "xpm_color_index out of range in SetAColorByteByXpmRGB()", NULL);
1584 #endif /* _TGIF_DBG */
1585    if (pcb[xpm_color_index].valid) return;
1586 
1587    SetAColorByteInfo(&pcb[xpm_color_index], &tgifColors[global_color_index]);
1588 }
1589 
ConvertPpmTrueToPpm6(ppm_data,ppm_data_size,ppm_data_compress,tmp_ppm6_fname,tmp_ppm6_sz)1590 int ConvertPpmTrueToPpm6(ppm_data, ppm_data_size, ppm_data_compress,
1591       tmp_ppm6_fname, tmp_ppm6_sz)
1592    char *ppm_data, *tmp_ppm6_fname;
1593    int ppm_data_size, ppm_data_compress, tmp_ppm6_sz;
1594 {
1595    *tmp_ppm6_fname = '\0';
1596    if (ppm_data_compress == PPM_JPEG_COMPRESS) {
1597       char jpeg_fname[MAXPATHLENGTH+1];
1598 
1599       if (!WriteBufIntoTmpFile(ppm_data, ppm_data_size, jpeg_fname,
1600             sizeof(jpeg_fname))) {
1601          return FALSE;
1602       }
1603       if (!ConvertJpegToPpm6(jpeg_fname, tmp_ppm6_fname, tmp_ppm6_sz)) {
1604          unlink(jpeg_fname);
1605          return FALSE;
1606       }
1607       unlink(jpeg_fname);
1608    } else if (ppm_data_compress == PPM_DATA_DEFLATED) {
1609       FILE *fp=NULL;
1610       int rc=0;
1611 
1612       if (MkTempFile(tmp_ppm6_fname, tmp_ppm6_sz, tmpDir, TOOL_NAME) == NULL) {
1613          return FALSE;
1614       }
1615       if ((fp=fopen(tmp_ppm6_fname, "w")) == NULL) {
1616          FailToOpenMessage(tmp_ppm6_fname, "w", NULL);
1617          return FALSE;
1618       }
1619       if (!DoInflate(ppm_data, ppm_data_size, fp, FALSE, &rc)) {
1620          fclose(fp);
1621          unlink(tmp_ppm6_fname);
1622          ZlibError(rc, FALSE);
1623          return FALSE;
1624       }
1625       fclose(fp);
1626    }
1627    return TRUE;
1628 }
1629 
1630 static
GetImagePixels(ObjPtr,xpm_ptr,pipi,pxtii,pcb)1631 int GetImagePixels(ObjPtr, xpm_ptr, pipi, pxtii, pcb)
1632    struct ObjRec *ObjPtr;
1633    struct XPmRec *xpm_ptr;
1634    ImagePixelInfo *pipi;
1635    XpmTransIndexInfo *pxtii;
1636    ColorBytes *pcb;
1637    /*
1638     * can only get here if the object has too many colors and colorDump
1639     * also, this object canont have transparent pixels
1640     */
1641 {
1642    int row=0, image_w=xpm_ptr->image_w, image_h=xpm_ptr->image_h;
1643    int chars_per_pixel=0, pixel_index=0;
1644    int ncolors=0;
1645    char *xpm_data=NULL, *color_char=NULL;
1646    Pixmap pixmap=(Pixmap)0, bitmap=(Pixmap)0;
1647    XImage *image=NULL, *bitmap_image=NULL;
1648 
1649    memset(pipi, 0, sizeof(ImagePixelInfo));
1650    if (image_h == 0) return FALSE;
1651 
1652    pixmap = xpm_ptr->pixmap;
1653    bitmap = xpm_ptr->bitmap;
1654 
1655    if ((!PRTGIF || cmdLineOpenDisplay) &&
1656          (image=xpm_ptr->image) == NULL) {
1657       if ((image=xpm_ptr->image=XGetImage(mainDisplay, pixmap, 0, 0,
1658             image_w, image_h, AllPlanes, ZPixmap)) == NULL) {
1659          Msg(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM));
1660          return FALSE;
1661       }
1662    }
1663    if ((!PRTGIF || cmdLineOpenDisplay) &&
1664          (bitmap_image=xpm_ptr->bitmap_image) == NULL) {
1665       if ((bitmap_image=xpm_ptr->bitmap_image=XGetImage(mainDisplay, bitmap,
1666             0, 0, image_w, image_h, 1, ZPixmap)) == NULL) {
1667          Msg(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM));
1668          return FALSE;
1669       }
1670    }
1671    pipi->image_pixels = (int**)malloc(image_h*sizeof(int*));
1672    pipi->transparent =
1673          (unsigned char **)malloc(image_h*sizeof(unsigned char *));
1674    if (pipi->image_pixels == NULL || pipi->transparent == NULL) {
1675       FailAllocMessage();
1676    }
1677    memset(pipi->image_pixels, 0, image_h*sizeof(int*));
1678    memset(pipi->transparent, 0, image_h*sizeof(unsigned char *));
1679    for (row=0; row < image_h; row++) {
1680       pipi->image_pixels[row] = (int*)malloc(image_w*sizeof(int));
1681       pipi->transparent[row] =
1682             (unsigned char *)malloc(image_w*sizeof(unsigned char));
1683       if (pipi->image_pixels[row] == NULL || pipi->transparent[row] == NULL) {
1684          FailAllocMessage();
1685       }
1686       memset(pipi->image_pixels[row], 0, image_w*sizeof(int));
1687       memset(pipi->transparent[row], 0, image_w*sizeof(unsigned char));
1688    }
1689    ncolors = xpm_ptr->ncolors;
1690 
1691    xpm_data = xpm_ptr->data;
1692    chars_per_pixel = xpm_ptr->chars_per_pixel;
1693    color_char = xpm_ptr->color_char;
1694 
1695    for (row=0; row < image_h; row++) {
1696       int col=0;
1697 
1698       for (col=0; col < image_w; col++) {
1699          int transparent_pixel=INVALID;
1700 #ifdef NOT_DEFINED
1701          float gray=(float)0;
1702          int value=0;
1703 #endif /* NOT_DEFINED */
1704 
1705          if (PRTGIF && !cmdLineOpenDisplay) {
1706             /* this works! */
1707             pixel_index = XPmLookUp(INVALID, chars_per_pixel,
1708                   &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
1709             SetAColorByteByXpmRGB(pcb, xpm_ptr, pixel_index, ncolors+3);
1710 
1711             if (!pxtii->has_transparent_pixel) {
1712                if (!colorDump) {
1713                   /* should never get here */
1714 #ifdef NOT_DEFINED
1715                   gray = 0.299*((float)xpm_ptr->red[pixel_index]/10000.0) +
1716                         0.587*((float)xpm_ptr->green[pixel_index]/10000.0) +
1717                         0.114*((float)xpm_ptr->blue[pixel_index]/10000.0);
1718                   value = gray*256;
1719                   pixel_index = ((value>255) ? 255 : ((value<0) ? 0 : value));
1720 #endif /* NOT_DEFINED */
1721                } else {
1722                   if (pxtii->has_transparent_pixel &&
1723                           pxtii->found_transparent_pixel &&
1724                           pxtii->transparent_pixel_index == pixel_index) {
1725                      pipi->transparent[row][col] = TRUE;
1726                   }
1727                }
1728             } else {
1729                /* should never get here */
1730                if (pxtii->has_transparent_pixel &&
1731                        pxtii->found_transparent_pixel &&
1732                        pxtii->transparent_pixel_index == pixel_index) {
1733                   pipi->transparent[row][col] = TRUE;
1734                }
1735             }
1736          } else {
1737             if (colorDump || pxtii->has_transparent_pixel) {
1738                if (!colorDisplay && xpm_ptr->red != NULL) {
1739                   pixel_index = XPmLookUp(INVALID, chars_per_pixel,
1740                         &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
1741                   SetAColorByteByXpmRGB(pcb, xpm_ptr, pixel_index, ncolors+3);
1742                } else if (XGetPixel(bitmap_image,col,row) != 0) {
1743                   /* this works! */
1744                   int pixel=XGetPixel(image,col,row), global_color_index=(-1);
1745 
1746                   pixel_index = XPmLookUp(pixel, INVALID, NULL, NULL);
1747                   if (HashLookUpInt(&gColorsHashForPrinting,
1748                         (char*)(&pixel), sizeof(int), &global_color_index)) {
1749                      SetAColorByteByMaxRGB(pcb, pixel_index, global_color_index,
1750                            ncolors+3);
1751                   } else {
1752                   }
1753                } else {
1754                   /* transparent pixel */
1755                   pixel_index = XPmLookUp((-1), INVALID, NULL, NULL);
1756                   transparent_pixel = pixel_index;
1757                }
1758                if (pxtii->has_transparent_pixel &&
1759                        pxtii->found_transparent_pixel &&
1760                        pxtii->transparent_pixel_index == pixel_index) {
1761                   pipi->transparent[row][col] = TRUE;
1762                }
1763             } else {
1764                /* should never get here */
1765 #ifdef NOT_DEFINED
1766                if (!colorDisplay && xpm_ptr->red != NULL) {
1767                   pixel_index = XPmLookUp(INVALID, chars_per_pixel,
1768                         &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
1769                   gray = 0.299*((float)xpm_ptr->red[pixel_index]/10000.0) +
1770                         0.587*((float)xpm_ptr->green[pixel_index]/10000.0) +
1771                         0.114*((float)xpm_ptr->blue[pixel_index]/10000.0);
1772                } else {
1773                   int cur_pixel=0, found_index=0;
1774 
1775                   if (XGetPixel(bitmap_image, col, row) != 0) {
1776                      cur_pixel = XGetPixel(image, col, row);
1777                   } else {
1778                      found_index = ObjPtr->color;
1779                      cur_pixel = (-1);
1780                   }
1781                   if (cur_pixel != (-1)) {
1782                      int i=0;
1783 
1784                      for (i=0; i < maxColors; i++) {
1785                         if (colorPixels[i] == cur_pixel) {
1786                            found_index = i;
1787                            break;
1788                         }
1789                      }
1790                   }
1791                   gray = 0.299*((float)tgifColors[found_index].red/maxRGB) +
1792                         0.587*((float)tgifColors[found_index].green/maxRGB) +
1793                         0.114*((float)tgifColors[found_index].blue/maxRGB);
1794                   SetAColorByteByMaxRGB(pcb, pixel_index, ncolors+3);
1795                }
1796                value = gray*256;
1797                pixel_index = ((value>255) ? 255 : ((value<0) ? 0 : value));
1798 #endif /* NOT_DEFINED */
1799             }
1800          }
1801          pipi->image_pixels[row][col] = pixel_index;
1802       }
1803    }
1804    return TRUE;
1805 }
1806 
1807 static
PrepareColorsForConvertObjToPpm6(xpm_ptr,pxtii)1808 int PrepareColorsForConvertObjToPpm6(xpm_ptr, pxtii)
1809    struct XPmRec *xpm_ptr;
1810    XpmTransIndexInfo *pxtii;
1811 {
1812    int index=0, ncolors=xpm_ptr->ncolors;
1813    int chars_per_pixel=xpm_ptr->chars_per_pixel;
1814    char *color_char=xpm_ptr->color_char;
1815    int *pixels=xpm_ptr->pixels;
1816 
1817    if (colorDump) {
1818       if ((PRTGIF && !cmdLineOpenDisplay) ||
1819             (!colorDisplay && xpm_ptr->red != NULL)) {
1820          if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel,
1821                color_char, pxtii)) {
1822             return FALSE;
1823          }
1824          for (index=0; index < ncolors; index++) {
1825             if (xpm_ptr->red[index] == (-1)) {
1826                if (pxtii->has_transparent_pixel) {
1827                   if (pxtii->found_transparent_pixel) {
1828 #ifdef _TGIF_DBG /* debug, do not translate */
1829                      TgAssert(FALSE,
1830                            "Found transparent pixel again in PrepareColorsForConvertObjToPpm6()",
1831                            NULL);
1832 #endif /* _TGIF_DBG */
1833                   } else {
1834                      pxtii->found_transparent_pixel = TRUE;
1835                      pxtii->transparent_pixel_index = index;
1836                   }
1837                }
1838             }
1839          }
1840       } else {
1841          /* interactive printing */
1842          pxtii->dump_index_to_color_index =
1843                (int*)malloc((maxColors+3)*sizeof(int));
1844          if (pxtii->dump_index_to_color_index == NULL) FailAllocMessage();
1845          for (index=0; index < maxColors+3; index++) {
1846             pxtii->dump_index_to_color_index[index] = INVALID;
1847          }
1848          if (!BuildXPmBuckets(ncolors, pixels,
1849                pxtii->dump_index_to_color_index, INVALID, NULL, pxtii)) {
1850             return FALSE;
1851          }
1852       }
1853    } else if ((PRTGIF && !cmdLineOpenDisplay) ||
1854          (!colorDisplay && xpm_ptr->red != NULL)) {
1855       if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel, color_char,
1856             pxtii)) {
1857          return FALSE;
1858       }
1859    } else if (pxtii->has_transparent_pixel) {
1860       /*
1861        * should never get here since such object is not suppose to have
1862        *         transparent pixels!
1863        */
1864       pxtii->dump_index_to_color_index =
1865             (int*)malloc((maxColors+3)*sizeof(int));
1866       if (pxtii->dump_index_to_color_index == NULL) FailAllocMessage();
1867       for (index=0; index < maxColors+3; index++) {
1868          pxtii->dump_index_to_color_index[index] = INVALID;
1869       }
1870       if (!BuildXPmBuckets(ncolors, pixels, pxtii->dump_index_to_color_index,
1871             INVALID, NULL, pxtii)) {
1872          return FALSE;
1873       }
1874    }
1875    return TRUE;
1876 }
1877 
1878 static
ConvertObjToPpm6(ObjPtr,xpm_ptr,psz_ppm6_path,ppm6_path_sz,pxtii)1879 int ConvertObjToPpm6(ObjPtr, xpm_ptr, psz_ppm6_path, ppm6_path_sz, pxtii)
1880    struct ObjRec *ObjPtr;
1881    struct XPmRec *xpm_ptr;
1882    char *psz_ppm6_path;
1883    int ppm6_path_sz;
1884    XpmTransIndexInfo *pxtii;
1885 {
1886    FILE *ppm_fp=NULL;
1887    int row=0, image_w=xpm_ptr->image_w, image_h=xpm_ptr->image_h, pixel_index=0;
1888    int ncolors=xpm_ptr->ncolors;
1889    XColor *saved_tgif_colors=tgifColors;
1890    ColorBytes *pcb=(ColorBytes*)malloc((ncolors+3)*sizeof(ColorBytes));
1891    ImagePixelInfo ipi;
1892 
1893    if (!PrepareColorsForConvertObjToPpm6(xpm_ptr, pxtii)) return FALSE;
1894 
1895    /*
1896     * pcb maps an object color index to an RGB value
1897     */
1898    if (pcb == NULL) FailAllocMessage();
1899    memset(pcb, 0, (ncolors+3)*sizeof(ColorBytes));
1900    if (printUsingRequestedColor) tgifColors = tgifRequestedColors;
1901 
1902    if (MkTempFile(psz_ppm6_path, ppm6_path_sz, tmpDir, TOOL_NAME) == NULL) {
1903       free(pcb);
1904       if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
1905       return FALSE;
1906    }
1907    if ((ppm_fp=fopen(psz_ppm6_path, "w")) == NULL) {
1908       free(pcb);
1909       if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
1910       return FailToOpenMessage(psz_ppm6_path, "w", NULL);
1911    }
1912    memset(&ipi, 0, sizeof(ImagePixelInfo));
1913 
1914    if (!GetImagePixels(ObjPtr, xpm_ptr, &ipi, pxtii, pcb)) {
1915       free(pcb);
1916       if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
1917       return FALSE;
1918    }
1919    writeFileFailed = FALSE;
1920 
1921    fprintf(ppm_fp, "P6\n%1d %1d\n255\n", image_w, image_h);
1922    for (row=0; row < image_h; row++) {
1923       int col=0;
1924 
1925       for (col=0; col < image_w; col++) {
1926          pixel_index = ipi.image_pixels[row][col];
1927 
1928          if (fprintf(ppm_fp, "%c%c%c", pcb[pixel_index].r, pcb[pixel_index].g,
1929                pcb[pixel_index].b) == EOF) {
1930             writeFileFailed = TRUE;
1931          }
1932       }
1933    }
1934    fclose(ppm_fp);
1935    FreeImagePixels(&ipi);
1936 
1937    if (writeFileFailed) {
1938       FailToWriteFileMessage(psz_ppm6_path);
1939    }
1940    if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
1941    free(pcb);
1942 
1943    return TRUE;
1944 }
1945 
DumpXPmObj(FP,ObjPtr)1946 void DumpXPmObj(FP, ObjPtr)
1947    FILE *FP;
1948    struct ObjRec *ObjPtr;
1949 {
1950    int row=0, i=0, index=0, col=0, too_many_colors=FALSE;
1951    int ltx=0, lty=0, rbx=0, rby=0, w=0, h=0, image_w=0, image_h=0;
1952    int ncolors=0, *pixels=NULL, flip=0, orig_x=0, orig_y=0;
1953    int cur_pixel=0, chars_per_pixel=0, x=0, y=0, found_index=0, pixel_index=0;
1954    int has_transparent_pixel=FALSE, is_linked_jpeg=IsLinkedJpegObj(ObjPtr);
1955    unsigned int trans_color_pixel_r=0, trans_color_pixel_g=0, trans_color_pixel_b=0;
1956    int is_ppm_true=FALSE;
1957    char *xpm_data=NULL, *color_char=NULL;
1958    Pixmap pixmap=(Pixmap)0, bitmap=(Pixmap)0;
1959    XImage *image=NULL, *bitmap_image=NULL;
1960    struct XPmRec *xpm_ptr=NULL;
1961    struct MtrxRec mtrx;
1962    XpmTransIndexInfo xtii;
1963 
1964    memset(&mtrx, 0, sizeof(struct MtrxRec));
1965    memset(&xtii, 0, sizeof(XpmTransIndexInfo));
1966 
1967    ltx = ObjPtr->obbox.ltx;
1968    lty = ObjPtr->obbox.lty;
1969    rbx = ObjPtr->obbox.rbx;
1970    rby = ObjPtr->obbox.rby;
1971 
1972    xpm_ptr = ObjPtr->detail.xpm;
1973 
1974    pixmap = xpm_ptr->pixmap;
1975    bitmap = xpm_ptr->bitmap;
1976    pixels = xpm_ptr->pixels;
1977    ncolors = xpm_ptr->ncolors;
1978    flip = xpm_ptr->flip;
1979    image_w = xpm_ptr->image_w;
1980    image_h = xpm_ptr->image_h;
1981 
1982    w = rbx - ltx;
1983    h = rby - lty;
1984 
1985    is_ppm_true = IsPpmTrueObj(xpm_ptr->real_type, xpm_ptr->ppm_data_compress,
1986          xpm_ptr->ppm_data);
1987 
1988    if ((!PRTGIF || cmdLineOpenDisplay) &&
1989          (image=xpm_ptr->image) == NULL) {
1990       if ((image=xpm_ptr->image=XGetImage(mainDisplay, pixmap, 0, 0,
1991             image_w, image_h, AllPlanes, ZPixmap)) == NULL) {
1992          Msg(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM));
1993          return;
1994       }
1995    }
1996    if ((!PRTGIF || cmdLineOpenDisplay) &&
1997          (bitmap_image=xpm_ptr->bitmap_image) == NULL) {
1998       if ((bitmap_image=xpm_ptr->bitmap_image=XGetImage(mainDisplay, bitmap,
1999             0, 0, image_w, image_h, 1, ZPixmap)) == NULL) {
2000          Msg(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM));
2001          return;
2002       }
2003    }
2004    mtrx.image_w = (float)image_w; mtrx.image_h = (float)image_h;
2005    mtrx.w = (float)w; mtrx.h = (float)h;
2006    mtrx.rotate = ROTATE0; mtrx.flip = flip;
2007 
2008    CalcTransform(&mtrx);
2009 
2010    orig_x = (mtrx.transformed_w >= 0.0) ? ltx : ltx+w;
2011    orig_y = (mtrx.transformed_h >= 0.0) ? lty : lty+h;
2012 
2013    fprintf(FP, "%% XPM\n");
2014 
2015    xpm_data = xpm_ptr->data;
2016    chars_per_pixel = xpm_ptr->chars_per_pixel;
2017    color_char = xpm_ptr->color_char;
2018 
2019    if (PRTGIF && !cmdLineOpenDisplay && fileVersion < 25) {
2020       /* can't print color with PRTGIF, treat it like a bitmap */
2021       PrTgifDumpOldXPmObj(FP, ObjPtr, &mtrx);
2022       return;
2023    }
2024    if ((PRTGIF && !cmdLineOpenDisplay) ||
2025          (!colorDisplay && xpm_ptr->red != NULL)) {
2026       if (xpm_ptr->real_type == PPM_TRUE && xpm_ptr->has_transparent_color) {
2027          has_transparent_pixel = TRUE;
2028          trans_color_pixel_r = (unsigned int)xpm_ptr->transparent_color[0];
2029          trans_color_pixel_g = (unsigned int)xpm_ptr->transparent_color[1];
2030          trans_color_pixel_b = (unsigned int)xpm_ptr->transparent_color[2];
2031       } else {
2032          int *red_ptr=xpm_ptr->red;
2033 
2034          if (ncolors > 0xff) {
2035             too_many_colors = TRUE;
2036          }
2037          for (index = 0; index < ncolors; index++) {
2038             if (red_ptr[index] == (-1)) {
2039                has_transparent_pixel = TRUE;
2040                break;
2041             }
2042          }
2043       }
2044    } else {
2045       if (fullTrueColorMode && xpm_ptr->real_type == PPM_TRUE &&
2046             xpm_ptr->has_transparent_color) {
2047          has_transparent_pixel = TRUE;
2048          trans_color_pixel_r = (unsigned int)xpm_ptr->transparent_color[0];
2049          trans_color_pixel_g = (unsigned int)xpm_ptr->transparent_color[1];
2050          trans_color_pixel_b = (unsigned int)xpm_ptr->transparent_color[2];
2051       } else {
2052          if (ncolors > 0xff) {
2053             too_many_colors = TRUE;
2054          }
2055          for (index = 0; index < ncolors; index++) {
2056             if (pixels[index] == (-1)) {
2057                has_transparent_pixel = TRUE;
2058                break;
2059             }
2060          }
2061       }
2062    }
2063    if (has_transparent_pixel) {
2064       xtii.has_transparent_pixel = TRUE;
2065       if (((PRTGIF && !cmdLineOpenDisplay) || fullTrueColorMode) &&
2066             xpm_ptr->real_type == PPM_TRUE && xpm_ptr->has_transparent_color) {
2067       } else if (too_many_colors && colorDump) {
2068          sprintf(gszMsgBox, TgLoadString(STID_TRANS_XPM_TOO_MANY_COLORS_SKP),
2069                ncolors);
2070          if (PRTGIF) {
2071             fprintf(stderr, "%s\n", gszMsgBox);
2072          } else {
2073             Msg(gszMsgBox);
2074          }
2075          xpmHasTooManyColorsForPrinting = TRUE;
2076          return;
2077       }
2078    }
2079    x = (mtrx.transformed_w >= 0.0) ? ltx : ltx+w;
2080    y = (mtrx.transformed_h >= 0.0) ? lty : lty+h;
2081 
2082    fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
2083    if (is_linked_jpeg) {
2084       if (!ConvertJpegToPpm6(xpm_ptr->filename, xpm_ptr->tmp_ppm6_fname,
2085             sizeof(xpm_ptr->tmp_ppm6_fname))) {
2086          return;
2087       }
2088    } else if (is_ppm_true) {
2089       if (!ConvertPpmTrueToPpm6(xpm_ptr->ppm_data, xpm_ptr->ppm_data_size,
2090             xpm_ptr->ppm_data_compress, xpm_ptr->tmp_ppm6_fname,
2091             sizeof(xpm_ptr->tmp_ppm6_fname))) {
2092          return;
2093       }
2094    } else if (too_many_colors && colorDump) {
2095       if (!ConvertObjToPpm6(ObjPtr, xpm_ptr, xpm_ptr->tmp_ppm6_fname,
2096             sizeof(xpm_ptr->tmp_ppm6_fname), &xtii)) {
2097          return;
2098       }
2099    } else if (colorDump) {
2100       fprintf(FP, "   3 %1d %s %s tgifsetpixels\n", ncolors,
2101             gPsCmd[PS_MUL], gPsCmd[PS_ARRAY]);
2102 
2103       if ((PRTGIF && !cmdLineOpenDisplay) ||
2104             (!colorDisplay && xpm_ptr->red != NULL)) {
2105          if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel,
2106                color_char, &xtii)) {
2107             return;
2108          }
2109          for (index = 0; index < ncolors; index++) {
2110             if (xpm_ptr->red[index] == (-1)) {
2111                fprintf(FP, "%s%3d [ -1.00 -1.00 -1.00 ] tgifsetpix",
2112                      ((index & 0x1) ? "" : "   "), index*3);
2113             } else {
2114                fprintf(FP, "%s%3d [ %.3f %.3f %.3f ] tgifsetpix",
2115                      ((index & 0x1) ? "" : "   "), index*3,
2116                      ((float)xpm_ptr->red[index])/((float)10000.0),
2117                      ((float)xpm_ptr->green[index])/((float)10000.0),
2118                      ((float)xpm_ptr->blue[index])/((float)10000.0));
2119             }
2120             fprintf(FP, "%s", ((index & 0x1) ? "\n" : " "));
2121          }
2122       } else {
2123          if (!BuildXPmBuckets(ncolors, pixels, NULL, INVALID, NULL, &xtii)) {
2124             return;
2125          }
2126          for (index = 0; index < ncolors; index++) {
2127             cur_pixel = pixels[index];
2128             if (cur_pixel != (-1)) {
2129                found_index = ObjPtr->color;
2130                for (i = 0; i < maxColors; i++) {
2131                   if (colorPixels[i] == cur_pixel) {
2132                      found_index = i;
2133                      break;
2134                   }
2135                }
2136                fprintf(FP, "%s%3d [ %.3f %.3f %.3f ] tgifsetpix",
2137                      ((index & 0x1) ? "" : "   "), index*3,
2138                      ((float)tgifColors[found_index].red/maxRGB),
2139                      ((float)tgifColors[found_index].green/maxRGB),
2140                      ((float)tgifColors[found_index].blue/maxRGB));
2141             } else {
2142                fprintf(FP, "%s%3d [ -1.00 -1.00 -1.00 ] tgifsetpix",
2143                      ((index & 0x1) ? "" : "   "), index*3);
2144             }
2145             fprintf(FP, "%s", ((index & 0x1) ? "\n" : " "));
2146          }
2147       }
2148       if (ncolors & 0x1) fprintf(FP, "\n");
2149    } else if ((PRTGIF && !cmdLineOpenDisplay) ||
2150          (!colorDisplay && xpm_ptr->red != NULL)) {
2151       if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel, color_char,
2152             &xtii)) {
2153          return;
2154       }
2155       if (has_transparent_pixel) {
2156          fprintf(FP, "   3 %1d %s %s tgifsetpixels\n", ncolors,
2157                gPsCmd[PS_MUL], gPsCmd[PS_ARRAY]);
2158 
2159          for (index = 0; index < ncolors; index++) {
2160             if (xpm_ptr->red[index] == (-1)) {
2161                fprintf(FP, "%s%3d [ -1.00 -1.00 -1.00 ] tgifsetpix",
2162                      ((index & 0x1) ? "" : "   "), index*3);
2163             } else {
2164                float gray;
2165 
2166                gray = 0.299*((float)xpm_ptr->red[index]/10000.0) +
2167                      0.587*((float)xpm_ptr->green[index]/10000.0) +
2168                      0.114*((float)xpm_ptr->blue[index]/10000.0);
2169                fprintf(FP, "%s%3d [ %.3f %.3f %.3f ] tgifsetpix",
2170                      ((index & 0x1) ? "" : "   "), index*3,
2171                      gray, gray, gray);
2172             }
2173             fprintf(FP, "%s", ((index & 0x1) ? "\n" : " "));
2174          }
2175       }
2176    } else if (has_transparent_pixel) {
2177       if (!BuildXPmBuckets(ncolors, pixels, NULL, INVALID, NULL, &xtii)) {
2178          return;
2179       }
2180       fprintf(FP, "   3 %1d %s %s tgifsetpixels\n", ncolors,
2181             gPsCmd[PS_MUL], gPsCmd[PS_ARRAY]);
2182 
2183       for (index = 0; index < ncolors; index++) {
2184          cur_pixel = pixels[index];
2185          if (cur_pixel != (-1)) {
2186             float gray;
2187 
2188             found_index = ObjPtr->color;
2189             for (i = 0; i < maxColors; i++) {
2190                if (colorPixels[i] == cur_pixel) {
2191                   found_index = i;
2192                   break;
2193                }
2194             }
2195             gray = 0.299*((float)tgifColors[found_index].red)/((float)maxRGB) +
2196                   0.587*((float)tgifColors[found_index].green)/((float)maxRGB) +
2197                   0.114*((float)tgifColors[found_index].blue)/((float)maxRGB);
2198             fprintf(FP, "%s%3d [ %.3f %.3f %.3f ] tgifsetpix",
2199                   ((index & 0x1) ? "" : "   "), index*3,
2200                   gray, gray, gray);
2201          } else {
2202             fprintf(FP, "%s%3d [ -1.00 -1.00 -1.00 ] tgifsetpix",
2203                   ((index & 0x1) ? "" : "   "), index*3);
2204          }
2205          fprintf(FP, "%s", ((index & 0x1) ? "\n" : " "));
2206       }
2207    } else {
2208       /* grayscale */
2209    }
2210    if (((PRTGIF && !cmdLineOpenDisplay) || fullTrueColorMode) &&
2211          xpm_ptr->real_type == PPM_TRUE && xpm_ptr->has_transparent_color) {
2212       fprintf(FP, "   %1d %1d %1d tgifsetppmtruetranspix\n",
2213             trans_color_pixel_r, trans_color_pixel_g, trans_color_pixel_b);
2214    }
2215    if (ObjPtr->ctm == NULL) {
2216       fprintf(FP, "   %1d %1d %s %.3f %.3f %s %1d %s\n", x, y,
2217             gPsCmd[PS_TRANSLATE], mtrx.dump_h_scale, mtrx.dump_v_scale,
2218             gPsCmd[PS_SCALE], mtrx.degree, gPsCmd[PS_ROTATE]);
2219    } else {
2220       float m[6];
2221 
2222       m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
2223       m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
2224       m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
2225       m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
2226       fprintf(FP, "   %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
2227             gPsCmd[PS_TRANSLATE]);
2228       fprintf(FP, "   [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
2229             m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
2230             ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
2231    }
2232    fprintf(FP, "   %1d %1d 8\n   [1 0 0 1 0 0]\n", image_w, image_h);
2233 
2234    if (preDumpSetup) {
2235       PSUseColorImage();
2236       hasReadHexString = TRUE;
2237    }
2238    if (is_linked_jpeg || is_ppm_true || (too_many_colors && colorDump)) {
2239       if (((PRTGIF && !cmdLineOpenDisplay) || fullTrueColorMode) &&
2240             xpm_ptr->real_type == PPM_TRUE && xpm_ptr->has_transparent_color) {
2241          fprintf(FP, "   { }\n");
2242          fprintf(FP, "   false 3 tgiftransppmtruecolorimage\n   ");
2243       } else {
2244          fprintf(FP, "   {currentfile\n");
2245          fprintf(FP, "    tgifbwpicstr readhexstring pop}\n");
2246          fprintf(FP, "   false 3 colorimage\n   ");
2247       }
2248    } else if (colorDump) {
2249       fprintf(FP, "   {currentfile\n");
2250       fprintf(FP, "    tgifbwpicstr readhexstring pop 0 get tgifcolorspot}\n");
2251       if (has_transparent_pixel) {
2252          fprintf(FP, "   false 3 tgiftranscolorimage\n   ");
2253       } else {
2254          fprintf(FP, "   false 3 colorimage\n   ");
2255       }
2256    } else {
2257       /* grayscale */
2258       if (has_transparent_pixel) {
2259          fprintf(FP, "   {currentfile\n");
2260          fprintf(FP, "    %s}\n",
2261                "tgifbwpicstr readhexstring pop 0 get tgifcolorspot");
2262          fprintf(FP, "   false 3 tgiftranscolorimage\n   ");
2263       } else {
2264          fprintf(FP, "   {currentfile\n");
2265          fprintf(FP, "    tgifbwpicstr readhexstring pop}\n");
2266          fprintf(FP, "   %s\n   ", gPsCmd[PS_IMAGE]);
2267       }
2268    }
2269    /*
2270     * Transparent_pixel is dealt with a little bit differently here.
2271     * When generating colors for a particular pixel, if the pixel is
2272     *       suppose to be transparent, the color components are all
2273     *       (-1).  The postscript code will take care of it and not
2274     *       put down any ink.
2275     * Whether we are doing colorDump or not doesn't matter here.
2276     */
2277    if (is_linked_jpeg || is_ppm_true || (too_many_colors && colorDump)) {
2278       DumpPpm6File(FP, image_w, image_h, xpm_ptr->tmp_ppm6_fname);
2279       unlink(xpm_ptr->tmp_ppm6_fname);
2280       *xpm_ptr->tmp_ppm6_fname = '\0';
2281       if (xtii.dump_index_to_color_index != NULL) {
2282          free(xtii.dump_index_to_color_index);
2283       }
2284    } else if (PRTGIF && !cmdLineOpenDisplay) {
2285       for (row=0; row < image_h; row++) {
2286          for (col=0; col < image_w; col++) {
2287             float gray;
2288             int value;
2289 
2290             pixel_index = XPmLookUp(INVALID, chars_per_pixel,
2291                   &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
2292 
2293             if (!has_transparent_pixel) {
2294                if (!colorDump) {
2295                   gray = 0.299*((float)xpm_ptr->red[pixel_index]/10000.0) +
2296                         0.587*((float)xpm_ptr->green[pixel_index]/10000.0) +
2297                         0.114*((float)xpm_ptr->blue[pixel_index]/10000.0);
2298                   value = gray*256;
2299                   pixel_index = ((value>255) ? 255 : ((value<0) ? 0 : value));
2300                }
2301             }
2302             fprintf(FP, "%c", hexValue[(pixel_index>>4)&0x0f]);
2303             fprintf(FP, "%c", hexValue[pixel_index&0x0f]);
2304             if (col%36 == 35) fprintf(FP, "\n   ");
2305          }
2306          if (col%36 != 0) fprintf(FP, "\n");
2307          if (row != image_h-1) fprintf(FP, "   ");
2308       }
2309    } else {
2310       for (row=0; row < image_h; row++) {
2311          for (col=0; col < image_w; col++) {
2312             if (colorDump || has_transparent_pixel) {
2313                if (!colorDisplay && xpm_ptr->red != NULL) {
2314                   pixel_index = XPmLookUp(INVALID, chars_per_pixel,
2315                         &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
2316                } else if (XGetPixel(bitmap_image,col,row) != 0) {
2317                   pixel_index = XPmLookUp(XGetPixel(image,col,row), INVALID,
2318                         NULL, NULL);
2319                } else {
2320                   pixel_index = XPmLookUp((-1), INVALID, NULL, NULL);
2321                }
2322             } else {
2323                float gray;
2324                int value;
2325 
2326                if (!colorDisplay && xpm_ptr->red != NULL) {
2327                   pixel_index = XPmLookUp(INVALID, chars_per_pixel,
2328                         &(xpm_data[(row*image_w+col)*chars_per_pixel]), NULL);
2329                   gray = 0.299*((float)xpm_ptr->red[pixel_index]/10000.0) +
2330                         0.587*((float)xpm_ptr->green[pixel_index]/10000.0) +
2331                         0.114*((float)xpm_ptr->blue[pixel_index]/10000.0);
2332                } else {
2333                   if (XGetPixel(bitmap_image, col, row) != 0) {
2334                      cur_pixel = XGetPixel(image, col, row);
2335                   } else {
2336                      found_index = ObjPtr->color;
2337                      cur_pixel = (-1);
2338                   }
2339                   if (cur_pixel != (-1)) {
2340                      for (i = 0; i < maxColors; i++) {
2341                         if (colorPixels[i] == cur_pixel) {
2342                            found_index = i;
2343                            break;
2344                         }
2345                      }
2346                   }
2347                   gray = 0.299*((float)tgifColors[found_index].red/maxRGB) +
2348                         0.587*((float)tgifColors[found_index].green/maxRGB) +
2349                         0.114*((float)tgifColors[found_index].blue/maxRGB);
2350                }
2351                value = gray*256;
2352                pixel_index = ((value>255) ? 255 : ((value<0) ? 0 : value));
2353             }
2354             fprintf(FP, "%c", hexValue[(pixel_index>>4)&0x0f]);
2355             fprintf(FP, "%c", hexValue[pixel_index&0x0f]);
2356             if (col%36 == 35) {
2357                fprintf(FP, "\n%s",
2358                      (col==image_w-1 && row==image_h-1) ? "" : "   ");
2359             }
2360          }
2361          if (col%36 != 0) fprintf(FP, "\n");
2362          if (row != image_h-1 && (col%36) != 0) fprintf(FP, "   ");
2363       }
2364    }
2365    fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
2366    fprintf(FP, "\n");
2367 }
2368 
NeedsToCacheXPmObj(ObjPtr)2369 int NeedsToCacheXPmObj(ObjPtr)
2370    struct ObjRec *ObjPtr;
2371 {
2372    register struct XPmRec *xpm_ptr=ObjPtr->detail.xpm;
2373    int w, h;
2374 
2375    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
2376    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
2377 
2378    return (ObjPtr->ctm != NULL ||
2379          zoomScale != 0 || xpm_ptr->image_w != w || xpm_ptr->image_h != h ||
2380          xpm_ptr->flip != 0);
2381 }
2382 
2383 static
DrawHiddenXPm(win,ctm,vs,x,y,w,h,s)2384 void DrawHiddenXPm(win, ctm, vs, x, y, w, h, s)
2385    Window win;
2386    struct XfrmMtrxRec *ctm;
2387    XPoint *vs;
2388    int x, y, w, h;
2389    char *s;
2390 {
2391    int str_w, len, sx, sy;
2392    XGCValues values;
2393 
2394    values.foreground = GetDrawingBgPixel(INVALID, INVALID);
2395    values.function = GXcopy;;
2396    values.fill_style = FillSolid;
2397 #ifdef NO_THIN_LINE
2398    values.line_width = 1;
2399 #else
2400    values.line_width = 0;
2401 #endif
2402    values.font = rulerFontPtr->fid;
2403    values.line_style = LineSolid;
2404 
2405    XChangeGC(mainDisplay, drawGC,
2406          GCForeground | GCFunction | GCFillStyle | GCLineWidth | GCFont |
2407          GCLineStyle, &values);
2408    if (ctm != NULL) {
2409       XFillPolygon(mainDisplay, win, drawGC, vs, 5, Convex, CoordModeOrigin);
2410    } else {
2411       XFillRectangle(mainDisplay, win, drawGC, x, y, w, h);
2412    }
2413    XSetForeground(mainDisplay, drawGC, GetDrawingFgPixel(INVALID, INVALID));
2414    if (ctm != NULL) {
2415       XDrawLines(mainDisplay, win, drawGC, vs, 5, CoordModeOrigin);
2416    } else {
2417       XDrawRectangle(mainDisplay, win, drawGC, x, y, w, h);
2418    }
2419    XSetForeground(mainDisplay, drawGC, colorPixels[colorIndex]);
2420 
2421    len = strlen(s);
2422    str_w = rulerFontWidth*len;
2423    if (str_w < w && rulerFontHeight < h) {
2424       sx = x + ((w-str_w)>>1);
2425       sy = y + ((h-rulerFontHeight)>>1);
2426       XDrawString(mainDisplay, win, drawGC, sx, sy+rulerFontAsc, s, len);
2427    }
2428    XSetFont(mainDisplay, drawGC, canvasFontPtr->fid);
2429 }
2430 
RecolorXPmObj(obj_ptr,color_index)2431 void RecolorXPmObj(obj_ptr, color_index)
2432    struct ObjRec *obj_ptr;
2433    int color_index;
2434 {
2435    register int c, r;
2436    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
2437    int image_w=xpm_ptr->image_w, image_h=xpm_ptr->image_h;
2438    Pixmap pixmap=None;
2439    XImage *image=NULL;
2440 
2441    xpm_ptr->cached_color = (-1);
2442    if (xpm_ptr->bitmap_image == NULL) {
2443       xpm_ptr->bitmap_image = XGetImage(mainDisplay, xpm_ptr->bitmap,
2444             0, 0, image_w, image_h, 1, ZPixmap);
2445       if (xpm_ptr->bitmap_image == NULL) return;
2446    }
2447    if (xpm_ptr->image == NULL) {
2448       xpm_ptr->image = XGetImage(mainDisplay, xpm_ptr->pixmap,
2449             0, 0, image_w, image_h, AllPlanes, ZPixmap);
2450       if (xpm_ptr->image == NULL) return;
2451    }
2452    pixmap = XCreatePixmap(mainDisplay, dummyPixmap, image_w, image_h,
2453          mainDepth);
2454    if (pixmap == None) return;
2455    XFillRectangle(mainDisplay, pixmap, xpmGC, 0, 0, image_w, image_h);
2456    image = XGetImage(mainDisplay, pixmap, 0, 0, image_w, image_h,
2457          AllPlanes, ZPixmap);
2458    if (image == NULL) {
2459       XFreePixmap(mainDisplay, pixmap);
2460       return;
2461    }
2462    for (r=0; r < image_h; r++) {
2463       for (c=0; c < image_w; c++) {
2464          if (XGetPixel(xpm_ptr->bitmap_image, c, r) != 0) {
2465             XPutPixel(image, c, r, XGetPixel(xpm_ptr->image, c, r));
2466          } else {
2467             XPutPixel(image, c, r, colorPixels[color_index]);
2468          }
2469       }
2470    }
2471    XPutImage(mainDisplay, pixmap, xpmGC, image, 0, 0, 0, 0, image_w, image_h);
2472    XFreePixmap(mainDisplay, xpm_ptr->pixmap);
2473    XDestroyImage(xpm_ptr->image);
2474    xpm_ptr->pixmap = pixmap;
2475    xpm_ptr->image = image;
2476    if (obj_ptr->ctm != NULL) {
2477       MakeCachedPixmap(obj_ptr);
2478    }
2479 }
2480 
DrawXPmObj(win,XOff,YOff,ObjPtr)2481 void DrawXPmObj(win, XOff, YOff, ObjPtr)
2482    Window win;
2483    int XOff, YOff;
2484    struct ObjRec *ObjPtr;
2485 {
2486    int ltx, lty, rbx, rby, w, h, scr_w, scr_h, real_x_off, real_y_off;
2487    char s[80];
2488    struct XPmRec *xpm_ptr=ObjPtr->detail.xpm;
2489    XGCValues values;
2490 
2491    if (userDisableRedraw) return;
2492 
2493    if (ObjPtr->prev != NULL && ObjPtr->prev->type == OBJ_XPM &&
2494          Inside(ObjPtr->obbox, ObjPtr->prev->obbox) &&
2495          ObjPtr->prev->detail.xpm->bitmap == None) {
2496       return;
2497    }
2498    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
2499    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
2500 
2501    real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
2502    real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
2503    ltx = ZOOMED_SIZE(ObjPtr->obbox.ltx - real_x_off);
2504    lty = ZOOMED_SIZE(ObjPtr->obbox.lty - real_y_off);
2505    rbx = ZOOMED_SIZE(ObjPtr->obbox.rbx - real_x_off);
2506    rby = ZOOMED_SIZE(ObjPtr->obbox.rby - real_y_off);
2507    scr_w = rbx - ltx;
2508    scr_h = rby - lty;
2509 
2510    if (!mapShown) {
2511       sprintf(s, "(%1dx%1d)", xpm_ptr->image_w, xpm_ptr->image_h);
2512       DrawHiddenXPm(win, ObjPtr->ctm, ObjPtr->rotated_obbox,
2513             ltx, lty, scr_w, scr_h, s);
2514       return;
2515    }
2516    if (NeedsToCacheXPmObj(ObjPtr) &&
2517          (ObjPtr->ctm == NULL ||
2518          (ObjPtr->ctm != NULL && (xpm_ptr->cached_pixmap == None ||
2519          xpm_ptr->clip_mask == None)))) {
2520       MakeCachedPixmap(ObjPtr);
2521    }
2522    XSetFunction(mainDisplay, drawGC, GXcopy);
2523    if (ObjPtr->ctm==NULL && zoomScale==0 &&
2524          xpm_ptr->flip==0 && xpm_ptr->image_w==w && xpm_ptr->image_h==h) {
2525       if (xpm_ptr->bitmap == None) {
2526          XCopyArea(mainDisplay, xpm_ptr->pixmap, win, drawGC, 0, 0, w, h,
2527                ltx, lty);
2528       } else {
2529          values.function = GXcopy;
2530          values.clip_x_origin = ltx;
2531          values.clip_y_origin = lty;
2532          values.clip_mask = xpm_ptr->bitmap;
2533          XChangeGC(mainDisplay, drawGC, GCFunction |
2534                GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2535 
2536          DrawClippedPixmap(xpm_ptr->pixmap, win, drawGC, scr_w, scr_h,
2537                ltx, lty);
2538 
2539          values.clip_x_origin = 0;
2540          values.clip_y_origin = 0;
2541          values.clip_mask = None;
2542          XChangeGC(mainDisplay, drawGC,
2543                GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2544          if (numClipRecs > 0) {
2545             XSetClipRectangles(mainDisplay, drawGC, 0, 0, clipRecs,
2546                numClipRecs, clipOrdering);
2547          }
2548       }
2549    } else {
2550       if (xpm_ptr->cached_pixmap == None) return;
2551       if (ObjPtr->ctm == NULL) {
2552          if (xpm_ptr->cached_bitmap == None) {
2553             XCopyArea(mainDisplay, xpm_ptr->cached_pixmap, win, drawGC, 0, 0,
2554                   scr_w, scr_h, ltx, lty);
2555          } else {
2556             values.function = GXcopy;
2557             values.clip_x_origin = ltx;
2558             values.clip_y_origin = lty;
2559             values.clip_mask = xpm_ptr->cached_bitmap;
2560             XChangeGC(mainDisplay, drawGC, GCFunction |
2561                   GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2562 
2563             DrawClippedPixmap(xpm_ptr->cached_pixmap, win, drawGC, scr_w, scr_h,
2564                   ltx, lty);
2565 
2566             values.clip_x_origin = 0;
2567             values.clip_y_origin = 0;
2568             values.clip_mask = None;
2569             XChangeGC(mainDisplay, drawGC,
2570                   GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2571             if (numClipRecs > 0) {
2572                XSetClipRectangles(mainDisplay, drawGC, 0, 0, clipRecs,
2573                   numClipRecs, clipOrdering);
2574             }
2575          }
2576       } else if (xpm_ptr->clip_mask == None) {
2577          XCopyArea(mainDisplay, xpm_ptr->cached_pixmap, win, drawGC, 0, 0,
2578                scr_w, scr_h, ltx, lty);
2579       } else {
2580          values.function = GXcopy;
2581          values.clip_x_origin = ltx;
2582          values.clip_y_origin = lty;
2583          values.clip_mask = xpm_ptr->clip_mask;
2584          XChangeGC(mainDisplay, drawGC, GCFunction |
2585                GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2586 
2587          DrawClippedPixmap(xpm_ptr->cached_pixmap, win, drawGC, scr_w, scr_h,
2588                ltx, lty);
2589 
2590          values.clip_x_origin = 0;
2591          values.clip_y_origin = 0;
2592          values.clip_mask = None;
2593          XChangeGC(mainDisplay, drawGC,
2594                GCClipXOrigin | GCClipYOrigin | GCClipMask, &values);
2595          if (numClipRecs > 0) {
2596             XSetClipRectangles(mainDisplay, drawGC, 0, 0, clipRecs,
2597                numClipRecs, clipOrdering);
2598          }
2599       }
2600    }
2601 }
2602 
PrTgifFindColorIndex(ObjPtr,s)2603 int PrTgifFindColorIndex(ObjPtr, s)
2604    struct ObjRec *ObjPtr;
2605    char *s;
2606 {
2607    int i;
2608 
2609    for (i=0; i < maxColors; i++) {
2610       int valid=FALSE;
2611       char *s1=s, *s2=colorMenuItems[i];
2612 
2613       if (*s1 == *s2) {
2614          valid = TRUE;
2615       } else if (*s1 >= 'a' && *s1 <= 'z') {
2616          if (*s1+'A'-'a' == *s2) {
2617             valid = TRUE;
2618          }
2619       } else if (*s >= 'A' && *s <= 'Z') {
2620          if (*s1+'a'-'A' == *s2) {
2621             valid = TRUE;
2622          }
2623       }
2624       if (valid && (UtilStrICmp(++s1,++s2) == 0)) {
2625          if (ObjPtr != NULL) {
2626             UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2627                   colorMenuItems[i]);
2628          }
2629          return i;
2630       }
2631    }
2632    return INVALID;
2633 }
2634 
QuickFindColorIndex(ObjPtr,s,new_alloc,use_default)2635 int QuickFindColorIndex(ObjPtr, s, new_alloc, use_default)
2636    struct ObjRec *ObjPtr;
2637    char *s;
2638    int *new_alloc, use_default;
2639 {
2640    register int i;
2641    XColor exact_def, screen_def;
2642 
2643    if (new_alloc != NULL) *new_alloc = FALSE;
2644 
2645    if (PRTGIF && cmdLineColor && (prTgifFoundColorInfo ||
2646          !cmdLineOpenDisplay)) {
2647       int color_index=PrTgifFindColorIndex(ObjPtr, s);
2648 
2649       if (color_index != INVALID || !cmdLineOpenDisplay) {
2650          return color_index;
2651       }
2652    }
2653    if (ObjPtr != NULL) {
2654       UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str), s);
2655    }
2656    if (colorMenuItems == NULL) {
2657       return INVALID;
2658    }
2659    if (*s == '#') {
2660       if (!TgifParseColor(s, &exact_def)) {
2661          if (use_default) {
2662             sprintf(gszMsgBox,
2663                   TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2664                   s, colorMenuItems[colorIndex]);
2665             if (!PRTGIF) Msg(gszMsgBox);
2666             allocColorFailed = TRUE;
2667             if (ObjPtr != NULL) {
2668                UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2669                      colorMenuItems[colorIndex]);
2670             }
2671             return colorIndex;
2672          }
2673          return INVALID;
2674       }
2675    } else {
2676       for (i=0; i < maxColors; i++) {
2677          int valid=FALSE;
2678          char *s1=s, *s2=colorMenuItems[i];
2679 
2680          if (*s1 == *s2) {
2681             valid = TRUE;
2682          } else if (*s1 >= 'a' && *s1 <= 'z') {
2683             if (*s1+'A'-'a' == *s2) {
2684                valid = TRUE;
2685             }
2686          } else if (*s >= 'A' && *s <= 'Z') {
2687             if (*s1+'a'-'A' == *s2) {
2688                valid = TRUE;
2689             }
2690          }
2691          if (valid && (UtilStrICmp(++s1,++s2) == 0)) {
2692             if (ObjPtr != NULL) {
2693                UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2694                      colorMenuItems[i]);
2695             }
2696             return i;
2697          }
2698       }
2699 
2700       if (!TgifParseColor(s, &exact_def)) {
2701          if (use_default) {
2702             sprintf(gszMsgBox,
2703                   TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2704                   s, colorMenuItems[colorIndex]);
2705             if (!PRTGIF) Msg(gszMsgBox);
2706             allocColorFailed = TRUE;
2707             if (ObjPtr != NULL) {
2708                UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2709                      colorMenuItems[colorIndex]);
2710             }
2711             return colorIndex;
2712          }
2713          return INVALID;
2714       }
2715    }
2716    for (i=0; i < maxColors; i++) {
2717       if (tgifRequestedColors[i].red == exact_def.red &&
2718             tgifRequestedColors[i].green == exact_def.green &&
2719             tgifRequestedColors[i].blue == exact_def.blue) {
2720          if (ObjPtr != NULL) {
2721             UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2722                   colorMenuItems[i]);
2723          }
2724          return i;
2725       }
2726    }
2727 
2728    memcpy(&screen_def, &exact_def, sizeof(XColor));
2729 
2730    if (!XAllocColor(mainDisplay, mainColormap, &screen_def)) {
2731       Colormap colormap;
2732 
2733       if (newColormapUsed) {
2734          if (use_default) {
2735             sprintf(gszMsgBox,
2736                   TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2737                   s, colorMenuItems[colorIndex]);
2738             if (!PRTGIF) Msg(gszMsgBox);
2739             allocColorFailed = TRUE;
2740             if (ObjPtr != NULL) {
2741                UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2742                      colorMenuItems[colorIndex]);
2743             }
2744             return colorIndex;
2745          }
2746          return INVALID;
2747       }
2748       colormap = XCopyColormapAndFree(mainDisplay, mainColormap);
2749       mainColormap = colormap;
2750       newColormapUsed = TRUE;
2751       XSetWindowColormap(mainDisplay, mainWindow, mainColormap);
2752       if (!XAllocColor(mainDisplay, mainColormap, &screen_def)) {
2753          if (use_default) {
2754             sprintf(gszMsgBox,
2755                   TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
2756                   s, colorMenuItems[colorIndex]);
2757             if (!PRTGIF) Msg(gszMsgBox);
2758             allocColorFailed = TRUE;
2759             if (ObjPtr != NULL) {
2760                UtilStrCpyN(ObjPtr->color_str, sizeof(ObjPtr->color_str),
2761                      colorMenuItems[colorIndex]);
2762             }
2763             return colorIndex;
2764          }
2765          return INVALID;
2766       }
2767    }
2768    colorPixels = (int*)realloc(colorPixels, (maxColors+1)*sizeof(int));
2769    xorColorPixels = (int*)realloc(xorColorPixels,
2770          (maxColors+1)*sizeof(int));
2771    colorLayerOn = (int*)realloc(colorLayerOn, (maxColors+1)*sizeof(int));
2772    colorMenuItems = (char**)realloc(colorMenuItems,
2773          (maxColors+1)*sizeof(char*));
2774    colorMenuItems[maxColors] = (char*)malloc((strlen(s)+1)*sizeof(char));
2775    if (colorMenuItems[maxColors] == NULL) FailAllocMessage();
2776    tgifColors = (XColor*)realloc(tgifColors,
2777          (maxColors+1)*sizeof(XColor));
2778    tgifRequestedColors = (XColor*)realloc(tgifRequestedColors,
2779          (maxColors+1)*sizeof(XColor));
2780 
2781    colorPixels[maxColors] = screen_def.pixel;
2782    xorColorPixels[maxColors] =
2783          screen_def.pixel ^ GetDrawingBgPixel(INVALID, INVALID);
2784    colorLayerOn[maxColors] = TRUE;
2785    strcpy(colorMenuItems[maxColors], s);
2786    tgifRequestedColors[maxColors].red = exact_def.red;
2787    tgifRequestedColors[maxColors].green = exact_def.green;
2788    tgifRequestedColors[maxColors].blue = exact_def.blue;
2789    tgifColors[maxColors].red = screen_def.red;
2790    tgifColors[maxColors].green = screen_def.green;
2791    tgifColors[maxColors].blue = screen_def.blue;
2792    maxColors++;
2793    *new_alloc = TRUE;
2794 
2795    DestroyPinnedMenu(MENU_COLOR);
2796    if (!PRTGIF && colorLayers) {
2797       needToRedrawColorWindow = TRUE;
2798    }
2799    return (maxColors-1);
2800 }
2801 
CreateXPmObj(ImageW,ImageH,W,H,pixmap,image,bitmap,bitmap_image,ncolors,chars_per_pixel,first_pixel_is_bg,color_char,color_str,pixels,xpm_data)2802 struct ObjRec *CreateXPmObj(ImageW, ImageH, W, H, pixmap, image, bitmap,
2803       bitmap_image, ncolors, chars_per_pixel, first_pixel_is_bg, color_char,
2804       color_str, pixels, xpm_data)
2805    int ImageW, ImageH, W, H;
2806    Pixmap pixmap, bitmap;
2807    XImage *image, *bitmap_image;
2808    int ncolors, chars_per_pixel, first_pixel_is_bg;
2809    char *color_char;
2810    char **color_str;
2811    int *pixels;
2812    char *xpm_data;
2813 {
2814    struct XPmRec *xpm_ptr;
2815    struct ObjRec *obj_ptr;
2816 
2817    xpm_ptr = (struct XPmRec *)malloc(sizeof(struct XPmRec));
2818    if (xpm_ptr == NULL) FailAllocMessage();
2819    memset(xpm_ptr, 0, sizeof(struct XPmRec));
2820 
2821    xpm_ptr->pixmap = pixmap;
2822    xpm_ptr->image = image;
2823    xpm_ptr->bitmap = bitmap;
2824    xpm_ptr->bitmap_image = bitmap_image;
2825    xpm_ptr->image_w = ImageW;
2826    xpm_ptr->image_h = ImageH;
2827    xpm_ptr->data = xpm_data;
2828 
2829    xpm_ptr->fill = objFill;
2830    xpm_ptr->flip = xpm_ptr->cached_flip = 0;
2831    xpm_ptr->cached_zoom = 0;
2832    xpm_ptr->cached_pixmap = None;
2833    xpm_ptr->cached_bitmap = None;
2834    xpm_ptr->cached_w = xpm_ptr->cached_h = 0;
2835    xpm_ptr->cached_color = (-1);
2836 
2837    xpm_ptr->ncolors = ncolors;
2838    xpm_ptr->chars_per_pixel = chars_per_pixel;
2839    xpm_ptr->first_pixel_is_bg = first_pixel_is_bg;
2840    xpm_ptr->color_char = color_char;
2841    xpm_ptr->color_str = color_str;
2842    xpm_ptr->pixels = pixels;
2843    if (colorDisplay || ncolors == (-1)) {
2844       xpm_ptr->red = xpm_ptr->green = xpm_ptr->blue = NULL;
2845    } else {
2846       int i;
2847 
2848       xpm_ptr->red = (int*)malloc(ncolors*sizeof(int));
2849       xpm_ptr->green = (int*)malloc(ncolors*sizeof(int));
2850       xpm_ptr->blue = (int*)malloc(ncolors*sizeof(int));
2851       if (xpm_ptr->red==NULL || xpm_ptr->green==NULL || xpm_ptr->blue==NULL) {
2852          FailAllocMessage();
2853       }
2854       for (i=0; i < ncolors; i++) {
2855          int new_alloc;
2856          int index=QuickFindColorIndex(NULL, color_str[i], &new_alloc, TRUE);
2857 
2858          xpm_ptr->red[i] =
2859                (int)(10000*((int)tgifRequestedColors[index].red)/maxRGB);
2860          xpm_ptr->green[i] =
2861                (int)(10000*((int)tgifRequestedColors[index].green)/maxRGB);
2862          xpm_ptr->blue[i] =
2863                (int)(10000*((int)tgifRequestedColors[index].blue)/maxRGB);
2864       }
2865    }
2866    xpm_ptr->clip_mask = None;
2867 
2868    obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
2869    if (obj_ptr == NULL) FailAllocMessage();
2870    memset(obj_ptr, 0, sizeof(struct ObjRec));
2871 
2872    obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = drawOrigX;
2873    obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = drawOrigY;
2874    obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = W + drawOrigX;
2875    obj_ptr->bbox.rby = obj_ptr->obbox.rby = H + drawOrigY;
2876    obj_ptr->type = OBJ_XPM;
2877    obj_ptr->color = colorIndex;
2878    if (mainDisplay != NULL) {
2879       UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
2880             colorMenuItems[colorIndex]);
2881    }
2882    obj_ptr->id = objId++;
2883    obj_ptr->dirty = FALSE;
2884    obj_ptr->rotation = 0;
2885    obj_ptr->locked = FALSE;
2886    obj_ptr->detail.xpm = xpm_ptr;
2887    obj_ptr->fattr = obj_ptr->lattr = NULL;
2888    obj_ptr->ctm = NULL;
2889    obj_ptr->invisible = FALSE;
2890 
2891    return obj_ptr;
2892 }
2893 
2894 static
CopyXPmProperties(DestXpmObj,SrcXpmObj)2895 void CopyXPmProperties(DestXpmObj, SrcXpmObj)
2896    struct ObjRec *DestXpmObj, *SrcXpmObj;
2897 {
2898    struct XPmRec *dest_xpm_ptr=DestXpmObj->detail.xpm;
2899    struct XPmRec *src_xpm_ptr=SrcXpmObj->detail.xpm;
2900 
2901    dest_xpm_ptr->fill = src_xpm_ptr->fill;
2902    DestXpmObj->color = SrcXpmObj->color;
2903    memcpy(DestXpmObj->color_str, SrcXpmObj->color_str,
2904          sizeof(DestXpmObj->color_str));
2905 }
2906 
2907 static
FinishBreakUpXPixmap(obj_ptr,cols_and_rows,cols,rows)2908 int FinishBreakUpXPixmap(obj_ptr, cols_and_rows, cols, rows)
2909    struct ObjRec *obj_ptr;
2910    int cols_and_rows, cols, rows;
2911 {
2912    struct XPmRec *xpm_ptr=obj_ptr->detail.xpm;
2913    int y, image_w=xpm_ptr->image_w, image_h=xpm_ptr->image_h;
2914    int chunk_w=0, chunk_h=0, total_chunks=0;
2915    int orig_x=obj_ptr->x, orig_y=obj_ptr->y;
2916    int ncolors, chars_per_pixel, first_pixel_is_bg;
2917    char tmp_fname[MAXPATHLENGTH];
2918 
2919    if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
2920       return FALSE;
2921    }
2922    ncolors = xpm_ptr->ncolors;
2923    chars_per_pixel = xpm_ptr->chars_per_pixel;
2924    first_pixel_is_bg = xpm_ptr->first_pixel_is_bg;
2925 
2926    if (cols_and_rows) {
2927       chunk_w = (int)(image_w / cols);
2928       chunk_h = (int)(image_h / rows);
2929    } else {
2930       chunk_w = cols;
2931       chunk_h = rows;
2932    }
2933    for (y=0; y < image_h; y += chunk_h) {
2934       int h=min(image_h-y,chunk_h), x;
2935 
2936       for (x=0; x < image_w; x += chunk_w) {
2937          int w=min(image_w-x,chunk_w), i, *pixels=NULL;
2938          char *color_char=NULL, **color_str=NULL, *xpm_data=NULL;
2939          struct ObjRec *new_obj_ptr=NULL;
2940          Pixmap dest_pixmap=None, dest_bitmap=None;
2941          XImage *dest_image=NULL, *dest_bitmap_image=NULL;
2942 
2943          if (w <= 0 || h <= 0 ||
2944                !ExtractPixmap(xpm_ptr->pixmap, xpm_ptr->image, xpm_ptr->bitmap,
2945                xpm_ptr->bitmap_image, x, y, w, h, &dest_pixmap, &dest_image,
2946                &dest_bitmap, &dest_bitmap_image)) {
2947             continue;
2948          }
2949          if ((xpm_ptr->real_type == XPM_JPEG ||
2950                xpm_ptr->real_type == PPM_TRUE) &&
2951                fullTrueColorMode && HasZlibSupport()) {
2952             if (DumpXImageToPpmFile(dest_image, w, h, tmp_fname, TRUE)) {
2953                char deflated_fname[MAXPATHLENGTH];
2954                unsigned int data_size=0;
2955                char *ppm_data=NULL;
2956 
2957                snprintf(deflated_fname, sizeof(deflated_fname), "%s.ppm.z",
2958                      tmp_fname);
2959                ppm_data = ReadFileIntoBuf(deflated_fname, &data_size);
2960                unlink(deflated_fname);
2961                unlink(tmp_fname);
2962                if (ppm_data) {
2963                   new_obj_ptr = CreatePpmTrueObjFromImage(dest_image, w, h,
2964                         ppm_data, data_size);
2965                }
2966             }
2967             if (dest_pixmap != None) XFreePixmap(mainDisplay, dest_pixmap);
2968             if (dest_bitmap != None) XFreePixmap(mainDisplay, dest_bitmap);
2969             if (dest_image != NULL) XDestroyImage(dest_image);
2970             if (dest_bitmap_image != NULL) XDestroyImage(dest_bitmap_image);
2971             dest_pixmap = dest_bitmap = None;
2972             dest_image = dest_bitmap_image = NULL;
2973             if (new_obj_ptr != NULL) {
2974                total_chunks++;
2975             }
2976          } else {
2977             pixels = (int*)malloc(ncolors*sizeof(int));
2978             if (pixels == NULL) FailAllocMessage();
2979             memcpy(pixels, xpm_ptr->pixels, (size_t)(ncolors*sizeof(int)));
2980 
2981             color_char = (char*)malloc(ncolors*chars_per_pixel*sizeof(char));
2982             if (color_char == NULL) FailAllocMessage();
2983             memcpy(color_char, xpm_ptr->color_char,
2984                   (size_t)(ncolors*chars_per_pixel*sizeof(char)));
2985 
2986             color_str = (char**)malloc(ncolors*sizeof(char*));
2987             if (color_str == NULL) FailAllocMessage();
2988             for (i=0; i < ncolors; i++) {
2989                if ((color_str[i]=UtilStrDup(xpm_ptr->color_str[i])) == NULL) {
2990                   FailAllocMessage();
2991                }
2992             }
2993             total_chunks++;
2994             new_obj_ptr = CreateXPmObj(w, h, w, h, dest_pixmap, dest_image,
2995                   dest_bitmap, dest_bitmap_image, ncolors, chars_per_pixel,
2996                   first_pixel_is_bg, color_char, color_str, pixels, xpm_data);
2997             CopyXPmProperties(new_obj_ptr, obj_ptr);
2998          }
2999          if (new_obj_ptr != NULL) {
3000             AdjObjBBox(new_obj_ptr);
3001             MoveObj(new_obj_ptr, orig_x+x, orig_y+y);
3002             AddObj(NULL, topObj, new_obj_ptr);
3003          }
3004       }
3005    }
3006    if (total_chunks > 0) {
3007       int i;
3008 
3009       RemoveAllSel();
3010       UnlinkObj(obj_ptr);
3011       FreeObj(obj_ptr);
3012 
3013       for (i=0, obj_ptr=topObj; obj_ptr != NULL && i < total_chunks; i++,
3014             obj_ptr=obj_ptr->next) {
3015          AddObjIntoSel(obj_ptr, botSel, NULL, &topSel, &botSel);
3016       }
3017    }
3018    return (total_chunks > 0);
3019 }
3020 
BreakUpXPixmap(obj_ptr,cols_and_rows,cols,rows)3021 void BreakUpXPixmap(obj_ptr, cols_and_rows, cols, rows)
3022    struct ObjRec *obj_ptr;
3023    int cols_and_rows, cols, rows;
3024 {
3025    HighLightReverse();
3026    PrepareToReplaceAnObj(obj_ptr);
3027    if (FinishBreakUpXPixmap(obj_ptr, cols_and_rows, cols, rows)) {
3028       UpdSelBBox();
3029       RecordCmd(CMD_ONE_TO_MANY, NULL, topSel, botSel, numObjSelected);
3030       SetFileModified(TRUE);
3031       justDupped = FALSE;
3032    } else {
3033       AbortPrepareCmd(CMD_REPLACE);
3034    }
3035    HighLightForward();
3036 }
3037 
3038 static
SaveXPmPixels(FP,xpm_ptr,pixmap,image,bitmap,bitmap_image,w,h,ncolors,chars_per_pixel,color_char,pixels)3039 void SaveXPmPixels(FP, xpm_ptr, pixmap, image, bitmap, bitmap_image, w, h,
3040       ncolors, chars_per_pixel, color_char, pixels)
3041    FILE *FP;
3042    struct XPmRec *xpm_ptr;
3043    Pixmap pixmap, bitmap;
3044    XImage **image, **bitmap_image;
3045    int w, h, ncolors, chars_per_pixel, *pixels;
3046    char *color_char;
3047 {
3048    register int j, data, index, i, k;
3049    char *xpm_data=NULL;
3050 
3051    if (*image == NULL) {
3052       *image = XGetImage(mainDisplay, pixmap, 0, 0, w, h, AllPlanes, ZPixmap);
3053       if (*image == NULL) {
3054          sprintf(gszMsgBox, "%s\n\n%s",
3055                TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM),
3056                TgLoadString(STID_SAVED_FILE_MAY_BE_CORRUPTED));
3057          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3058          return;
3059       }
3060    }
3061    if (*bitmap_image == NULL) {
3062       *bitmap_image = XGetImage(mainDisplay, bitmap, 0, 0, w, h, 1, ZPixmap);
3063       if (*bitmap_image == NULL) {
3064          sprintf(gszMsgBox, "%s\n\n%s",
3065                TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM),
3066                TgLoadString(STID_SAVED_FILE_MAY_BE_CORRUPTED));
3067          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3068          return;
3069       }
3070    }
3071    xpm_data = xpm_ptr->data;
3072    for (i=0; i < h; i++) {
3073       if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
3074       for (j=0; j < w; j++) {
3075          if (!colorDisplay && xpm_data != NULL && xpm_ptr->red != NULL) {
3076             for (k=0; k < chars_per_pixel; k++) {
3077                if (fprintf(FP, "%c", xpm_data[j*chars_per_pixel+k]) == EOF) {
3078                   writeFileFailed = TRUE;
3079                }
3080             }
3081          } else {
3082             if (XGetPixel(*bitmap_image, j, i) != 0) {
3083                data = XGetPixel(*image,j,i);
3084             } else {
3085                data = (-1);
3086             }
3087             index = XPmLookUp(data, INVALID, NULL, NULL);
3088             if (index == INVALID) {
3089                sprintf(gszMsgBox,
3090                      TgLoadString(STID_UNRECOG_GIVEN_PIXEL_VAL_PRINT),
3091                      j, i, data, (long)data);
3092                Msg(gszMsgBox);
3093                return;
3094             }
3095             for (k=0; k < chars_per_pixel; k++) {
3096                if (fprintf(FP, "%c", color_char[index*chars_per_pixel+k]) ==
3097                      EOF) {
3098                   writeFileFailed = TRUE;
3099                }
3100             }
3101          }
3102       }
3103       if (xpm_data != NULL) xpm_data += w*chars_per_pixel;
3104       if (i == h-1) {
3105          if (fprintf(FP, "\"],") == EOF) writeFileFailed = TRUE;
3106       } else {
3107          if (fprintf(FP, "\",\n") == EOF) writeFileFailed = TRUE;
3108       }
3109    }
3110 }
3111 
3112 static
WritePpmTrueData(FP,xpm_ptr)3113 int WritePpmTrueData(FP, xpm_ptr)
3114    FILE *FP;
3115    struct XPmRec *xpm_ptr;
3116 {
3117    char *psz=xpm_ptr->ppm_data;
3118    int total_bytes_to_write=xpm_ptr->ppm_data_size;
3119 
3120    while (total_bytes_to_write > 0) {
3121       int bytes_to_read=min(48, total_bytes_to_write), bytes_to_write=0;
3122       char out_buf[65];
3123 
3124       bytes_to_write = (bytes_to_read / 3);
3125       if ((bytes_to_read % 3) == 0) {
3126          bytes_to_write = bytes_to_write << 2;
3127       } else {
3128          bytes_to_write = (bytes_to_write+1) << 2;
3129       }
3130       *out_buf = '\0';
3131       DoBase64Encode(psz, bytes_to_read, out_buf);
3132       if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
3133       if (fwrite(out_buf, 1, bytes_to_write, FP) != bytes_to_write) {
3134          writeFileFailed = TRUE;
3135       }
3136       psz += bytes_to_read;
3137       total_bytes_to_write -= bytes_to_read;
3138       if (total_bytes_to_write > 0) {
3139          if (fprintf(FP, "\",\n") == EOF) writeFileFailed = TRUE;
3140       } else {
3141          if (fprintf(FP, "\"],[\n") == EOF) writeFileFailed = TRUE;
3142       }
3143    }
3144    if (xpm_ptr->ppm_mask_data != NULL) {
3145       TgAssert(FALSE, "xpm_ptr->ppm_mask_data != NULL in WritePpmTrueData()",
3146             NULL);
3147    }
3148    if (fprintf(FP, "   ],") == EOF) writeFileFailed = TRUE;
3149 
3150    return TRUE;
3151 }
3152 
3153 static
ReadPpmTrueData(fp,ppm_data_size)3154 char *ReadPpmTrueData(fp, ppm_data_size)
3155    FILE *fp;
3156    int ppm_data_size;
3157 {
3158    char line[64+20], *write_ptr=NULL;
3159    char *buf_return=(char*)malloc(ppm_data_size+1);
3160 
3161    if (buf_return == NULL) FailAllocMessage();
3162    write_ptr = buf_return;
3163    while (fgets(line, sizeof(line), fp) != NULL) {
3164       int len=strlen(line), bytes_converted=0;
3165       char *s=NULL, buf[64+20], out_buf[49];
3166 
3167       scanLineNum++;
3168       if (len > 0 && line[len-1] != '\n') {
3169          sprintf(gszMsgBox, TgLoadString(STID_BAD_LINE_READING_GIVEN_OBJ),
3170                "ppm_true");
3171          if (PRTGIF) {
3172             fprintf(stderr, "%s\n", gszMsgBox);
3173          } else {
3174             Msg(gszMsgBox);
3175          }
3176          UtilFree(buf_return);
3177          return NULL;
3178       }
3179       s = FindChar((int)'"', line);
3180       s = ParseStr(s, (int)'"', buf, sizeof(buf));
3181       len = strlen(buf);
3182       if (len > 64 || (len & 0x3) != 0) {
3183          sprintf(gszMsgBox, TgLoadString(STID_BAD_LINE_READING_GIVEN_OBJ),
3184                "ppm_true");
3185          if (PRTGIF) {
3186             fprintf(stderr, "%s\n", gszMsgBox);
3187          } else {
3188             Msg(gszMsgBox);
3189          }
3190          UtilFree(buf_return);
3191          return NULL;
3192       }
3193       /* bytes_converted = (len >> 2) * 3; */
3194       bytes_converted = DoBase64Decode(buf, len, out_buf);
3195       ppm_data_size -= bytes_converted;
3196       if (ppm_data_size < 0) {
3197          sprintf(gszMsgBox, TgLoadString(STID_INSUF_DATA_READING_GIVEN_OBJ),
3198                "ppm_true");
3199          if (PRTGIF) {
3200             fprintf(stderr, "%s\n", gszMsgBox);
3201          } else {
3202             Msg(gszMsgBox);
3203          }
3204          UtilFree(buf_return);
3205          return NULL;
3206       }
3207       memcpy(write_ptr, out_buf, bytes_converted);
3208       write_ptr += bytes_converted;
3209       if (ppm_data_size == 0) break;
3210    }
3211    if (ppm_data_size != 0) {
3212       sprintf(gszMsgBox, TgLoadString(STID_BAD_LINE_READING_GIVEN_OBJ),
3213             "ppm_true");
3214       if (PRTGIF) {
3215          fprintf(stderr, "%s\n", gszMsgBox);
3216       } else {
3217          Msg(gszMsgBox);
3218       }
3219       UtilFree(buf_return);
3220       return NULL;
3221    }
3222    return buf_return;
3223 }
3224 
3225 static
ReadPpmTrueMask(fp,ppm_mask_size)3226 char *ReadPpmTrueMask(fp, ppm_mask_size)
3227    FILE *fp;
3228    int ppm_mask_size;
3229 {
3230    char line[64+20];
3231 
3232    while (fgets(line, sizeof(line), fp) != NULL) {
3233       /* this feature has not been implemented yet */
3234       break;
3235    }
3236    return NULL;
3237 }
3238 
SaveXPmObj(FP,ObjPtr)3239 void SaveXPmObj(FP, ObjPtr)
3240    FILE *FP;
3241    struct ObjRec *ObjPtr;
3242 {
3243    int ltx, lty, rbx, rby, fill, ncolors, *pixels=NULL;
3244    int chars_per_pixel, first_pixel_is_bg, image_w, image_h;
3245    int compressed=FALSE, real_type=0, linked_jpeg=FALSE, jpeg=FALSE;
3246    int ppm_z=FALSE;
3247    struct XPmRec *xpm_ptr=ObjPtr->detail.xpm;
3248    char *color_char=NULL, **color_str=NULL, *jpeg_filename=NULL;
3249 
3250    ltx = ObjPtr->obbox.ltx; lty = ObjPtr->obbox.lty;
3251    rbx = ObjPtr->obbox.rbx; rby = ObjPtr->obbox.rby;
3252    image_w = xpm_ptr->image_w;
3253    image_h = xpm_ptr->image_h;
3254    fill = xpm_ptr->fill;
3255    ncolors = xpm_ptr->ncolors;
3256    chars_per_pixel = xpm_ptr->chars_per_pixel;
3257    first_pixel_is_bg = xpm_ptr->first_pixel_is_bg;
3258    color_char = xpm_ptr->color_char;
3259    color_str = xpm_ptr->color_str;
3260    pixels = xpm_ptr->pixels;
3261 
3262    real_type = xpm_ptr->real_type;
3263    linked_jpeg = xpm_ptr->linked_jpeg;
3264    jpeg_filename = xpm_ptr->filename;
3265 
3266    /* only doing linked JPEG */
3267    jpeg = (real_type == XPM_JPEG && linked_jpeg && jpeg_filename != NULL);
3268    ppm_z = (real_type == PPM_TRUE);
3269 
3270    if (!colorDisplay && xpm_ptr->red == NULL && !shownXPmErrorMessage) {
3271       MsgBox(TgLoadString(STID_CANT_SAVE_XPM_ON_BW_DPY), TOOL_NAME, INFO_MB);
3272       shownXPmErrorMessage = TRUE;
3273       return;
3274    }
3275    if (jpeg) {
3276       if (fprintf(FP, "jpeg('%s','',", colorMenuItems[ObjPtr->color]) == EOF) {
3277          writeFileFailed = TRUE;
3278       }
3279    } else if (ppm_z) {
3280       if (fprintf(FP, "ppm_true('%s',", colorMenuItems[ObjPtr->color]) == EOF) {
3281          writeFileFailed = TRUE;
3282       }
3283       if (xpm_ptr->has_transparent_color) {
3284          if (fprintf(FP, "'#%02x%02x%02x',1,",
3285                xpm_ptr->transparent_color[0], xpm_ptr->transparent_color[1],
3286                xpm_ptr->transparent_color[2]) == EOF) {
3287             writeFileFailed = TRUE;
3288          }
3289       } else {
3290          if (fprintf(FP, "'#ffffff',0,") == EOF) {
3291             writeFileFailed = TRUE;
3292          }
3293       }
3294    } else {
3295       if (fprintf(FP, "xpm('%s','',", colorMenuItems[ObjPtr->color]) == EOF) {
3296          writeFileFailed = TRUE;
3297       }
3298    }
3299    if (ppm_z) {
3300       if (fprintf(FP,
3301             "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,",
3302             ltx, lty, rbx, rby, ObjPtr->id, ObjPtr->rotation, image_w,
3303             image_h) == EOF) {
3304          writeFileFailed = TRUE;
3305       }
3306    } else {
3307       if (fprintf(FP,
3308             "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,",
3309             ltx, lty, rbx, rby, fill, ncolors, chars_per_pixel,
3310             first_pixel_is_bg, ObjPtr->id, ObjPtr->rotation, image_w,
3311             image_h) == EOF) {
3312          writeFileFailed = TRUE;
3313       }
3314    }
3315    if (jpeg) {
3316       if (fprintf(FP,
3317             "0,%1d,%1d,%1d,%1d,%1d,%1d,%1d,\n    \"%s\",",
3318             xpm_ptr->flip, ObjPtr->locked, compressed,
3319             ObjPtr->ctm!=NULL, ObjPtr->invisible, real_type, linked_jpeg,
3320             jpeg_filename) == EOF) {
3321          writeFileFailed = TRUE;
3322       }
3323    } else if (ppm_z) {
3324       if (fprintf(FP,
3325             "0,%1d,%1d,%1d,%1d,%1d,%1d,%1d,",
3326             xpm_ptr->flip, ObjPtr->locked, ObjPtr->ctm!=NULL, ObjPtr->invisible,
3327             xpm_ptr->ppm_data_compress, xpm_ptr->ppm_data_size,
3328             xpm_ptr->ppm_mask_size) == EOF) {
3329          writeFileFailed = TRUE;
3330       }
3331    } else {
3332       if (fprintf(FP,
3333             "0,%1d,%1d,%1d,%1d,%1d,",
3334             xpm_ptr->flip, ObjPtr->locked, compressed,
3335             ObjPtr->ctm!=NULL, ObjPtr->invisible) == EOF) {
3336          writeFileFailed = TRUE;
3337       }
3338    }
3339    if (ObjPtr->ctm != NULL && fprintf(FP,
3340          "[\n   %1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
3341          ObjPtr->x, ObjPtr->y,
3342          ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
3343          ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
3344          ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
3345          ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
3346          ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
3347       writeFileFailed = TRUE;
3348    }
3349    if (jpeg) {
3350       /* nothing to write here */
3351    } else if (ppm_z) {
3352       if (fprintf(FP, "[\n") == EOF) writeFileFailed = TRUE;
3353       if (!WritePpmTrueData(FP, xpm_ptr)) {
3354          return;
3355       }
3356    } else {
3357       if (fprintf(FP, "[\n") == EOF) writeFileFailed = TRUE;
3358       if (!colorDisplay && xpm_ptr->red != NULL) {
3359          if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel,
3360                color_char, NULL)) {
3361             return;
3362          }
3363       } else {
3364          if (!BuildXPmBuckets(ncolors, pixels, NULL, INVALID, NULL, NULL)) {
3365             return;
3366          }
3367       }
3368       SaveXPmColors(FP, ObjPtr->color, xpm_ptr, ncolors, chars_per_pixel,
3369             color_char, color_str, pixels);
3370       SaveXPmPixels(FP, xpm_ptr, xpm_ptr->pixmap, &(xpm_ptr->image),
3371             xpm_ptr->bitmap, &(xpm_ptr->bitmap_image),
3372             image_w, image_h, ncolors, chars_per_pixel, color_char, pixels);
3373    }
3374    if (serializingFile) SaveCreatorID(FP, ObjPtr, "    ");
3375    SaveAttrs(FP, ObjPtr->lattr);
3376    if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
3377 }
3378 
3379 static
FreeAuxData(fp,ncolors,color_char,color_str,p_pixels,pixels_used,p_pixmap,p_image,p_bitmap,p_bitmap_image)3380 void FreeAuxData(fp, ncolors, color_char, color_str,
3381       p_pixels, pixels_used, p_pixmap, p_image, p_bitmap, p_bitmap_image)
3382    FILE *fp;
3383    int ncolors;
3384    char *color_char, **color_str;
3385    int **p_pixels, *pixels_used;
3386    Pixmap *p_pixmap, *p_bitmap;
3387    XImage **p_image, **p_bitmap_image;
3388 {
3389    register int i;
3390 
3391    for (i = 0; i < ncolors; i++) free(color_str[i]);
3392    free(color_char);
3393    free(color_str);
3394    if (p_pixels != NULL && *p_pixels != NULL) free(*p_pixels);
3395    if (pixels_used != NULL) free(pixels_used);
3396    if (p_pixmap != NULL && *p_pixmap != None) {
3397       XFreePixmap(mainDisplay, *p_pixmap);
3398    }
3399    if (p_bitmap != NULL && *p_bitmap != None){
3400        XFreePixmap(mainDisplay, *p_bitmap);
3401    }
3402    if (p_image != NULL && *p_image != NULL) XDestroyImage(*p_image);
3403    if (p_bitmap_image != NULL && *p_bitmap_image != NULL) {
3404       XDestroyImage(*p_bitmap_image);
3405    }
3406    fclose(fp);
3407 }
3408 
MyReadPixmapFile(file_name,image_w_return,image_h_return,w_return,h_return,pixmap_return,image_return,bitmap_return,bitmap_image_return,ncolors_return,chars_per_pixel_return,first_pixel_is_bg_return,color_char,color_str,pixels,xpm_data)3409 int MyReadPixmapFile(file_name, image_w_return, image_h_return, w_return,
3410       h_return, pixmap_return, image_return, bitmap_return, bitmap_image_return,
3411       ncolors_return, chars_per_pixel_return, first_pixel_is_bg_return,
3412       color_char, color_str, pixels, xpm_data)
3413    char *file_name;
3414    int *image_w_return, *image_h_return, *w_return, *h_return;
3415    int *ncolors_return;
3416    int *chars_per_pixel_return, *first_pixel_is_bg_return;
3417    Pixmap *pixmap_return, *bitmap_return;
3418    XImage **image_return, **bitmap_image_return;
3419    char **color_char, ***color_str;
3420    int **pixels;
3421    char **xpm_data;
3422 {
3423    register int j, k;
3424    register char *c_ptr;
3425    FILE *fp;
3426    char inbuf[MAXSTRING], *line, s[MAXSTRING];
3427    char mag_spec[MAXSTRING], *xpm_data_ptr=NULL;
3428    int i, len, format, found=FALSE, index, saved_max_colors, xpm_version=1;
3429    int x, y, w, h, chars_per_pixel, new_alloc, image_w=0, image_h=0;
3430    int *pixels_used=NULL, bg_pixel;
3431    float mag=(float)0;
3432 
3433    myReadTransparentPixmap = FALSE;
3434 
3435    if (xpm_data != NULL) *xpm_data = NULL;
3436    gnNumNewColorsInPixmapFile = 0;
3437 
3438    if ((fp=fopen(file_name, "r")) == NULL) return BitmapOpenFailed;
3439 
3440    saved_max_colors = maxColors;
3441    while (fgets(inbuf, MAXSTRING, fp) != NULL) {
3442       if (strncmp(inbuf, "#define ", 8) == 0) {
3443          xpm_version = 1;
3444          found = TRUE;
3445          break;
3446       } else if (strncmp(inbuf, "/* XPM */", 9) == 0) {
3447          xpm_version = 3;
3448          found = TRUE;
3449          break;
3450       }
3451    }
3452    if (!found) return BitmapFileInvalid;
3453 
3454    if (xpm_version == 1) {
3455       c_ptr = FindChar((int)' ', inbuf);
3456       c_ptr = ParseStr(c_ptr, (int)' ', s, sizeof(s));
3457       len = strlen(s);
3458       if (len <= 7 || strcmp(&s[len-7], "_format") != 0) {
3459          return BitmapFileInvalid;
3460       }
3461       sscanf(c_ptr, "%d", &format);
3462       if (format != 1) {
3463          sprintf(gszMsgBox, TgLoadString(STID_CANT_IMPORT_GIVEN_FORMAT_XPM),
3464                format);
3465          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3466          return BitmapFileInvalid;
3467       }
3468       if (fgets(inbuf, MAXSTRING, fp)==NULL) return BitmapFileInvalid;
3469       c_ptr = FindChar((int)' ', inbuf);
3470       c_ptr = ParseStr(c_ptr, (int)' ', s, sizeof(s));
3471       len = strlen(s);
3472       if (len <= 6 || strcmp(&s[len-6], "_width") != 0) {
3473          return BitmapFileInvalid;
3474       }
3475       sscanf(c_ptr, "%d", &image_w);
3476       if (image_w_return != NULL) *image_w_return = image_w;
3477 
3478       if (fgets(inbuf, MAXSTRING, fp)==NULL) return BitmapFileInvalid;
3479       c_ptr = FindChar((int)' ', inbuf);
3480       c_ptr = ParseStr(c_ptr, (int)' ', s, sizeof(s));
3481       len = strlen(s);
3482       if (len <= 7 || strcmp(&s[len-7], "_height") != 0) {
3483          return BitmapFileInvalid;
3484       }
3485       sscanf(c_ptr, "%d", &image_h);
3486       if (image_h_return != NULL) *image_h_return = image_h;
3487 
3488       if (fgets(inbuf, MAXSTRING, fp)==NULL) return BitmapFileInvalid;
3489       c_ptr = FindChar((int)' ', inbuf);
3490       c_ptr = ParseStr(c_ptr, (int)' ', s, sizeof(s));
3491       len = strlen(s);
3492       if (len <= 8 || strcmp(&s[len-8], "_ncolors") != 0) {
3493          return BitmapFileInvalid;
3494       }
3495       sscanf(c_ptr, "%d", ncolors_return);
3496 
3497       if (fgets(inbuf, MAXSTRING, fp)==NULL) return BitmapFileInvalid;
3498       c_ptr = FindChar((int)' ', inbuf);
3499       c_ptr = ParseStr(c_ptr, (int)' ', s, sizeof(s));
3500       len = strlen(s);
3501       if (len <= 16 || strcmp(&s[len-16], "_chars_per_pixel") != 0) {
3502          return BitmapFileInvalid;
3503       }
3504       sscanf(c_ptr, "%d", &chars_per_pixel);
3505       if (chars_per_pixel_return != NULL) {
3506          *chars_per_pixel_return = chars_per_pixel;
3507       }
3508       if (chars_per_pixel > 2) {
3509          sprintf(gszMsgBox, TgLoadString(STID_CANT_IMPORT_GIVEN_CPP_XPM),
3510                chars_per_pixel);
3511          Msg(gszMsgBox);
3512          return BitmapFileInvalid;
3513       }
3514 
3515       if (fgets(inbuf, MAXSTRING, fp)==NULL) return BitmapFileInvalid;
3516       len = strlen(inbuf);
3517       if (len <= 27 || strncmp(inbuf, "static char *", 13) != 0 ||
3518             strncmp(&inbuf[len-14], "_colors[] = {\n", 14) != 0) {
3519          return BitmapFileInvalid;
3520       }
3521    } else {
3522       /* xpm_version is 3 */
3523       found = FALSE;
3524       while (fgets(inbuf, MAXSTRING, fp) != NULL) {
3525          if (*inbuf == '"') {
3526             found = TRUE;
3527             break;
3528          }
3529       }
3530       if (!found) return BitmapFileInvalid;
3531       c_ptr = &inbuf[1];
3532       if (sscanf(c_ptr, "%d %d %d %d", &image_w, &image_h,
3533             ncolors_return, &chars_per_pixel) != 4) {
3534          return BitmapFileInvalid;
3535       }
3536       if (image_w_return != NULL) *image_w_return = image_w;
3537       if (image_h_return != NULL) *image_h_return = image_h;
3538       if (chars_per_pixel_return != NULL) {
3539          *chars_per_pixel_return = chars_per_pixel;
3540       }
3541    }
3542 
3543    *color_char =
3544          (char*)malloc((*ncolors_return)*(chars_per_pixel)*sizeof(char)+1);
3545    *color_str = (char**)malloc((*ncolors_return)*sizeof(char*));
3546    if (color_char == NULL || color_str == NULL) FailAllocMessage();
3547    if (pixels != NULL) {
3548       *pixels = (int*)malloc((*ncolors_return)*sizeof(int));
3549       pixels_used = (int*)malloc((*ncolors_return)*sizeof(int));
3550       if (*pixels == NULL || pixels_used == NULL) FailAllocMessage();
3551       memset(pixels_used, 0, (*ncolors_return)*sizeof(int));
3552    }
3553    if (pixmap_return != NULL) *pixmap_return = None;
3554    if (bitmap_return != NULL) *bitmap_return = None;
3555    if (image_return != NULL) *image_return = NULL;
3556    if (bitmap_image_return != NULL) *bitmap_image_return = NULL;
3557    if (first_pixel_is_bg_return != NULL) *first_pixel_is_bg_return = FALSE;
3558 
3559    bg_pixel = GetDrawingBgPixel(INVALID, INVALID);
3560    if (xpm_version == 1) {
3561       for (i = 0; i < *ncolors_return; i++) {
3562          if (fgets(inbuf, MAXSTRING, fp) == NULL) {
3563             FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3564                   pixmap_return, image_return, bitmap_return,
3565                   bitmap_image_return);
3566             return BitmapFileInvalid;
3567          }
3568          c_ptr = FindChar((int)'"', inbuf);
3569          for (j = 0; j < chars_per_pixel; j++) {
3570             (*color_char)[i*(chars_per_pixel)+j] = c_ptr[j];
3571          }
3572          if (guessXPmBgColor && i == 0 &&
3573                ((chars_per_pixel == 1 && (*c_ptr=='`' || *c_ptr==' ')) ||
3574                (chars_per_pixel == 2 && ((c_ptr[0]=='`' && c_ptr[1]=='`') ||
3575                (c_ptr[0]==' ' && c_ptr[1]==' '))))) {
3576             strcpy(s, (myFileBgColorStr==NULL ? myBgColorStr :
3577                   myFileBgColorStr));
3578             if (pixels != NULL) (*pixels)[0] = bg_pixel;
3579             if (first_pixel_is_bg_return != NULL) {
3580                *first_pixel_is_bg_return = TRUE;
3581             }
3582          } else {
3583             c_ptr = FindChar((int)'"', c_ptr);
3584             c_ptr = FindChar((int)'"', c_ptr);
3585             ParseStr(c_ptr, (int)'"', s, sizeof(s));
3586             if (pixels != NULL) {
3587                if (UtilStrICmp(s, "None") == 0) {
3588                   (*pixels)[i] = (-1);
3589                   myReadTransparentPixmap = TRUE;
3590                } else if ((index=QuickFindColorIndex(NULL, s, &new_alloc,
3591                      TRUE)) == INVALID) {
3592                   sprintf(gszMsgBox,
3593                         TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
3594                         s, colorMenuItems[colorIndex]);
3595                   Msg(gszMsgBox);
3596                   strcpy(s, colorMenuItems[colorIndex]);
3597                   (*pixels)[i] = colorPixels[colorIndex];
3598                   allocColorFailed = TRUE;
3599                } else {
3600                   (*pixels)[i] = colorPixels[index];
3601                }
3602             } else {
3603                if (UtilStrICmp(s, "None") == 0) {
3604                   myReadTransparentPixmap = TRUE;
3605                }
3606             }
3607          }
3608          len = strlen(s);
3609          (*color_str)[i] = (char*)malloc((len+1)*sizeof(char));
3610          if ((*color_str)[i] == NULL) FailAllocMessage();
3611          strcpy((*color_str)[i], s);
3612       }
3613 
3614       if (fgets(inbuf, MAXSTRING, fp) == NULL ||
3615             inbuf[0] != '}' ||
3616             fgets(inbuf, MAXSTRING, fp) == NULL) {
3617          FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3618                pixels_used, pixmap_return, image_return, bitmap_return,
3619                bitmap_image_return);
3620          return BitmapFileInvalid;
3621       }
3622       len = strlen(inbuf);
3623       if (len <= 27 || strncmp(inbuf, "static char *", 13) != 0 ||
3624             strncmp(&inbuf[len-14], "_pixels[] = {\n", 14) != 0) {
3625          return BitmapFileInvalid;
3626       }
3627    } else {
3628       /* xpm_version is 3 */
3629       for (i=0; i < *ncolors_return; i++) {
3630          if (i == 0) {
3631             found = FALSE;
3632             while (fgets(inbuf, MAXSTRING, fp) != NULL) {
3633                if (*inbuf == '"') {
3634                   found = TRUE;
3635                   break;
3636                }
3637             }
3638             if (!found) {
3639                FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3640                      pixmap_return, image_return, bitmap_return,
3641                      bitmap_image_return);
3642                return BitmapFileInvalid;
3643             }
3644          } else if (fgets(inbuf, MAXSTRING, fp) == NULL) {
3645             FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3646                   pixmap_return, image_return, bitmap_return,
3647                   bitmap_image_return);
3648             return BitmapFileInvalid;
3649          }
3650          c_ptr = FindChar((int)'"', inbuf);
3651          for (j = 0; j < chars_per_pixel; j++) {
3652             (*color_char)[i*(chars_per_pixel)+j] = c_ptr[j];
3653          }
3654          if (guessXPmBgColor && i == 0 &&
3655                ((chars_per_pixel == 1 && (*c_ptr=='`' || *c_ptr==' ')) ||
3656                (chars_per_pixel == 2 && ((c_ptr[0]=='`' && c_ptr[1]=='`') ||
3657                (c_ptr[0]==' ' && c_ptr[1]==' '))))) {
3658             strcpy(s, (myFileBgColorStr==NULL ? myBgColorStr :
3659                   myFileBgColorStr));
3660             if (pixels != NULL) (*pixels)[0] = bg_pixel;
3661             if (first_pixel_is_bg_return != NULL) {
3662                *first_pixel_is_bg_return = TRUE;
3663             }
3664          } else {
3665             char *ptr;
3666 
3667             c_ptr += chars_per_pixel;
3668             while (*c_ptr != '\0') {
3669                while (*c_ptr == ' ' || *c_ptr == '\t') c_ptr++;
3670                if ((*c_ptr == 'c' || *c_ptr == 'm') &&
3671                      (c_ptr[1]==' ' || c_ptr[1]=='\t')) {
3672                   break;
3673                }
3674                while (*c_ptr!=' ' && *c_ptr!='\t' && *c_ptr!='\0') c_ptr++;
3675                while (*c_ptr == ' ' || *c_ptr == '\t') c_ptr++;
3676                while (*c_ptr!=' ' && *c_ptr!='\t' && *c_ptr!='\0') c_ptr++;
3677             }
3678             if (*c_ptr++ == '\0') {
3679                FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3680                      pixmap_return, image_return, bitmap_return,
3681                      bitmap_image_return);
3682                return BitmapFileInvalid;
3683             }
3684             while (*c_ptr == ' ' || *c_ptr == '\t') c_ptr++;
3685             for (ptr=c_ptr; *ptr !=  '"' && *ptr != '\0'; ptr++) {
3686                if (*ptr == ' ' || *ptr == '\t') {
3687                   char tmp_ch=ptr[1];
3688 
3689                   if (tmp_ch == 'm' || tmp_ch == 's') {
3690                      tmp_ch = ptr[2];
3691                      if (tmp_ch == ' ' || tmp_ch == '\t') {
3692                         break;
3693                      }
3694                   } else if (tmp_ch == 'g') {
3695                      tmp_ch = ptr[2];
3696                      if (tmp_ch == ' ' || tmp_ch == '\t') {
3697                         break;
3698                      } else if (tmp_ch == '4') {
3699                         tmp_ch = ptr[4];
3700                         if (tmp_ch == ' ' || tmp_ch == '\t') {
3701                            break;
3702                         }
3703                      }
3704                   }
3705                }
3706             }
3707             if (*ptr == '\0') {
3708                FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3709                      pixmap_return, image_return, bitmap_return,
3710                      bitmap_image_return);
3711                return BitmapFileInvalid;
3712             }
3713             while (ptr >= c_ptr) {
3714                if (*ptr == ' ' || *ptr == '\t' || *ptr == '"') {
3715                   ptr--;
3716                } else {
3717                   break;
3718                }
3719             }
3720             if (ptr < c_ptr) {
3721                FreeAuxData(fp, i, *color_char, *color_str, pixels, pixels_used,
3722                      pixmap_return, image_return, bitmap_return,
3723                      bitmap_image_return);
3724                return BitmapFileInvalid;
3725             }
3726             *(++ptr) = '\0';
3727             strcpy(s, c_ptr);
3728             if (pixels != NULL) {
3729                if (UtilStrICmp(s, "None") == 0) {
3730                   (*pixels)[i] = (-1);
3731                   myReadTransparentPixmap = TRUE;
3732                } else if ((index=QuickFindColorIndex(NULL, s, &new_alloc,
3733                      TRUE)) == INVALID) {
3734                   sprintf(gszMsgBox,
3735                         TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
3736                         s, colorMenuItems[colorIndex]);
3737                   Msg(gszMsgBox);
3738                   strcpy(s, colorMenuItems[colorIndex]);
3739                   (*pixels)[i] = colorPixels[colorIndex];
3740                   allocColorFailed = TRUE;
3741                } else {
3742                   (*pixels)[i] = colorPixels[index];
3743                }
3744             } else {
3745                if (UtilStrICmp(s, "None") == 0) {
3746                   myReadTransparentPixmap = TRUE;
3747                }
3748             }
3749          }
3750          len = strlen(s);
3751          (*color_str)[i] = (char*)malloc((len+1)*sizeof(char));
3752          if ((*color_str)[i] == NULL) FailAllocMessage();
3753          strcpy((*color_str)[i], s);
3754       }
3755    }
3756    if (chars_per_pixel_return == NULL && first_pixel_is_bg_return == NULL &&
3757          pixels == NULL &&  xpm_data == NULL) {
3758       /* just getting the colors, so no need to read data */
3759       if (pixels_used != NULL) free(pixels_used);
3760       return BitmapSuccess;
3761    }
3762 
3763    x = 0;
3764    y = 0;
3765    w = image_w;
3766    h = image_h;
3767    if (pixmap_return != NULL && bitmap_return != NULL &&
3768          image_return != NULL && bitmap_image_return != NULL) {
3769       mag = 1.0;
3770       if (askForXPmSpec) {
3771          sprintf(gszMsgBox, TgLoadString(STID_ENTER_GEOM_SPEC_ORIG_SIZE),
3772                image_w, image_h);
3773          *mag_spec = '\0';
3774          Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CONTINUE),
3775                mag_spec);
3776          if (*mag_spec != '\0') {
3777             ParseCutSpec(mag_spec, image_w, image_h, &mag, &x, &y, &w, &h);
3778          }
3779       }
3780       *pixmap_return = XCreatePixmap(mainDisplay, dummyPixmap, w, h, mainDepth);
3781       *bitmap_return = XCreatePixmap(mainDisplay, dummyBitmap, w, h, 1);
3782       if (*pixmap_return == None || *bitmap_return == None) {
3783          FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3784                pixels_used, pixmap_return, image_return, bitmap_return,
3785                bitmap_image_return);
3786          return BitmapNoMemory;
3787       }
3788       XFillRectangle(mainDisplay, *pixmap_return, xpmGC, 0, 0, w, h);
3789       XSetForeground(mainDisplay, xbmGC, 1);
3790       XFillRectangle(mainDisplay, *bitmap_return, xbmGC, 0, 0, w, h);
3791       XSetForeground(mainDisplay, xbmGC, 0);
3792       *image_return = XGetImage(mainDisplay, *pixmap_return, 0, 0, w, h,
3793             AllPlanes, ZPixmap);
3794       *bitmap_image_return = XGetImage(mainDisplay, *bitmap_return, 0, 0, w, h,
3795             1, ZPixmap);
3796       if (*image_return == NULL || *bitmap_image_return == NULL) {
3797          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
3798                INFO_MB);
3799          FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3800                pixels_used, pixmap_return, image_return, bitmap_return,
3801                bitmap_image_return);
3802          return BitmapNoMemory;
3803       }
3804    }
3805    if (!BuildXPmBuckets(*ncolors_return, NULL, NULL, chars_per_pixel,
3806          *color_char, NULL)) {
3807       FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3808             pixels_used, pixmap_return, image_return, bitmap_return,
3809             bitmap_image_return);
3810       return BitmapFileInvalid;
3811    }
3812    if (!colorDisplay) {
3813       if (xpm_data != NULL) {
3814          xpm_data_ptr = *xpm_data = (char*)malloc(
3815                image_w*image_h*chars_per_pixel*sizeof(char)+1);
3816          if (*xpm_data == NULL) FailAllocMessage();
3817       }
3818    }
3819    line = (char*)malloc((image_w*chars_per_pixel+20)*sizeof(char));
3820    if (line == NULL) FailAllocMessage();
3821    for (i=0; i < y+h; i++) {
3822       if (xpm_version == 3 && i == 0) {
3823          found = FALSE;
3824          while (fgets(line, image_w*chars_per_pixel+20, fp) != NULL) {
3825             if (*line == '"') {
3826                found = TRUE;
3827                break;
3828             }
3829          }
3830          if (!found) {
3831             FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3832                   pixels_used, pixmap_return, image_return, bitmap_return,
3833                   bitmap_image_return);
3834             return BitmapFileInvalid;
3835          }
3836       } else if (fgets(line, image_w*chars_per_pixel+20, fp)==NULL) {
3837          FreeAuxData(fp, *ncolors_return, *color_char, *color_str, pixels,
3838                pixels_used, pixmap_return, image_return, bitmap_return,
3839                bitmap_image_return);
3840          free(line);
3841          return BitmapFileInvalid;
3842       }
3843       if (i >= y) {
3844          c_ptr = FindChar((int)'"', line);
3845          if (xpm_data_ptr != NULL) {
3846             strncpy(xpm_data_ptr, c_ptr, image_w*chars_per_pixel);
3847             xpm_data_ptr += image_w*chars_per_pixel;
3848          }
3849          if (pixels != NULL) {
3850             for (j=0; j < x+w; j++, c_ptr+=chars_per_pixel) {
3851                if (j >= x) {
3852                   k = XPmLookUp(INVALID, chars_per_pixel, c_ptr, NULL);
3853                   if (k == INVALID) {
3854                      FreeAuxData(fp, *ncolors_return, *color_char, *color_str,
3855                            pixels, pixels_used, pixmap_return, image_return,
3856                            bitmap_return, bitmap_image_return);
3857                      free(line);
3858                      return BitmapFileInvalid;
3859                   }
3860                   if (pixels_used != NULL) pixels_used[k] = TRUE;
3861                   if ((*pixels)[k] == (-1)) {
3862                      if (bitmap_image_return != NULL) {
3863                         XPutPixel(*bitmap_image_return, j-x, i-y, 0);
3864                      }
3865                      if (image_return != NULL) {
3866                         XPutPixel(*image_return, j-x, i-y,
3867                               colorPixels[colorIndex]);
3868                      }
3869                   } else {
3870                      if (image_return != NULL) {
3871                         XPutPixel(*image_return, j-x, i-y, (*pixels)[k]);
3872                      }
3873                   }
3874                }
3875             }
3876          }
3877       }
3878    }
3879    if (xpm_data_ptr != NULL) *xpm_data_ptr = '\0';
3880    free(line);
3881    fclose(fp);
3882    if (pixmap_return != NULL && image_return != NULL) {
3883       XPutImage(mainDisplay,*pixmap_return,xpmGC,*image_return,0,0,0,0,w,h);
3884    }
3885    if (bitmap_return != NULL && bitmap_image_return != NULL) {
3886       XPutImage(mainDisplay, *bitmap_return, xbmGC, *bitmap_image_return,
3887             0, 0, 0, 0, w, h);
3888    }
3889    if (image_w_return != NULL) *image_w_return = w;
3890    if (image_h_return != NULL) *image_h_return = h;
3891    if (w_return != NULL) *w_return = (int)(((float)w) * mag);
3892    if (h_return != NULL) *h_return = (int)(((float)h) * mag);
3893    if (pixels != NULL) {
3894       int new_ncolors=0;
3895 
3896       for (i=0; i < *ncolors_return; i++) {
3897          if (pixels_used[i]) {
3898             new_ncolors++;
3899          }
3900       }
3901       if (new_ncolors < *ncolors_return) {
3902          /* some pixels are not used */
3903          char *new_color_char=(char*)malloc(
3904                new_ncolors*chars_per_pixel*sizeof(char));
3905          char **new_color_str=(char**)malloc(new_ncolors*sizeof(char *));
3906          int *new_pixels=(int*)malloc(new_ncolors*sizeof(int));
3907 
3908          if (new_color_char == NULL || new_color_str == NULL ||
3909                new_pixels == NULL) {
3910             FailAllocMessage();
3911          } else {
3912             int new_index=0, ok=TRUE;
3913 
3914             for (i=0; i < *ncolors_return; i++) {
3915                if (pixels_used[i]) {
3916                   int j;
3917 
3918                   strncpy(&new_color_char[new_index*chars_per_pixel],
3919                         &(*color_char)[i*chars_per_pixel],
3920                         chars_per_pixel*sizeof(char));
3921                   new_color_str[new_index] = UtilStrDup((*color_str)[i]);
3922                   if (new_color_str[new_index] == NULL) {
3923                      for (j=0; j < i; j++) {
3924                         free(new_color_str[j]);
3925                      }
3926                      free(new_color_char);
3927                      free(new_color_str);
3928                      free(new_pixels);
3929                      new_color_char = NULL;
3930                      new_color_str = NULL;
3931                      new_pixels = NULL;
3932                      ok = FALSE;
3933                      break;
3934                   }
3935                   new_pixels[new_index] = (*pixels)[i];
3936                   new_index++;
3937                }
3938             }
3939             if (ok) {
3940                free(*color_char);
3941                *color_char = new_color_char;
3942                for (i=0; i < *ncolors_return; i++) {
3943                   free((*color_str)[i]);
3944                }
3945                free(*color_str);
3946                *color_str = new_color_str;
3947                free(*pixels);
3948                *pixels = new_pixels;
3949                if (first_pixel_is_bg_return != NULL &&
3950                      *first_pixel_is_bg_return && pixels_used[0]) {
3951                   *first_pixel_is_bg_return = FALSE;
3952                }
3953                new_color_char = NULL;
3954                new_color_str = NULL;
3955                new_pixels = NULL;
3956                *ncolors_return = new_ncolors;
3957             }
3958          }
3959          if (new_color_char != NULL) free(new_color_char);
3960          if (new_color_str != NULL) free(new_color_str);
3961          if (new_pixels != NULL) free(new_pixels);
3962       }
3963    }
3964    if (pixels_used != NULL) free(pixels_used);
3965    gnNumNewColorsInPixmapFile = maxColors - saved_max_colors;
3966    if (gnNumNewColorsInPixmapFile != 0) {
3967       sprintf(gszMsgBox, TgLoadCachedString(CSTID_GIVEN_ADDTNL_COLOR_ALLOCATED),
3968             gnNumNewColorsInPixmapFile);
3969       Msg(gszMsgBox);
3970    }
3971    return BitmapSuccess;
3972 }
3973 
ReadXPmObj(FP,Inbuf,ObjPtr)3974 void ReadXPmObj(FP, Inbuf, ObjPtr)
3975    FILE *FP;
3976    char *Inbuf;
3977    struct ObjRec **ObjPtr;
3978 {
3979    struct XPmRec *xpm_ptr;
3980    char color_s[40], trans_color_s[40], *s, inbuf[MAXSTRING], *c_ptr, *line;
3981    int ltx, lty, rbx, rby, i, j, k, image_w, image_h;
3982    int ncolors, * pixels, len, index, fill, color_index;
3983    int *red=NULL, *green=NULL, *blue=NULL;
3984    int unrecognized_color = FALSE, rotation, chars_per_pixel;
3985    int first_pixel_is_bg, first_pixel_maybe_bg, new_alloc;
3986    int id=0, rotate=ROTATE0, flip=NO_FLIP, locked=FALSE;
3987    int compressed=FALSE, real_x=0, real_y=0;
3988    int transformed=FALSE, invisible=FALSE, bg_pixel;
3989    char *xpm_data=NULL, *color_char, **color_str;
3990    Pixmap pixmap=None, bitmap=None;
3991    XImage *image=NULL, *bitmap_image=NULL;
3992    struct XfrmMtrxRec *ctm=NULL;
3993    struct BBRec orig_obbox;
3994 
3995    *ObjPtr = NULL;
3996 
3997    s = FindChar((int)'(', Inbuf);
3998    s = ParseStr(s, (int)',', color_s, sizeof(color_s));
3999    if (fileVersion >= 37) {
4000       s = ParseStr(s, (int)',', trans_color_s, sizeof(trans_color_s));
4001    }
4002    InitScan(s, "\t\n, ");
4003 
4004    rotation = 0;
4005    chars_per_pixel = 1;
4006    first_pixel_maybe_bg = TRUE;
4007    first_pixel_is_bg = TRUE;
4008    if (fileVersion <= 9) {
4009       sprintf(gszMsgBox, TgLoadCachedString(CSTID_INVALID_FILEVER_FOR_XPM),
4010             fileVersion);
4011       if (PRTGIF) {
4012          fprintf(stderr, "%s\n", gszMsgBox);
4013       } else {
4014          Msg(gszMsgBox);
4015       }
4016       return;
4017    } else if (fileVersion <= 13) {
4018       if (GETINT("xpixmap", ltx,      "ltx") == INVALID ||
4019           GETINT("xpixmap", lty,      "lty") == INVALID ||
4020           GETINT("xpixmap", rbx,      "rbx") == INVALID ||
4021           GETINT("xpixmap", rby,      "rby") == INVALID ||
4022           GETINT("xpixmap", fill,     "fill") == INVALID ||
4023           GETINT("xpixmap", ncolors,  "ncolors") == INVALID ||
4024           GETINT("xpixmap", id,       "id") == INVALID) {
4025          return;
4026       }
4027       if (id >= objId) objId = id+1;
4028    } else if (fileVersion <= 14) {
4029       if (GETINT("xpixmap", ltx,      "ltx") == INVALID ||
4030           GETINT("xpixmap", lty,      "lty") == INVALID ||
4031           GETINT("xpixmap", rbx,      "rbx") == INVALID ||
4032           GETINT("xpixmap", rby,      "rby") == INVALID ||
4033           GETINT("xpixmap", fill,     "fill") == INVALID ||
4034           GETINT("xpixmap", ncolors,  "ncolors") == INVALID ||
4035           GETINT("xpixmap", id,       "id") == INVALID ||
4036           GETINT("xpixmap", rotation, "rotation") == INVALID) {
4037          return;
4038       }
4039       if (id >= objId) objId = id+1;
4040    } else if (fileVersion <= 22) {
4041       if (GETINT("xpixmap", ltx,              "ltx") == INVALID ||
4042           GETINT("xpixmap", lty,              "lty") == INVALID ||
4043           GETINT("xpixmap", rbx,              "rbx") == INVALID ||
4044           GETINT("xpixmap", rby,              "rby") == INVALID ||
4045           GETINT("xpixmap", fill,             "fill") == INVALID ||
4046           GETINT("xpixmap", ncolors,          "ncolors") == INVALID ||
4047           GETINT("xpixmap", chars_per_pixel,  "chars_per_pixel") == INVALID ||
4048           GETINT("xpixmap", first_pixel_is_bg,"first_pixel_is_bg") == INVALID ||
4049           GETINT("xpixmap", id,               "id") == INVALID ||
4050           GETINT("xpixmap", rotation,         "rotation") == INVALID) {
4051          return;
4052       }
4053       if (id >= objId) objId = id+1;
4054       first_pixel_maybe_bg = FALSE;
4055    } else if (fileVersion <= 25) {
4056       if (GETINT("xpixmap", ltx,              "ltx") == INVALID ||
4057           GETINT("xpixmap", lty,              "lty") == INVALID ||
4058           GETINT("xpixmap", rbx,              "rbx") == INVALID ||
4059           GETINT("xpixmap", rby,              "rby") == INVALID ||
4060           GETINT("xpixmap", fill,             "fill") == INVALID ||
4061           GETINT("xpixmap", ncolors,          "ncolors") == INVALID ||
4062           GETINT("xpixmap", chars_per_pixel,  "chars_per_pixel") == INVALID ||
4063           GETINT("xpixmap", first_pixel_is_bg,"first_pixel_is_bg") == INVALID ||
4064           GETINT("xpixmap", id,               "id") == INVALID ||
4065           GETINT("xpixmap", rotation,         "rotation") == INVALID ||
4066           GETINT("xpixmap", image_w,          "image_w") == INVALID ||
4067           GETINT("xpixmap", image_h,          "image_h") == INVALID ||
4068           GETINT("xpixmap", rotate,           "rotate") == INVALID ||
4069           GETINT("xpixmap", flip,             "flip") == INVALID) {
4070          return;
4071       }
4072       if (id >= objId) objId = id+1;
4073       first_pixel_maybe_bg = FALSE;
4074    } else if (fileVersion <= 32) {
4075       if (GETINT("xpixmap", ltx,              "ltx") == INVALID ||
4076           GETINT("xpixmap", lty,              "lty") == INVALID ||
4077           GETINT("xpixmap", rbx,              "rbx") == INVALID ||
4078           GETINT("xpixmap", rby,              "rby") == INVALID ||
4079           GETINT("xpixmap", fill,             "fill") == INVALID ||
4080           GETINT("xpixmap", ncolors,          "ncolors") == INVALID ||
4081           GETINT("xpixmap", chars_per_pixel,  "chars_per_pixel") == INVALID ||
4082           GETINT("xpixmap", first_pixel_is_bg,"first_pixel_is_bg") == INVALID ||
4083           GETINT("xpixmap", id,               "id") == INVALID ||
4084           GETINT("xpixmap", rotation,         "rotation") == INVALID ||
4085           GETINT("xpixmap", image_w,          "image_w") == INVALID ||
4086           GETINT("xpixmap", image_h,          "image_h") == INVALID ||
4087           GETINT("xpixmap", rotate,           "rotate") == INVALID ||
4088           GETINT("xpixmap", flip,             "flip") == INVALID ||
4089           GETINT("xpixmap", locked,           "locked") == INVALID) {
4090          return;
4091       }
4092       if (id >= objId) objId = id+1;
4093       first_pixel_maybe_bg = FALSE;
4094    } else {
4095       if (GETINT("xpixmap", ltx,              "ltx") == INVALID ||
4096           GETINT("xpixmap", lty,              "lty") == INVALID ||
4097           GETINT("xpixmap", rbx,              "rbx") == INVALID ||
4098           GETINT("xpixmap", rby,              "rby") == INVALID ||
4099           GETINT("xpixmap", fill,             "fill") == INVALID ||
4100           GETINT("xpixmap", ncolors,          "ncolors") == INVALID ||
4101           GETINT("xpixmap", chars_per_pixel,  "chars_per_pixel") == INVALID ||
4102           GETINT("xpixmap", first_pixel_is_bg,"first_pixel_is_bg") == INVALID ||
4103           GETINT("xpixmap", id,               "id") == INVALID ||
4104           GETINT("xpixmap", rotation,         "rotation") == INVALID ||
4105           GETINT("xpixmap", image_w,          "image_w") == INVALID ||
4106           GETINT("xpixmap", image_h,          "image_h") == INVALID ||
4107           GETINT("xpixmap", rotate,           "rotate") == INVALID ||
4108           GETINT("xpixmap", flip,             "flip") == INVALID ||
4109           GETINT("xpixmap", locked,           "locked") == INVALID ||
4110           GETINT("xpixmap", compressed,       "compressed") == INVALID ||
4111           GETINT("xpixmap", transformed,      "transformed") == INVALID ||
4112           GETINT("xpixmap", invisible,        "invisible") == INVALID) {
4113          return;
4114       }
4115       if (id >= objId) objId = id+1;
4116       first_pixel_maybe_bg = FALSE;
4117    }
4118    if (fileVersion <= 22) {
4119       image_w = rbx-ltx;
4120       image_h = rby-lty;
4121       rotate = ROTATE0;
4122       flip = 0;
4123    }
4124    if (fileVersion >= 33 && transformed) {
4125       (void)fgets(inbuf, MAXSTRING, FP);
4126       scanLineNum++;
4127       InitScan(inbuf, "\t\n, ");
4128 
4129       ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
4130       if (ctm == NULL) FailAllocMessage();
4131       if (GETINT("xpixmap", real_x,           "real_x") == INVALID ||
4132           GETINT("xpixmap", real_y,           "real_y") == INVALID ||
4133           GETINT("xpixmap", orig_obbox.ltx,   "orig_obbox.ltx") == INVALID ||
4134           GETINT("xpixmap", orig_obbox.lty,   "orig_obbox.lty") == INVALID ||
4135           GETINT("xpixmap", orig_obbox.rbx,   "orig_obbox.rbx") == INVALID ||
4136           GETINT("xpixmap", orig_obbox.rby,   "orig_obbox.rby") == INVALID ||
4137           GETDBL("xpixmap", ctm->m[CTM_SX],   "CTM_SX") == INVALID ||
4138           GETDBL("xpixmap", ctm->m[CTM_SIN],  "CTM_SIN") == INVALID ||
4139           GETDBL("xpixmap", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
4140           GETDBL("xpixmap", ctm->m[CTM_SY],   "CTM_SY") == INVALID ||
4141           GETINT("xpixmap", ctm->t[CTM_TX],   "CTM_TX") == INVALID ||
4142           GETINT("xpixmap", ctm->t[CTM_TY],   "CTM_TY") == INVALID) {
4143          return;
4144       }
4145    }
4146    fill = UpgradePenFill(fill);
4147 
4148    *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
4149    if (*ObjPtr == NULL) FailAllocMessage();
4150    memset(*ObjPtr, 0, sizeof(struct ObjRec));
4151    xpm_ptr = (struct XPmRec *)malloc(sizeof(struct XPmRec));
4152    if (xpm_ptr == NULL) FailAllocMessage();
4153    memset(xpm_ptr, 0, sizeof(struct XPmRec));
4154 
4155    color_index = QuickFindColorIndex(*ObjPtr, color_s, &new_alloc, TRUE);
4156 
4157    (*ObjPtr)->color = color_index;
4158    if (mainDisplay != NULL) {
4159       UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str),
4160             colorMenuItems[color_index]);
4161    }
4162    (*ObjPtr)->dirty = FALSE;
4163    (*ObjPtr)->id = id;
4164    (*ObjPtr)->rotation = rotation;
4165    (*ObjPtr)->locked = locked;
4166    (*ObjPtr)->type = OBJ_XPM;
4167    (*ObjPtr)->obbox.ltx = (*ObjPtr)->bbox.ltx = (*ObjPtr)->x = ltx;
4168    (*ObjPtr)->obbox.lty = (*ObjPtr)->bbox.lty = (*ObjPtr)->y = lty;
4169    (*ObjPtr)->obbox.rbx = (*ObjPtr)->bbox.rbx = rbx;
4170    (*ObjPtr)->obbox.rby = (*ObjPtr)->bbox.rby = rby;
4171    (*ObjPtr)->detail.xpm = xpm_ptr;
4172    (*ObjPtr)->ctm = ctm;
4173    (*ObjPtr)->invisible = invisible;
4174 
4175    if (ctm != NULL) {
4176       memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
4177       (*ObjPtr)->x = real_x;
4178       (*ObjPtr)->y = real_y;
4179       GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
4180    }
4181    color_char = (char*)malloc(ncolors*chars_per_pixel*sizeof(char));
4182    color_str = (char**)malloc(ncolors*sizeof(char*));
4183    pixels = (int*)malloc(ncolors*sizeof(int));
4184    if (color_char == NULL || color_str == NULL || pixels == NULL) {
4185       FailAllocMessage();
4186    }
4187    if (fileVersion >= 25 && ((PRTGIF && !cmdLineOpenDisplay) ||
4188          !colorDisplay)) {
4189       red = (int*)malloc(ncolors*sizeof(int));
4190       green = (int*)malloc(ncolors*sizeof(int));
4191       blue = (int*)malloc(ncolors*sizeof(int));
4192       if (red == NULL || green == NULL || blue == NULL) FailAllocMessage();
4193    }
4194    xpm_ptr->pixmap = None;
4195    xpm_ptr->image = NULL;
4196    xpm_ptr->bitmap = None;
4197    xpm_ptr->bitmap_image = NULL;
4198    xpm_ptr->cached_pixmap = None;
4199    xpm_ptr->cached_bitmap = None;
4200    xpm_ptr->cached_zoom = 0;
4201    xpm_ptr->data = NULL;
4202    xpm_ptr->fill = fill;
4203    xpm_ptr->flip = flip;
4204    xpm_ptr->cached_flip = 0;
4205    xpm_ptr->cached_w = xpm_ptr->cached_h = 0;
4206    xpm_ptr->cached_color = (-1);
4207    xpm_ptr->image_w = image_w;
4208    xpm_ptr->image_h = image_h;
4209 
4210    xpm_ptr->ncolors = ncolors;
4211    xpm_ptr->chars_per_pixel = chars_per_pixel;
4212    xpm_ptr->first_pixel_is_bg = first_pixel_is_bg;
4213    xpm_ptr->color_char = color_char;
4214    xpm_ptr->color_str = color_str;
4215    xpm_ptr->pixels = pixels;
4216    xpm_ptr->red = red;
4217    xpm_ptr->green = green;
4218    xpm_ptr->blue = blue;
4219 
4220    bg_pixel = GetDrawingBgPixel(INVALID, INVALID);
4221    for (i=0; i < ncolors; i++) {
4222       (void)fgets(inbuf, MAXSTRING, FP);
4223       scanLineNum++;
4224       c_ptr = FindChar((int)'"', inbuf);
4225       for (j = 0; j < chars_per_pixel; j++) {
4226          color_char[i*chars_per_pixel+j] = c_ptr[j];
4227       }
4228       c_ptr = FindChar((int)'"', c_ptr);
4229       c_ptr = FindChar((int)'"', c_ptr);
4230       c_ptr = ParseStr(c_ptr, (int)'"', color_s, sizeof(color_s));
4231       if (!PRTGIF || cmdLineOpenDisplay) {
4232          if (i == 0 && (first_pixel_is_bg || (first_pixel_maybe_bg &&
4233                (color_char[i]=='`' || color_char[i]==' ')))) {
4234             strcpy(color_s, (myFileBgColorStr==NULL ? myBgColorStr :
4235                   myFileBgColorStr));
4236             pixels[i] = bg_pixel;
4237             xpm_ptr->first_pixel_is_bg = first_pixel_is_bg = TRUE;
4238          } else if (UtilStrICmp(color_s, "None") == 0) {
4239             pixels[i] = (-1);
4240          } else if ((index = QuickFindColorIndex(NULL, color_s, &new_alloc,
4241                TRUE)) == INVALID) {
4242             sprintf(gszMsgBox,
4243                   TgLoadCachedString(CSTID_CANNOT_ALLOC_COLOR_USE_ALT),
4244                   color_s, colorMenuItems[colorIndex]);
4245             Msg(gszMsgBox);
4246             allocColorFailed = TRUE;
4247             strcpy(color_s, colorMenuItems[colorIndex]);
4248             pixels[i] = colorPixels[colorIndex];
4249          } else {
4250             pixels[i] = colorPixels[index];
4251          }
4252 
4253          len = strlen(color_s);
4254          color_str[i] = (char*)malloc((len+1)*sizeof(char));
4255          if (color_str[i] == NULL) FailAllocMessage();
4256          strcpy(color_str[i], color_s);
4257       }
4258       if (fileVersion >= 25 && ((PRTGIF && !cmdLineOpenDisplay) ||
4259             !colorDisplay)) {
4260          /* has RGB information for PRTGIF */
4261          InitScan(c_ptr, "\t\n, ");
4262 
4263          if (GETINT("xpixmap", red[i],   "red") == INVALID ||
4264              GETINT("xpixmap", green[i], "green") == INVALID ||
4265              GETINT("xpixmap", blue[i],  "blue") == INVALID) {
4266             return;
4267          }
4268          if (UtilStrICmp(color_s, "None") == 0) {
4269             red[i] = green[i] = blue[i] = (-1);
4270          } else if (PRTGIF && cmdLineColor && (prTgifFoundColorInfo ||
4271                !cmdLineOpenDisplay)) {
4272             int found_index=PrTgifFindColorIndex(NULL, color_s);
4273 
4274             if (found_index != INVALID) {
4275                red[i] =
4276                      (int)(10000*((int)tgifColors[found_index].red)/maxRGB);
4277                green[i] =
4278                      (int)(10000*((int)tgifColors[found_index].green)/maxRGB);
4279                blue[i] =
4280                      (int)(10000*((int)tgifColors[found_index].blue)/maxRGB);
4281             }
4282          }
4283       }
4284    }
4285    xpm_ptr->clip_mask = None;
4286 
4287    if (PRTGIF && !cmdLineOpenDisplay) {
4288       xpm_data = (char*)malloc(image_w*image_h*chars_per_pixel*sizeof(char));
4289       if (xpm_data == NULL) FailAllocMessage();
4290       xpm_ptr->data = xpm_data;
4291 
4292       line = (char*)malloc((image_w*chars_per_pixel+20)*sizeof(char));
4293       if (line == NULL) FailAllocMessage();
4294       for (i=0; i < image_h; i++, xpm_data += image_w*chars_per_pixel) {
4295          (void)fgets(line, image_w*chars_per_pixel+20, FP);
4296          scanLineNum++;
4297          c_ptr = &line[4];
4298          strncpy(xpm_data, c_ptr, image_w*chars_per_pixel);
4299       }
4300       free(line);
4301    } else {
4302       if (fileVersion >= 25 && !colorDisplay) {
4303          xpm_data = (char*)malloc(image_w*image_h*chars_per_pixel*sizeof(char));
4304          if (xpm_data == NULL) FailAllocMessage();
4305          xpm_ptr->data = xpm_data;
4306       }
4307       pixmap = XCreatePixmap(mainDisplay, dummyPixmap, image_w, image_h,
4308             mainDepth);
4309       bitmap = XCreatePixmap(mainDisplay, dummyPixmap, image_w, image_h, 1);
4310       XFillRectangle(mainDisplay, pixmap, xpmGC, 0, 0, image_w, image_h);
4311       XSetForeground(mainDisplay, xbmGC, 1);
4312       XFillRectangle(mainDisplay, bitmap, xbmGC, 0, 0, image_w, image_h);
4313       XSetForeground(mainDisplay, xbmGC, 0);
4314       image = XGetImage(mainDisplay, pixmap, 0, 0, image_w, image_h, AllPlanes,
4315             ZPixmap);
4316       bitmap_image = XGetImage(mainDisplay, bitmap, 0, 0, image_w, image_h, 1,
4317             ZPixmap);
4318       if (image == NULL || bitmap_image == NULL) {
4319          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
4320                INFO_MB);
4321          XFreePixmap(mainDisplay, pixmap);
4322          XFreePixmap(mainDisplay, bitmap);
4323          if (image != NULL) XDestroyImage(image);
4324          if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4325          return;
4326       }
4327       if (!BuildXPmBuckets(ncolors, NULL, NULL, chars_per_pixel, color_char,
4328             NULL)) {
4329          XFreePixmap(mainDisplay, pixmap);
4330          XFreePixmap(mainDisplay, bitmap);
4331          if (image != NULL) XDestroyImage(image);
4332          if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4333          return;
4334       }
4335       line = (char*)malloc((image_w*chars_per_pixel+20)*sizeof(char));
4336       if (line == NULL) FailAllocMessage();
4337       for (i=0; i < image_h; i++) {
4338          (void)fgets(line, image_w*chars_per_pixel+20, FP);
4339          scanLineNum++;
4340          c_ptr = &line[4];
4341          if (xpm_data != NULL) {
4342             strncpy(xpm_data, c_ptr, image_w*chars_per_pixel);
4343          }
4344          for (j = 0; j < image_w; j++, c_ptr+=chars_per_pixel) {
4345             k = XPmLookUp(INVALID, chars_per_pixel, c_ptr, NULL);
4346             if (k == INVALID) {
4347                XPutPixel(image, j, i, pixels[0]);
4348                unrecognized_color = TRUE;
4349             } else if (pixels[k] == (-1)) {
4350                XPutPixel(bitmap_image, j, i, 0);
4351                XPutPixel(image, j, i, colorPixels[color_index]);
4352             } else {
4353                XPutPixel(image, j, i, pixels[k]);
4354             }
4355          }
4356          if (xpm_data != NULL) xpm_data += image_w*chars_per_pixel;
4357       }
4358       free(line);
4359       XPutImage(mainDisplay,pixmap,xpmGC,image,0,0,0,0,image_w,image_h);
4360       XPutImage(mainDisplay,bitmap,xbmGC,bitmap_image,0,0,0,0,image_w,image_h);
4361       xpm_ptr->pixmap = pixmap;
4362       xpm_ptr->image = image;
4363       xpm_ptr->bitmap = bitmap;
4364       xpm_ptr->bitmap_image = bitmap_image;
4365 
4366       if (unrecognized_color) {
4367          sprintf(gszMsgBox,
4368                TgLoadCachedString(CSTID_COLOR_SUBS_FOR_UNRECOG_IN_XPM),
4369                color_str[0]);
4370          Msg(gszMsgBox);
4371       }
4372    }
4373    if (fileVersion < 33 && (rotate != ROTATE0 || flip != NO_FLIP)) {
4374       double dz=(double)0.0, d1=(double)1000.0, dm1=((double)-1000.0);
4375 
4376       if (rotate == ROTATE90 || rotate == ROTATE270) {
4377          int h=(*ObjPtr)->obbox.rbx-(*ObjPtr)->obbox.ltx;
4378          int w=(*ObjPtr)->obbox.rby-(*ObjPtr)->obbox.lty;
4379 
4380          (*ObjPtr)->obbox.rby = (*ObjPtr)->obbox.lty + h;
4381          (*ObjPtr)->obbox.rbx = (*ObjPtr)->obbox.ltx + w;
4382       }
4383       ltx = ((*ObjPtr)->obbox.ltx);
4384       lty = ((*ObjPtr)->obbox.lty);
4385       SetRotatePivotByObject(*ObjPtr);
4386 
4387       if (flip & HORI_EVEN) {
4388          ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1, &ltx, &lty);
4389       }
4390       if (flip & VERT_EVEN) {
4391          ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1, &ltx, &lty);
4392       }
4393       if (rotate == ROTATE0) {
4394          if (flip & (HORI_ODD | VERT_ODD)) {
4395             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4396             if (flip & HORI_ODD) {
4397                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1, &ltx, &lty);
4398             }
4399             if (flip & VERT_ODD) {
4400                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1, &ltx, &lty);
4401             }
4402             RotateObj(*ObjPtr, CORNER_LT, COUNTER90, &ltx, &lty);
4403          }
4404       } else {
4405          switch (rotate) {
4406          case ROTATE90:
4407             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4408             if (flip & HORI_ODD) {
4409                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1, &ltx, &lty);
4410             }
4411             if (flip & VERT_ODD) {
4412                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1, &ltx, &lty);
4413             }
4414             break;
4415          case ROTATE180:
4416             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4417             if (flip & HORI_ODD) {
4418                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1, &ltx, &lty);
4419             }
4420             if (flip & VERT_ODD) {
4421                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1, &ltx, &lty);
4422             }
4423             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4424             break;
4425          case ROTATE270:
4426             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4427             if (flip & HORI_ODD) {
4428                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1, &ltx, &lty);
4429             }
4430             if (flip & VERT_ODD) {
4431                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1, &ltx, &lty);
4432             }
4433             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4434             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
4435             break;
4436          }
4437       }
4438       xpm_ptr->flip = NO_FLIP;
4439    }
4440 }
4441 
4442 static
MyReadJpegFileSkipData(jpeg_filename,expected_image_w,expected_image_h)4443 struct ObjRec *MyReadJpegFileSkipData(jpeg_filename, expected_image_w,
4444       expected_image_h)
4445    char *jpeg_filename;
4446    int expected_image_w, expected_image_h;
4447 {
4448    FILE *ppm_fp=NULL;
4449    char tmp_fname[MAXPATHLENGTH+1];
4450    int rc=0, format=0, image_w=0, image_h=0, max_val=0;
4451    struct ObjRec *obj_ptr=NULL;
4452 
4453    SetWatchCursor(drawWindow);
4454    SetWatchCursor(mainWindow);
4455    SaveStatusStrings();
4456    rc = ConvertJpegToPpm6(jpeg_filename, tmp_fname, sizeof(tmp_fname));
4457    RestoreStatusStrings();
4458    SetDefaultCursor(mainWindow);
4459    ShowCursor();
4460    if (!rc) {
4461       return NULL;
4462    }
4463    ppm_fp = fopen(tmp_fname, "r");
4464    if (ppm_fp == NULL) {
4465       FailToOpenMessage(tmp_fname, "r", NULL);
4466       return NULL;
4467    }
4468    if (!ReadPpmHeader(ppm_fp, tmp_fname, &format, &image_w, &image_h,
4469          &max_val)) {
4470       fclose(ppm_fp);
4471       return NULL;
4472    }
4473    fclose(ppm_fp);
4474 
4475    if (expected_image_w != (-1) && expected_image_h != (-1) &&
4476          (image_w != expected_image_w || image_h != expected_image_h)) {
4477       sprintf(gszMsgBox, TgLoadString(STID_JPEG_DIM_NOT_MATCH_DELETED), image_w,
4478             image_h, jpeg_filename, expected_image_w, expected_image_h);
4479       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4480       return NULL;
4481    }
4482    obj_ptr = CreateXPmObj(image_w, image_h, image_w, image_h, None, NULL, None,
4483          NULL, (-1), 1, FALSE, NULL, NULL, NULL, NULL);
4484 
4485    unlink(tmp_fname);
4486 
4487    return obj_ptr;
4488 }
4489 
4490 static
MyReadJpegFile(jpeg_filename,expected_image_w,expected_image_h)4491 struct ObjRec *MyReadJpegFile(jpeg_filename, expected_image_w, expected_image_h)
4492    char *jpeg_filename;
4493    int expected_image_w, expected_image_h;
4494 {
4495    char tmp_fname[MAXPATHLENGTH+1];
4496    int rc=0, ncolors=0, chars_per_pixel=0, *pixels=NULL;
4497    int first_pixel_is_bg=FALSE, image_w=0, image_h=0, w=0, h=0;
4498    Pixmap pixmap=None, bitmap=None;
4499    XImage *image=NULL, *bitmap_image=NULL;
4500    char *color_char, **color_str=NULL, *xpm_data=NULL;
4501    struct ObjRec *obj_ptr=NULL;
4502 
4503    if (fullTrueColorMode && HasZlibSupport()) {
4504       struct XPmRec *xpm_ptr=NULL;
4505       char ppm6_fname[MAXPATHLENGTH+1];
4506 
4507       rc = ConvertJpegToPpm6(jpeg_filename, ppm6_fname, sizeof(ppm6_fname));
4508       if (!rc) return NULL;
4509 
4510       ResetPngHeaderInfo(&gPngHeaderInfo);
4511       obj_ptr = CreatePpmTrueObjFromFile(ppm6_fname);
4512       unlink(ppm6_fname);
4513 
4514       if (obj_ptr == NULL) return NULL;
4515 
4516       xpm_ptr = obj_ptr->detail.xpm;
4517       xpm_ptr->real_type = PPM_TRUE;
4518       xpm_ptr->ppm_data_compress = PPM_JPEG_COMPRESS;
4519       xpm_ptr->ppm_data = ReadFileIntoBuf( jpeg_filename,
4520             &xpm_ptr->ppm_data_size);
4521       xpm_ptr->ppm_mask_data = NULL;
4522       xpm_ptr->ppm_mask_size = 0;
4523 
4524       if (expected_image_w != (-1) && expected_image_h != (-1) &&
4525             (xpm_ptr->image_w != expected_image_w ||
4526             xpm_ptr->image_h != expected_image_h)) {
4527          sprintf(gszMsgBox, TgLoadString(STID_JPEG_DIM_NOT_MATCH_DELETED),
4528                xpm_ptr->image_w, xpm_ptr->image_h, jpeg_filename,
4529                expected_image_w, expected_image_h);
4530          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4531          return NULL;
4532       }
4533       return obj_ptr;
4534    }
4535    SetWatchCursor(drawWindow);
4536    SetWatchCursor(mainWindow);
4537    SaveStatusStrings();
4538    *tmp_fname = '\0';
4539    rc = ConvertJpegToXpm(jpeg_filename, tmp_fname, sizeof(tmp_fname));
4540    RestoreStatusStrings();
4541    SetDefaultCursor(mainWindow);
4542    ShowCursor();
4543    if (!rc) {
4544       return NULL;
4545    }
4546    SetWatchCursor(drawWindow);
4547    SetWatchCursor(mainWindow);
4548    rc = MyReadPixmapFile(tmp_fname,
4549          &image_w, &image_h, &w, &h, &pixmap, &image, &bitmap, &bitmap_image,
4550          &ncolors, &chars_per_pixel, &first_pixel_is_bg, &color_char,
4551          &color_str, &pixels, &xpm_data);
4552    SetDefaultCursor(mainWindow);
4553    ShowCursor();
4554 
4555    if (rc != BitmapSuccess) {
4556       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_IMPORT_XPM_FILE), tmp_fname);
4557       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4558       return NULL;
4559    }
4560    if (expected_image_w != (-1) && expected_image_h != (-1) &&
4561          (image_w != expected_image_w || image_h != expected_image_h)) {
4562       sprintf(gszMsgBox, TgLoadString(STID_JPEG_DIM_NOT_MATCH_DELETED), image_w,
4563             image_h, jpeg_filename, expected_image_w, expected_image_h);
4564       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4565       return NULL;
4566    }
4567    obj_ptr = CreateXPmObj(image_w, image_h, w, h, pixmap, image, bitmap,
4568          bitmap_image, ncolors, chars_per_pixel, first_pixel_is_bg, color_char,
4569          color_str, pixels, xpm_data);
4570 
4571    unlink(tmp_fname);
4572 
4573    return obj_ptr;
4574 }
4575 
ReadJpegObj(FP,Inbuf,ObjPtr)4576 void ReadJpegObj(FP, Inbuf, ObjPtr)
4577    FILE *FP;
4578    char *Inbuf;
4579    struct ObjRec **ObjPtr;
4580 {
4581    struct XPmRec *xpm_ptr=NULL;
4582    char color_s[40], trans_color_s[40], *s=NULL, inbuf[MAXSTRING];
4583    char *jpeg_filename=NULL;
4584    int ltx, lty, rbx, rby, image_w=0, image_h=0;
4585    int ncolors, fill, color_index;
4586    int rotation, chars_per_pixel;
4587    int first_pixel_is_bg, first_pixel_maybe_bg, new_alloc;
4588    int id=0, rotate=ROTATE0, flip=NO_FLIP, locked=FALSE;
4589    int compressed=FALSE, real_x=0, real_y=0, real_type=0, linked_jpeg=FALSE;
4590    int transformed=FALSE, invisible=FALSE;
4591    struct XfrmMtrxRec *ctm=NULL;
4592    struct BBRec orig_obbox;
4593    struct ObjRec *new_obj_ptr=NULL;
4594 
4595    *ObjPtr = NULL;
4596 
4597    s = FindChar((int)'(', Inbuf);
4598    s = ParseStr(s, (int)',', color_s, sizeof(color_s));
4599    if (fileVersion >= 37) {
4600       s = ParseStr(s, (int)',', trans_color_s, sizeof(trans_color_s));
4601    }
4602    InitScan(s, "\t\n, ");
4603 
4604    rotation = 0;
4605    chars_per_pixel = 1;
4606    first_pixel_maybe_bg = TRUE;
4607    first_pixel_is_bg = TRUE;
4608    if (fileVersion < 37) {
4609       sprintf(gszMsgBox,
4610             TgLoadCachedString(CSTID_INVALID_FILEVER_FOR_LINK_JPEG),
4611             fileVersion);
4612       if (PRTGIF) {
4613          fprintf(stderr, "%s\n", gszMsgBox);
4614       } else {
4615          Msg(gszMsgBox);
4616       }
4617       return;
4618    } else {
4619       if (GETINT("jpeg", ltx,              "ltx") == INVALID ||
4620           GETINT("jpeg", lty,              "lty") == INVALID ||
4621           GETINT("jpeg", rbx,              "rbx") == INVALID ||
4622           GETINT("jpeg", rby,              "rby") == INVALID ||
4623           GETINT("jpeg", fill,             "fill") == INVALID ||
4624           GETINT("jpeg", ncolors,          "ncolors") == INVALID ||
4625           GETINT("jpeg", chars_per_pixel,  "chars_per_pixel") == INVALID ||
4626           GETINT("jpeg", first_pixel_is_bg,"first_pixel_is_bg") == INVALID ||
4627           GETINT("jpeg", id,               "id") == INVALID ||
4628           GETINT("jpeg", rotation,         "rotation") == INVALID ||
4629           GETINT("jpeg", image_w,          "image_w") == INVALID ||
4630           GETINT("jpeg", image_h,          "image_h") == INVALID ||
4631           GETINT("jpeg", rotate,           "rotate") == INVALID ||
4632           GETINT("jpeg", flip,             "flip") == INVALID ||
4633           GETINT("jpeg", locked,           "locked") == INVALID ||
4634           GETINT("jpeg", compressed,       "compressed") == INVALID ||
4635           GETINT("jpeg", transformed,      "transformed") == INVALID ||
4636           GETINT("jpeg", invisible,        "invisible") == INVALID ||
4637           GETINT("jpeg", real_type,        "real_type") == INVALID ||
4638           GETINT("jpeg", linked_jpeg,      "linked_jpeg") == INVALID) {
4639          return;
4640       }
4641       if (id >= objId) objId = id+1;
4642       first_pixel_maybe_bg = FALSE;
4643    }
4644    if (real_type == XPM_JPEG && linked_jpeg) {
4645       char *tmp_str=NULL;
4646 
4647       (void)fgets(inbuf, MAXSTRING, FP);
4648       scanLineNum++;
4649 
4650       tmp_str = FindChar((int)'"', inbuf);
4651       s = ReadString(tmp_str);
4652       *(--s) = '\0';
4653       jpeg_filename = UtilStrDup(tmp_str);
4654       if (jpeg_filename == NULL) FailAllocMessage();
4655    } else {
4656       strcpy(gszMsgBox, TgLoadString(STID_INVALID_PARAM_LINKED_JPEG));
4657       if (PRTGIF) {
4658          fprintf(stderr, "%s\n", gszMsgBox);
4659       } else {
4660          Msg(gszMsgBox);
4661       }
4662       return;
4663    }
4664    if (transformed) {
4665       (void)fgets(inbuf, MAXSTRING, FP);
4666       scanLineNum++;
4667       InitScan(inbuf, "\t\n, ");
4668 
4669       ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
4670       if (ctm == NULL) FailAllocMessage();
4671       if (GETINT("xpixmap", real_x,           "real_x") == INVALID ||
4672           GETINT("xpixmap", real_y,           "real_y") == INVALID ||
4673           GETINT("xpixmap", orig_obbox.ltx,   "orig_obbox.ltx") == INVALID ||
4674           GETINT("xpixmap", orig_obbox.lty,   "orig_obbox.lty") == INVALID ||
4675           GETINT("xpixmap", orig_obbox.rbx,   "orig_obbox.rbx") == INVALID ||
4676           GETINT("xpixmap", orig_obbox.rby,   "orig_obbox.rby") == INVALID ||
4677           GETDBL("xpixmap", ctm->m[CTM_SX],   "CTM_SX") == INVALID ||
4678           GETDBL("xpixmap", ctm->m[CTM_SIN],  "CTM_SIN") == INVALID ||
4679           GETDBL("xpixmap", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
4680           GETDBL("xpixmap", ctm->m[CTM_SY],   "CTM_SY") == INVALID ||
4681           GETINT("xpixmap", ctm->t[CTM_TX],   "CTM_TX") == INVALID ||
4682           GETINT("xpixmap", ctm->t[CTM_TY],   "CTM_TY") == INVALID) {
4683          return;
4684       }
4685    }
4686    fill = UpgradePenFill(fill);
4687 
4688    if (!UtilPathExists(jpeg_filename)) {
4689       sprintf(gszMsgBox, TgLoadString(STID_INVALID_PATH_WHILE_READ_JPEG),
4690             jpeg_filename);
4691       if (PRTGIF) {
4692          fprintf(stderr, "%s\n", gszMsgBox);
4693       } else {
4694          Msg(gszMsgBox);
4695       }
4696       if (ctm != NULL) free(ctm);
4697       UtilFree(jpeg_filename);
4698       return;
4699    }
4700    if (PRTGIF && !cmdLineOpenDisplay) {
4701       new_obj_ptr = MyReadJpegFileSkipData(jpeg_filename, image_w, image_h);
4702    } else {
4703       new_obj_ptr = MyReadJpegFile(jpeg_filename, image_w, image_h);
4704    }
4705    if (new_obj_ptr == NULL) return;
4706 
4707    new_obj_ptr->id = id;
4708    MoveObj(new_obj_ptr, ltx, lty);
4709    if (ctm != NULL) {
4710       new_obj_ptr->obbox.ltx = new_obj_ptr->bbox.ltx = new_obj_ptr->x = ltx;
4711       new_obj_ptr->obbox.lty = new_obj_ptr->bbox.lty = new_obj_ptr->y = lty;
4712       new_obj_ptr->obbox.rbx = new_obj_ptr->bbox.rbx = rbx;
4713       new_obj_ptr->obbox.rby = new_obj_ptr->bbox.rby = rby;
4714       new_obj_ptr->ctm = ctm;
4715 
4716       memcpy(&new_obj_ptr->orig_obbox, &orig_obbox, sizeof(struct BBRec));
4717       new_obj_ptr->x = real_x;
4718       new_obj_ptr->y = real_y;
4719       GetTransformedOBBoxOffsetVs(new_obj_ptr, new_obj_ptr->rotated_obbox);
4720    }
4721    xpm_ptr = new_obj_ptr->detail.xpm;
4722 
4723    xpm_ptr->real_type = real_type;
4724    xpm_ptr->linked_jpeg = linked_jpeg;
4725    xpm_ptr->filename = jpeg_filename;
4726 
4727    color_index = QuickFindColorIndex(new_obj_ptr, color_s, &new_alloc, TRUE);
4728    new_obj_ptr->color = color_index;
4729    UtilStrCpyN(new_obj_ptr->color_str, sizeof(new_obj_ptr->color_str), color_s);
4730 
4731    *ObjPtr = new_obj_ptr;
4732 }
4733 
4734 static
MyReadPpmTrueFileSkipData(ppm_fname,expected_image_w,expected_image_h)4735 struct ObjRec *MyReadPpmTrueFileSkipData(ppm_fname, expected_image_w,
4736       expected_image_h)
4737    char *ppm_fname;
4738    int expected_image_w, expected_image_h;
4739 {
4740    FILE *ppm_fp=NULL;
4741    int format=0, image_w=0, image_h=0, max_val=0;
4742    struct ObjRec *obj_ptr=NULL;
4743    struct XPmRec *xpm_ptr=NULL;
4744 
4745    ppm_fp = fopen(ppm_fname, "r");
4746    if (ppm_fp == NULL) {
4747       FailToOpenMessage(ppm_fname, "r", NULL);
4748       return NULL;
4749    }
4750    if (!ReadPpmHeader(ppm_fp, ppm_fname, &format, &image_w, &image_h,
4751          &max_val)) {
4752       fclose(ppm_fp);
4753       return NULL;
4754    }
4755    fclose(ppm_fp);
4756 
4757    if (expected_image_w != (-1) && expected_image_h != (-1) &&
4758          (image_w != expected_image_w || image_h != expected_image_h)) {
4759       sprintf(gszMsgBox, TgLoadString(STID_PPM6_DIM_NOT_MATCH), image_w,
4760             image_h, ppm_fname, expected_image_w, expected_image_h);
4761       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4762       return NULL;
4763    }
4764    obj_ptr = CreateXPmObj(image_w, image_h, image_w, image_h, None, NULL, None,
4765          NULL, (-1), 1, FALSE, NULL, NULL, NULL, NULL);
4766    if (obj_ptr == NULL) return NULL;
4767 
4768    xpm_ptr = obj_ptr->detail.xpm;
4769    UtilStrCpyN(xpm_ptr->tmp_ppm6_fname, sizeof(xpm_ptr->tmp_ppm6_fname),
4770          ppm_fname);
4771    xpm_ptr->real_type = PPM_TRUE;
4772 
4773    return obj_ptr;
4774 }
4775 
4776 static
MyReadPpmFile(ppm_fname,expected_image_w,expected_image_h)4777 struct ObjRec *MyReadPpmFile(ppm_fname, expected_image_w, expected_image_h)
4778    char *ppm_fname;
4779    int expected_image_w, expected_image_h;
4780 {
4781    char tmp_fname[MAXPATHLENGTH+1];
4782    int rc=0, ncolors=0, chars_per_pixel=0, *pixels=NULL;
4783    int first_pixel_is_bg=FALSE, image_w=0, image_h=0, w=0, h=0;
4784    Pixmap pixmap=None, bitmap=None;
4785    XImage *image=NULL, *bitmap_image=NULL;
4786    char *color_char, **color_str=NULL, *xpm_data=NULL;
4787    struct ObjRec *obj_ptr=NULL;
4788 
4789    SetWatchCursor(drawWindow);
4790    SetWatchCursor(mainWindow);
4791    SaveStatusStrings();
4792    rc = ConvertPpmToXpm(ppm_fname, tmp_fname, sizeof(tmp_fname));
4793    RestoreStatusStrings();
4794    SetDefaultCursor(mainWindow);
4795    ShowCursor();
4796    if (!rc) {
4797       return NULL;
4798    }
4799    SetWatchCursor(drawWindow);
4800    SetWatchCursor(mainWindow);
4801    rc = MyReadPixmapFile(tmp_fname,
4802          &image_w, &image_h, &w, &h, &pixmap, &image, &bitmap, &bitmap_image,
4803          &ncolors, &chars_per_pixel, &first_pixel_is_bg, &color_char,
4804          &color_str, &pixels, &xpm_data);
4805    SetDefaultCursor(mainWindow);
4806    ShowCursor();
4807 
4808    if (rc != BitmapSuccess) {
4809       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_IMPORT_XPM_FILE), tmp_fname);
4810       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4811       return NULL;
4812    }
4813    if (expected_image_w != (-1) && expected_image_h != (-1) &&
4814          (image_w != expected_image_w || image_h != expected_image_h)) {
4815       sprintf(gszMsgBox, TgLoadString(STID_PPM6_DIM_NOT_MATCH), image_w,
4816             image_h, ppm_fname, expected_image_w, expected_image_h);
4817       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4818       return NULL;
4819    }
4820    obj_ptr = CreateXPmObj(image_w, image_h, w, h, pixmap, image, bitmap,
4821          bitmap_image, ncolors, chars_per_pixel, first_pixel_is_bg, color_char,
4822          color_str, pixels, xpm_data);
4823 
4824    unlink(tmp_fname);
4825 
4826    return obj_ptr;
4827 }
4828 
SetupTrueColorInfo(ptci)4829 int SetupTrueColorInfo(ptci)
4830    TrueColorInfo *ptci;
4831 {
4832    unsigned int r_mask=0, g_mask=0, b_mask=0;
4833    unsigned int r_maxval=0, g_maxval=0, b_maxval=0;
4834    unsigned int r_bits=0, g_bits=0, b_bits=0;
4835    int r_shift=(-1), g_shift=(-1), b_shift=(-1);
4836    unsigned int shifts=0;
4837 
4838    ptci->r_mask = r_mask = mainVisual->red_mask;
4839    ptci->g_mask = g_mask = mainVisual->green_mask;
4840    ptci->b_mask = b_mask = mainVisual->blue_mask;
4841    for (shifts=0; r_mask|g_mask|b_mask; shifts++) {
4842       if (r_mask & 0x1) {
4843          if (r_shift == (-1)) {
4844             r_shift = shifts;
4845             r_maxval = r_mask;
4846          }
4847          r_bits++;
4848       }
4849       if (g_mask & 0x1) {
4850          if (g_shift == (-1)) {
4851             g_shift = shifts;
4852             g_maxval = g_mask;
4853          }
4854          g_bits++;
4855       }
4856       if (b_mask & 0x1) {
4857          if (b_shift == (-1)) {
4858             b_shift = shifts;
4859             b_maxval = b_mask;
4860          }
4861          b_bits++;
4862       }
4863       r_mask >>= 1;
4864       g_mask >>= 1;
4865       b_mask >>= 1;
4866    }
4867    ptci->r_shift = (unsigned int)r_shift;
4868    ptci->g_shift = (unsigned int)g_shift;
4869    ptci->b_shift = (unsigned int)b_shift;
4870    ptci->dr_maxval = (double)r_maxval;
4871    ptci->dg_maxval = (double)g_maxval;
4872    ptci->db_maxval = (double)b_maxval;
4873    ptci->dr_maxval_div255 = ptci->dr_maxval / ((double)255);
4874    ptci->dg_maxval_div255 = ptci->dg_maxval / ((double)255);
4875    ptci->db_maxval_div255 = ptci->db_maxval / ((double)255);
4876    ptci->num_r_bits = r_bits;
4877    ptci->num_g_bits = g_bits;
4878    ptci->num_b_bits = b_bits;
4879 
4880    if (r_shift==(-1) || g_shift==(-1) || b_shift==(-1)) {
4881 #ifdef _TGIF_DBG /* debug, do not translate */
4882       TgAssert(FALSE, "unexpected error in SetupTrueColorInfo()", NULL);
4883 #endif /* _TGIF_DBG */
4884       return FALSE;
4885    }
4886    return TRUE;
4887 }
4888 
4889 static
MyReadPpmTrueFile2(ppm_fname,expected_image_w,expected_image_h)4890 struct ObjRec *MyReadPpmTrueFile2(ppm_fname, expected_image_w, expected_image_h)
4891    char *ppm_fname;
4892    int expected_image_w, expected_image_h;
4893 {
4894    FILE *ppm_fp=NULL;
4895    int row=0, format=0, image_w=0, image_h=0, max_val=0;
4896    struct ObjRec *obj_ptr=NULL;
4897    struct XPmRec *xpm_ptr=NULL;
4898    Pixmap pixmap=None, bitmap=None;
4899    XImage *image=NULL, *bitmap_image=NULL;
4900    TrueColorInfo tci;
4901    double dmaxval=(double)0;
4902    int can_have_trans_pixel=FALSE, has_trans_pixel=FALSE;
4903    unsigned int trans_pixel_r=0, trans_pixel_g=0, trans_pixel_b=0;
4904 
4905    memset(&tci, 0, sizeof(TrueColorInfo));
4906    if (!SetupTrueColorInfo(&tci)) return NULL;
4907 
4908    ppm_fp = fopen(ppm_fname, "r");
4909    if (ppm_fp == NULL) {
4910       FailToOpenMessage(ppm_fname, "r", NULL);
4911       return NULL;
4912    }
4913    if (!ReadPpmHeader(ppm_fp, ppm_fname, &format, &image_w, &image_h,
4914          &max_val)) {
4915       fclose(ppm_fp);
4916       return NULL;
4917    }
4918    if (max_val != 255 && max_val != 65535) {
4919       sprintf(gszMsgBox, TgLoadString(STID_UNSUP_PPM6_MAX_VAL), max_val,
4920             ppm_fname);
4921       if (PRTGIF) {
4922          fprintf(stderr, "%s\n", gszMsgBox);
4923       } else {
4924          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4925       }
4926       fclose(ppm_fp);
4927       return NULL;
4928    }
4929    if (expected_image_w != (-1) && expected_image_h != (-1) &&
4930          (image_w != expected_image_w || image_h != expected_image_h)) {
4931       sprintf(gszMsgBox, TgLoadString(STID_PPM6_DIM_NOT_MATCH), image_w,
4932             image_h, ppm_fname, expected_image_w, expected_image_h);
4933       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4934       fclose(ppm_fp);
4935       return NULL;
4936    }
4937    dmaxval = (double)255;
4938 
4939    pixmap = XCreatePixmap(mainDisplay, mainWindow, image_w, image_h, mainDepth);
4940    bitmap = XCreatePixmap(mainDisplay, dummyBitmap, image_w, image_h, 1);
4941    if (pixmap == None || bitmap == None) {
4942       if (pixmap != None) XFreePixmap(mainDisplay, pixmap);
4943       if (bitmap != None) XFreePixmap(mainDisplay, bitmap);
4944       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
4945             image_w, image_h);
4946       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4947       fclose(ppm_fp);
4948       return NULL;
4949    }
4950    XFillRectangle(mainDisplay, pixmap, xpmGC, 0, 0, image_w, image_h);
4951 
4952    XSetForeground(mainDisplay, xbmGC, 1);
4953    XFillRectangle(mainDisplay, bitmap, xbmGC, 0, 0, image_w, image_h);
4954    XSetForeground(mainDisplay, xbmGC, 0);
4955    bitmap_image =  XGetImage(mainDisplay, bitmap, 0, 0, image_w, image_h, 1,
4956             ZPixmap);
4957    image = XGetImage(mainDisplay, pixmap, 0, 0, image_w, image_h, AllPlanes,
4958          ZPixmap);
4959    if (image == NULL || bitmap_image == NULL) {
4960       XFreePixmap(mainDisplay, pixmap);
4961       XFreePixmap(mainDisplay, bitmap);
4962       if (image != NULL) XDestroyImage(image);
4963       if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4964       MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME, INFO_MB);
4965       return NULL;
4966    }
4967    if (gPngHeaderInfo.valid && gPngHeaderInfo.trans_color_pixel_found) {
4968       can_have_trans_pixel = TRUE;
4969       trans_pixel_r = (unsigned int)gPngHeaderInfo.trans_color_pixel_red;
4970       trans_pixel_g = (unsigned int)gPngHeaderInfo.trans_color_pixel_green;
4971       trans_pixel_b = (unsigned int)gPngHeaderInfo.trans_color_pixel_blue;
4972       if (max_val == 65535) {
4973          trans_pixel_r = trans_pixel_r | ((trans_pixel_r<<8)&0x0ff00);
4974          trans_pixel_g = trans_pixel_g | ((trans_pixel_g<<8)&0x0ff00);
4975          trans_pixel_b = trans_pixel_b | ((trans_pixel_b<<8)&0x0ff00);
4976       }
4977    }
4978    for (row=0; row < image_h; row++) {
4979       int col=0;
4980 
4981       for (col=0; col < image_w; col++) {
4982          unsigned char buf[3];
4983          unsigned int r=0, g=0, b=0;
4984          double dr=(double)0, dg=(double)0, db=(double)0;
4985          int bytes_read=0;
4986          uint32_t pixel=0;
4987 
4988          if (format == TYPE_PPM6) {
4989             if (max_val == 65535) {
4990                unsigned char r_buf[2], g_buf[2], b_buf[2];
4991 
4992                if (fread(r_buf, sizeof(char), 2, ppm_fp) != 2 ||
4993                      fread(g_buf, sizeof(char), 2, ppm_fp) != 2 ||
4994                      fread(b_buf, sizeof(char), 2, ppm_fp) != 2) {
4995                   XFreePixmap(mainDisplay, pixmap);
4996                   XFreePixmap(mainDisplay, bitmap);
4997                   sprintf(gszMsgBox,
4998                         TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
4999                         image_w, image_h);
5000                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5001                   fclose(ppm_fp);
5002                   return NULL;
5003                }
5004                if (littleEndianPpm6) {
5005                   buf[0] = r_buf[1];
5006                   buf[1] = g_buf[1];
5007                   buf[2] = b_buf[1];
5008                } else {
5009                   buf[0] = r_buf[0];
5010                   buf[1] = g_buf[0];
5011                   buf[2] = b_buf[0];
5012                }
5013             } else {
5014                if ((bytes_read=fread(buf, sizeof(char), 3, ppm_fp)) != 3) {
5015                   XFreePixmap(mainDisplay, pixmap);
5016                   XFreePixmap(mainDisplay, bitmap);
5017                   sprintf(gszMsgBox,
5018                         TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
5019                         image_w, image_h);
5020                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5021                   fclose(ppm_fp);
5022                   return NULL;
5023                }
5024             }
5025          } else if (format == TYPE_PPM5) {
5026             if (max_val == 65535) {
5027                unsigned char g_buf[2];
5028 
5029                if (fread(g_buf, sizeof(char), 2, ppm_fp) != 2) {
5030                   XFreePixmap(mainDisplay, pixmap);
5031                   XFreePixmap(mainDisplay, bitmap);
5032                   sprintf(gszMsgBox,
5033                         TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
5034                         image_w, image_h);
5035                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5036                   fclose(ppm_fp);
5037                   return NULL;
5038                }
5039                if (littleEndianPpm6) {
5040                   buf[0] = buf[1] = buf[2] = g_buf[1];
5041                } else {
5042                   buf[0] = buf[1] = buf[2] = g_buf[0];
5043                }
5044             } else {
5045                if ((bytes_read=fread(buf, sizeof(char), 1, ppm_fp)) != 1) {
5046                   XFreePixmap(mainDisplay, pixmap);
5047                   XFreePixmap(mainDisplay, bitmap);
5048                   sprintf(gszMsgBox,
5049                         TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
5050                         image_w, image_h);
5051                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5052                   fclose(ppm_fp);
5053                   return NULL;
5054                }
5055                buf[1] = buf[2] = buf[0];
5056             }
5057          } else {
5058             int red=0, green=0, blue=0;
5059 
5060             if (fscanf(ppm_fp, "%d %d %d", &red, &green, &blue) != 3) {
5061                XFreePixmap(mainDisplay, pixmap);
5062                XFreePixmap(mainDisplay, bitmap);
5063                sprintf(gszMsgBox,
5064                      TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
5065                      image_w, image_h);
5066                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5067                fclose(ppm_fp);
5068                return NULL;
5069             }
5070             buf[0] = (unsigned char)(red & 0x0ff);
5071             buf[1] = (unsigned char)(green & 0x0ff);
5072             buf[2] = (unsigned char)(blue & 0x0ff);
5073          }
5074          r = (unsigned int)buf[0];
5075          g = (unsigned int)buf[1];
5076          b = (unsigned int)buf[2];
5077          dr = ((double)r) / dmaxval * tci.dr_maxval;
5078          dg = ((double)g) / dmaxval * tci.dg_maxval;
5079          db = ((double)b) / dmaxval * tci.db_maxval;
5080          r = round(dr);
5081          g = round(dg);
5082          b = round(db);
5083          pixel = ((r << tci.r_shift) & mainVisual->red_mask) |
5084                  ((g << tci.g_shift) & mainVisual->green_mask) |
5085                  ((b << tci.b_shift) & mainVisual->blue_mask) ;
5086          XPutPixel(image, col, row, pixel);
5087          if (can_have_trans_pixel && trans_pixel_r == r &&
5088                trans_pixel_g == g && trans_pixel_b == b) {
5089             XPutPixel(bitmap_image, col, row, 0);
5090             has_trans_pixel = TRUE;
5091          }
5092       }
5093    }
5094    fclose(ppm_fp);
5095 
5096    XPutImage(mainDisplay, pixmap, xpmGC, image, 0, 0, 0, 0, image_w, image_h);
5097    if (has_trans_pixel) {
5098       XPutImage(mainDisplay, bitmap, xbmGC, bitmap_image, 0, 0, 0, 0,
5099             image_w, image_h);
5100    } else {
5101       /*
5102        * It seems to be a waste not to do the following.  But it's done
5103        *       this way so that other code (such as in "dup.c") do not
5104        *       have to be changed.
5105        *
5106        * XDestroyImage(bitmap_image);
5107        * XFreePixmap(mainDisplay, bitmap);
5108        * bitmap_image = NULL;
5109        * bitmap = None;
5110        */
5111    }
5112    obj_ptr = CreateXPmObj(image_w, image_h, image_w, image_h, pixmap, image,
5113          bitmap, bitmap_image, 0, 0, FALSE, NULL, NULL, NULL, NULL);
5114    xpm_ptr = obj_ptr->detail.xpm;
5115    xpm_ptr->real_type = PPM_TRUE;
5116    if (obj_ptr == NULL) return NULL;
5117 
5118    return obj_ptr;
5119 }
5120 
5121 static
MyReadPpmTrueFile(ppm_fname,expected_image_w,expected_image_h)5122 struct ObjRec *MyReadPpmTrueFile(ppm_fname, expected_image_w, expected_image_h)
5123    char *ppm_fname;
5124    int expected_image_w, expected_image_h;
5125 {
5126    struct ObjRec *obj_ptr=NULL;
5127    struct XPmRec *xpm_ptr=NULL;
5128 
5129    if (PRTGIF && !cmdLineOpenDisplay) {
5130       obj_ptr = MyReadPpmTrueFileSkipData(ppm_fname, expected_image_w,
5131             expected_image_h);
5132    } else {
5133       if (fullTrueColorMode && HasZlibSupport()) {
5134          obj_ptr = MyReadPpmTrueFile2(ppm_fname, expected_image_w,
5135                expected_image_h);
5136          if (obj_ptr != NULL) {
5137             MoveObj(obj_ptr, -drawOrigX, -drawOrigY);
5138 
5139             return obj_ptr;
5140          } else {
5141             return NULL;
5142          }
5143       }
5144       obj_ptr = MyReadPpmFile(ppm_fname, expected_image_w, expected_image_h);
5145       if (obj_ptr == NULL) {
5146          return NULL;
5147       }
5148       xpm_ptr = obj_ptr->detail.xpm;
5149       xpm_ptr->real_type = XPM_XPM;
5150    }
5151    MoveObj(obj_ptr, -drawOrigX, -drawOrigY);
5152 
5153    return obj_ptr;
5154 }
5155 
CreatePpmTrueObjFromFile(ppm_fname)5156 struct ObjRec *CreatePpmTrueObjFromFile(ppm_fname)
5157    char *ppm_fname;
5158 {
5159    return MyReadPpmTrueFile(ppm_fname, (-1), (-1));
5160 }
5161 
ReadPpmTrueObj(FP,Inbuf,ObjPtr)5162 void ReadPpmTrueObj(FP, Inbuf, ObjPtr)
5163    FILE *FP;
5164    char *Inbuf;
5165    struct ObjRec **ObjPtr;
5166 {
5167    struct XPmRec *xpm_ptr=NULL;
5168    char *s=NULL, inbuf[MAXSTRING], *ppm_data=NULL, *ppm_mask_data=NULL;
5169    char color_s[40], trans_color_s[40], tmp_fname[MAXPATHLENGTH];
5170    int ltx=0, lty=0, rbx=0, rby=0, image_w=0, image_h=0, color_index=(-1);
5171    int rotation=0, new_alloc=FALSE, id=0, rotate=ROTATE0, flip=NO_FLIP;
5172    int locked=FALSE, has_transp_color=FALSE, real_x=0, real_y=0;
5173    int transformed=FALSE, invisible=FALSE;
5174    int ppm_data_compress=FALSE, ppm_data_size=0, ppm_mask_size=0;
5175    struct XfrmMtrxRec *ctm=NULL;
5176    struct BBRec orig_obbox;
5177    struct ObjRec *new_obj_ptr=NULL;
5178    unsigned char trans_color_pixel_r='\0', trans_color_pixel_g='\0', trans_color_pixel_b='\0';
5179 
5180    *ObjPtr = NULL;
5181 
5182    s = FindChar((int)'(', Inbuf);
5183    s = ParseStr(s, (int)',', color_s, sizeof(color_s));
5184    s = ParseStr(s, (int)',', trans_color_s, sizeof(trans_color_s));
5185    InitScan(s, "\t\n, ");
5186 
5187    rotation = 0;
5188    if (fileVersion < 37) {
5189       sprintf(gszMsgBox,
5190             TgLoadCachedString(CSTID_INVALID_FILEVER_FOR_LINK_JPEG),
5191             fileVersion);
5192       if (PRTGIF) {
5193          fprintf(stderr, "%s\n", gszMsgBox);
5194       } else {
5195          Msg(gszMsgBox);
5196       }
5197       return;
5198    } else {
5199       if (GETINT("ppm_true", has_transp_color, "has_transparent_color") == INVALID ||
5200           GETINT("ppm_true", ltx,              "ltx") == INVALID ||
5201           GETINT("ppm_true", lty,              "lty") == INVALID ||
5202           GETINT("ppm_true", rbx,              "rbx") == INVALID ||
5203           GETINT("ppm_true", rby,              "rby") == INVALID ||
5204           GETINT("ppm_true", id,               "id") == INVALID ||
5205           GETINT("ppm_true", rotation,         "rotation") == INVALID ||
5206           GETINT("ppm_true", image_w,          "image_w") == INVALID ||
5207           GETINT("ppm_true", image_h,          "image_h") == INVALID ||
5208           GETINT("ppm_true", rotate,           "rotate") == INVALID ||
5209           GETINT("ppm_true", flip,             "flip") == INVALID ||
5210           GETINT("ppm_true", locked,           "locked") == INVALID ||
5211           GETINT("ppm_true", transformed,      "transformed") == INVALID ||
5212           GETINT("ppm_true", invisible,        "invisible") == INVALID ||
5213           GETINT("ppm_true", ppm_data_compress,"ppm_data_compress") == INVALID ||
5214           GETINT("ppm_true", ppm_data_size,    "ppm_data_size") == INVALID ||
5215           GETINT("ppm_true", ppm_mask_size,    "ppm_mask_size") == INVALID) {
5216          return;
5217       }
5218       if (id >= objId) objId = id+1;
5219    }
5220    if (ppm_data_compress == PPM_JPEG_COMPRESS) {
5221       /* this is fine */
5222    } else if (ppm_data_compress == PPM_DATA_DEFLATED) {
5223       if (!HasZlibSupport()) {
5224          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_INFLATE_GIVEN_OBJ),
5225                "ppm_true", TOOL_NAME);
5226          if (PRTGIF) {
5227             fprintf(stderr, "%s\n", gszMsgBox);
5228          } else {
5229             Msg(gszMsgBox);
5230          }
5231          return;
5232       }
5233    } else {
5234       /* including PPM_DATA_RAW -- not supported, must be an error */
5235       sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_PARAM_GIVEN_OBJ),
5236             "ppm_data_compress", "ppm_true");
5237       if (PRTGIF) {
5238          fprintf(stderr, "%s\n", gszMsgBox);
5239       } else {
5240          Msg(gszMsgBox);
5241       }
5242       return;
5243    }
5244    if (transformed) {
5245       (void)fgets(inbuf, MAXSTRING, FP);
5246       scanLineNum++;
5247       InitScan(inbuf, "\t\n, ");
5248 
5249       ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
5250       if (ctm == NULL) FailAllocMessage();
5251       if (GETINT("xpixmap", real_x,           "real_x") == INVALID ||
5252           GETINT("xpixmap", real_y,           "real_y") == INVALID ||
5253           GETINT("xpixmap", orig_obbox.ltx,   "orig_obbox.ltx") == INVALID ||
5254           GETINT("xpixmap", orig_obbox.lty,   "orig_obbox.lty") == INVALID ||
5255           GETINT("xpixmap", orig_obbox.rbx,   "orig_obbox.rbx") == INVALID ||
5256           GETINT("xpixmap", orig_obbox.rby,   "orig_obbox.rby") == INVALID ||
5257           GETDBL("xpixmap", ctm->m[CTM_SX],   "CTM_SX") == INVALID ||
5258           GETDBL("xpixmap", ctm->m[CTM_SIN],  "CTM_SIN") == INVALID ||
5259           GETDBL("xpixmap", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
5260           GETDBL("xpixmap", ctm->m[CTM_SY],   "CTM_SY") == INVALID ||
5261           GETINT("xpixmap", ctm->t[CTM_TX],   "CTM_TX") == INVALID ||
5262           GETINT("xpixmap", ctm->t[CTM_TY],   "CTM_TY") == INVALID) {
5263          return;
5264       }
5265    }
5266    ppm_data = ReadPpmTrueData(FP, ppm_data_size);
5267    ppm_mask_data = ReadPpmTrueMask(FP, ppm_mask_size);
5268    if (ppm_data == NULL) return;
5269 
5270    *tmp_fname = '\0';
5271    if (IsPpmTrueObj(PPM_TRUE, ppm_data_compress, ppm_data)) {
5272       if (!ConvertPpmTrueToPpm6(ppm_data, ppm_data_size, ppm_data_compress,
5273             tmp_fname, sizeof(tmp_fname))) {
5274          UtilFree(ppm_data);
5275          return;
5276       }
5277    } else {
5278 #ifdef _TGIF_DBG /* debug, do not translate */
5279       TgAssert(FALSE, "unsupported format in ReadPpmTrueObj()", NULL);
5280 #endif /* _TGIF_DBG */
5281    }
5282    if (has_transp_color) {
5283       if (!ParseTransColor(trans_color_s, &trans_color_pixel_r,
5284             &trans_color_pixel_g, &trans_color_pixel_b)) {
5285          strcpy(gszMsgBox, TgLoadString(STID_BAD_TRANS_COLOR_NO_TRANS));
5286          if (PRTGIF && !cmdLineOpenDisplay) {
5287             fprintf(stderr, "%s\n", gszMsgBox);
5288          } else {
5289             Msg(gszMsgBox);
5290          }
5291          has_transp_color = FALSE;
5292       }
5293    }
5294    ResetPngHeaderInfo(&gPngHeaderInfo);
5295    if (has_transp_color) {
5296       SetPngHeaderInfoForTransColor(&gPngHeaderInfo, trans_color_pixel_r,
5297             trans_color_pixel_g, trans_color_pixel_b);
5298    }
5299    new_obj_ptr = MyReadPpmTrueFile(tmp_fname, image_w, image_h);
5300    ResetPngHeaderInfo(&gPngHeaderInfo);
5301    if (new_obj_ptr == NULL) {
5302       unlink(tmp_fname);
5303       UtilFree(ppm_data);
5304       return;
5305    }
5306    unlink(tmp_fname);
5307    /* must set real_type set in MyReadPpmTrueFile() */
5308 
5309    color_index = QuickFindColorIndex(new_obj_ptr, color_s, &new_alloc, TRUE);
5310    new_obj_ptr->color = color_index;
5311    UtilStrCpyN(new_obj_ptr->color_str, sizeof(new_obj_ptr->color_str), color_s);
5312    new_obj_ptr->id = id;
5313    MoveObj(new_obj_ptr, ltx, lty);
5314    if (ctm != NULL) {
5315       new_obj_ptr->obbox.ltx = new_obj_ptr->bbox.ltx = new_obj_ptr->x = ltx;
5316       new_obj_ptr->obbox.lty = new_obj_ptr->bbox.lty = new_obj_ptr->y = lty;
5317       new_obj_ptr->obbox.rbx = new_obj_ptr->bbox.rbx = rbx;
5318       new_obj_ptr->obbox.rby = new_obj_ptr->bbox.rby = rby;
5319       new_obj_ptr->ctm = ctm;
5320 
5321       memcpy(&new_obj_ptr->orig_obbox, &orig_obbox, sizeof(struct BBRec));
5322       new_obj_ptr->x = real_x;
5323       new_obj_ptr->y = real_y;
5324       GetTransformedOBBoxOffsetVs(new_obj_ptr, new_obj_ptr->rotated_obbox);
5325    }
5326    xpm_ptr = new_obj_ptr->detail.xpm;
5327 
5328    if (xpm_ptr->real_type == PPM_TRUE) {
5329       xpm_ptr->ppm_data_compress = ppm_data_compress;
5330       xpm_ptr->ppm_data = ppm_data;
5331       xpm_ptr->ppm_mask_data = NULL;
5332       xpm_ptr->ppm_mask_size = 0;
5333       xpm_ptr->ppm_data_size = ppm_data_size;
5334       xpm_ptr->has_transparent_color = has_transp_color;
5335       if (xpm_ptr->has_transparent_color) {
5336          xpm_ptr->transparent_color[0] = trans_color_pixel_r;
5337          xpm_ptr->transparent_color[1] = trans_color_pixel_g;
5338          xpm_ptr->transparent_color[2] = trans_color_pixel_b;
5339       }
5340    } else {
5341       /* something didn't work, revert back to a regular XPM object */
5342       if (!PRTGIF || cmdLineOpenDisplay) {
5343          UtilStrCpyN(gszMsgBox, sizeof(gszMsgBox),
5344                TgLoadString(STID_PPM_TRUE_LOSSY_CONV_TO_XPM));
5345          Msg(gszMsgBox);
5346          SetFileModified(TRUE);
5347       }
5348       UtilFree(ppm_data);
5349    }
5350    *ObjPtr = new_obj_ptr;
5351 }
5352 
SetXPmPropMask(ObjPtr,plMask,plSkip,pProp)5353 void SetXPmPropMask(ObjPtr, plMask, plSkip, pProp)
5354    struct ObjRec *ObjPtr;
5355    long *plMask, *plSkip;
5356    struct PropertiesRec *pProp;
5357 {
5358    SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
5359 }
5360 
FreeXPmObj(ObjPtr)5361 void FreeXPmObj(ObjPtr)
5362    struct ObjRec *ObjPtr;
5363 {
5364    register int i, ncolors;
5365    struct XPmRec *xpm_ptr=ObjPtr->detail.xpm;
5366 
5367    if (xpm_ptr->pixmap != None) {
5368       if (xpm_ptr->pixels != NULL) free(xpm_ptr->pixels);
5369       if (xpm_ptr->red != NULL) free(xpm_ptr->red);
5370       if (xpm_ptr->green != NULL) free(xpm_ptr->green);
5371       if (xpm_ptr->blue != NULL) free(xpm_ptr->blue);
5372       if (xpm_ptr->color_char != NULL) free(xpm_ptr->color_char);
5373       if (xpm_ptr->color_str != NULL) {
5374          ncolors = xpm_ptr->ncolors;
5375          for (i = 0; i < ncolors; i++) free(xpm_ptr->color_str[i]);
5376          free(xpm_ptr->color_str);
5377       }
5378       XFreePixmap(mainDisplay, xpm_ptr->pixmap);
5379    }
5380    if (xpm_ptr->bitmap != None) XFreePixmap(mainDisplay, xpm_ptr->bitmap);
5381    if (xpm_ptr->image != NULL) XDestroyImage(xpm_ptr->image);
5382    if (xpm_ptr->bitmap_image != NULL) XDestroyImage(xpm_ptr->bitmap_image);
5383    if (xpm_ptr->cached_pixmap != None) {
5384       XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
5385    }
5386    if (xpm_ptr->cached_bitmap != None) {
5387       XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
5388    }
5389    if (xpm_ptr->clip_mask != None) {
5390       XFreePixmap(mainDisplay, xpm_ptr->clip_mask);
5391    }
5392    if (xpm_ptr->data != NULL) free(xpm_ptr->data);
5393    if (xpm_ptr->filename != NULL) free(xpm_ptr->filename);
5394    if (xpm_ptr->ppm_data != NULL) free(xpm_ptr->ppm_data);
5395    if (xpm_ptr->ppm_mask_data != NULL) free(xpm_ptr->ppm_mask_data);
5396    free(xpm_ptr);
5397    free(ObjPtr);
5398 }
5399