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/xbitmap.c,v 1.43 2011/05/16 16:22:00 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_XBITMAP_C_
22 
23 #include "tgifdefs.h"
24 #include "expfdefs.h"
25 #include "cmdids.h"
26 
27 #include "attr.e"
28 #include "auxtext.e"
29 #include "choice.e"
30 #include "cmd.e"
31 #include "color.e"
32 #include "cursor.e"
33 #include "cutpaste.e"
34 #include "dialog.e"
35 #include "drawing.e"
36 #include "dup.e"
37 #include "edit.e"
38 #include "eps.e"
39 #include "file.e"
40 #include "font.e"
41 #include "grid.e"
42 #include "imgproc.e"
43 #include "mainloop.e"
44 #include "mark.e"
45 #include "menu.e"
46 #include "miniline.e"
47 #include "move.e"
48 #include "msg.e"
49 #include "names.e"
50 #include "obj.e"
51 #include "page.e"
52 #include "pattern.e"
53 #include "ps.e"
54 #include "raster.e"
55 #include "rect.e"
56 #include "remote.e"
57 #include "select.e"
58 #include "setup.e"
59 #include "stretch.e"
60 #include "strtbl.e"
61 #include "util.e"
62 #include "version.e"
63 #include "xbitmap.e"
64 #include "xpixmap.e"
65 #include "xprtfltr.e"
66 #include "z_intrf.e"
67 
68 GC xbmGC=NULL;
69 
70 int askForXBmSpec=FALSE;
71 int stripEPSComments=FALSE;
72 int saveEPSLines=FALSE;
73 
74 int leftExportPixelTrim=0;
75 int topExportPixelTrim=0;
76 int rightExportPixelTrim=0;
77 int bottomExportPixelTrim=0;
78 
79 #ifdef _XPM3TOPPM
80 int xpmOutputVersion=3;
81 #else /* ~_XPM3TOPPM */
82 int xpmOutputVersion=1;
83 #endif /* _XPM3TOPPM */
84 
85 Pixmap dummyBitmap=None;
86 
87 char gszHhtmlExportTemplate[MAXPATHLENGTH];
88 
89 /* do not translate -- program constants */
90 static char hexValue[]="0123456789abcdef";
91 
92 static int importXBmRV=FALSE;
93 static int numColorsToDump=0;
94 static int charsPerPixel=1;
95 static int *pixelValue=NULL;
96 static int *colorIndexToDumpIndex=NULL;
97 static int *dumpIndexToColorIndex=NULL;
98 static char *colorChar=NULL;
99 static char **colorStr=NULL;
100 
101 static int xpmInXGrabSCFormat=FALSE;
102 
103 static int halfToneBitmap=FALSE; /* has precedence over thresholdBitmap */
104 static int thresholdBitmap=FALSE;
105 static float bitmapThreshold=0.5;
106 static char bitmapThresholdStr[MAXSTRING+1];
107 
108 static int unsignedInXBmExport=FALSE;
109 static int commentInBitmapExport=FALSE;
110 static int useImagePixelsForTrueColorExport=FALSE;
111 
112 #define IMF_FORMAT_NCSA 0
113 #define IMF_FORMAT_CERN 1
114 #define IMF_FORMAT_SPYG 2
115 
116 static int generateImageMap=INVALID;
117 static char xpmToGifCmd[MAXSTRING+1];
118 static char xpmToPngCmd[MAXSTRING+1];
119 static char xpmToJpegCmd[MAXSTRING+1];
120 static char ppmToGifCmd[MAXSTRING+1];
121 static char ppmToPngCmd[MAXSTRING+1];
122 static char ppmToPngWithTransCmd[MAXSTRING+1];
123 static char ppmToJpegCmd[MAXSTRING+1];
124 static char ppm6ToXpm3Cmd[MAXSTRING+1];
125 static char xpmDeckToGifAnimCmd[MAXSTRING+1];
126 static char imageMapFileExtension[MAXSTRING+1];
127 static char htmlFileExtension[MAXSTRING+1];
128 static char gifFileExtension[MAXSTRING+1];
129 static char pngFileExtension[MAXSTRING+1];
130 static char jpegFileExtension[MAXSTRING+1];
131 static int imageMapFileFormat=IMF_FORMAT_NCSA;
132 
133 #ifdef _XPM3TOPPM
134 static int useXPmVersion1ForImageMap=FALSE;
135 #else /* ~_XPM3TOPPM */
136 static int useXPmVersion1ForImageMap=TRUE;
137 #endif /* _XPM3TOPPM */
138 
139 static int useXPmVersion1ForXPmDeck=TRUE;
140 static int generateHtmlHref=TRUE;
141 
142 static int epsiThresholdPreviewBitmap=FALSE;
143 static double epsiPreviewBitmapThreshold=(double)0.5;
144 
SetHtmlExportTemplate()145 void SetHtmlExportTemplate()
146 {
147    char spec[MAXSTRING<<1];
148 
149    if (*gszHhtmlExportTemplate == '\0') {
150       sprintf(gszMsgBox, TgLoadString(STID_ENTER_HTML_TEMPLATE));
151    } else {
152       sprintf(gszMsgBox, TgLoadString(STID_ENTER_HTML_TEMPLATE_CUR_IS),
153             gszHhtmlExportTemplate);
154    }
155    *spec = '\0';
156    strcpy(spec, gszHhtmlExportTemplate);
157    if (Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), spec) ==
158          INVALID) {
159       return;
160    }
161    UtilTrimBlanks(spec);
162    if (strcmp(gszHhtmlExportTemplate, spec) == 0) {
163       Msg(TgLoadString(STID_HTML_TEMPLATE_UNCHANGED));
164       return;
165    }
166    if (*spec != '\0' && !UtilPathExists(spec)) {
167       sprintf(gszMsgBox, TgLoadString(STID_Q_FILE_NOT_EXIST_USE_ANYWAY), spec);
168       if (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB) != MB_ID_YES) {
169          Msg(TgLoadString(STID_HTML_TEMPLATE_UNCHANGED));
170          return;
171       }
172    }
173    UtilStrCpyN(gszHhtmlExportTemplate, sizeof(gszHhtmlExportTemplate), spec);
174    if (*gszHhtmlExportTemplate == '\0') {
175       sprintf(gszMsgBox, TgLoadString(STID_NO_HTML_TEMPLATE_FILE));
176    } else {
177       sprintf(gszMsgBox, TgLoadString(STID_HTML_TEMPLATE_SET_TO_GIVEN),
178             gszHhtmlExportTemplate);
179    }
180    Msg(gszMsgBox);
181    SetFileModified(TRUE);
182 }
183 
ReadHtmlExportTemplate(buf)184 int ReadHtmlExportTemplate(buf)
185    char *buf;
186 {
187    if (!importingFile) {
188       char *s=FindChar((int)'(', buf), *c_ptr=NULL;
189 
190       c_ptr = FindChar((int)'"', s);
191       s = ReadString(c_ptr);
192       *(--s) = '\0';
193       *gszHhtmlExportTemplate = '\0';
194       UtilStrCpyN(gszHhtmlExportTemplate, sizeof(gszHhtmlExportTemplate),
195             c_ptr);
196    }
197    return TRUE;
198 }
199 
200 static
ExpandTmpStorage()201 void ExpandTmpStorage()
202 {
203    /* the size before are all maxColors+2 */
204    pixelValue = (int*)realloc(pixelValue, (maxColors+3)*sizeof(int));
205    colorIndexToDumpIndex = (int*)realloc(colorIndexToDumpIndex,
206          (maxColors+3)*sizeof(int));
207    dumpIndexToColorIndex = (int*)realloc(dumpIndexToColorIndex,
208          (maxColors+3)*sizeof(int));
209    if (maxColors > 20) {
210       charsPerPixel = 2;
211       colorChar = (char*)realloc(colorChar, ((maxColors<<1)+4)*sizeof(char));
212    } else {
213       charsPerPixel = 1;
214       colorChar = (char*)realloc(colorChar, (maxColors+3)*sizeof(char));
215    }
216    colorStr = (char**)realloc(colorStr, (maxColors+3)*sizeof(char*));
217    if (colorStr == NULL) FailAllocMessage();
218    colorStr[maxColors+2] = NULL;
219    colorIndexToDumpIndex[maxColors+2] = INVALID;
220    dumpIndexToColorIndex[maxColors+2] = INVALID;
221 }
222 
223 static
ParseExportPixelTrim(pszSpec,nInit)224 void ParseExportPixelTrim(pszSpec, nInit)
225    char *pszSpec;
226    int nInit;
227 {
228    char *pszLeft, *pszTop=NULL, *pszRight=NULL, *pszBottom=NULL;
229    int left, top, right, bottom;
230 
231    pszLeft = strtok(pszSpec, " ,\t");
232    if (pszLeft == NULL) return;
233 
234    pszTop = strtok(NULL, " ,\t");
235    if (pszTop != NULL) {
236       pszRight = strtok(NULL, " ,\t");
237       if (pszRight != NULL) {
238          pszBottom = strtok(NULL, " ,\t");
239       }
240    }
241    left = (pszLeft==NULL ? 0 : atoi(pszLeft));
242    top = (pszTop==NULL ? 0 : atoi(pszTop));
243    right = (pszRight==NULL ? 0 : atoi(pszRight));
244    bottom = (pszBottom==NULL ? 0 : atoi(pszBottom));
245    if (left < 0 || top < 0 || right < 0 || bottom < 0) {
246       sprintf(gszMsgBox, TgLoadString(STID_NEG_VAL_IN_EXP_PXL_TRM_ALT),
247             leftExportPixelTrim, topExportPixelTrim, rightExportPixelTrim,
248             bottomExportPixelTrim);
249       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
250    } else {
251       leftExportPixelTrim = left;
252       topExportPixelTrim = top;
253       rightExportPixelTrim = right;
254       bottomExportPixelTrim = bottom;
255       sprintf(gszMsgBox, TgLoadString(STID_EXP_PXL_TRM_VAL_SET_TO),
256             leftExportPixelTrim, topExportPixelTrim, rightExportPixelTrim,
257             bottomExportPixelTrim);
258       if (!nInit) Msg(gszMsgBox);
259    }
260 }
261 
SetExportPixelTrim(cur_val_is_too_large)262 void SetExportPixelTrim(cur_val_is_too_large)
263    int cur_val_is_too_large;
264 {
265    char szSpec[MAXSTRING+1];
266 
267    *szSpec = '\0';
268    sprintf(gszMsgBox, TgLoadString(STID_SPECIFY_TO_TRIM_EXP_PXL_TRM),
269          leftExportPixelTrim, topExportPixelTrim, rightExportPixelTrim,
270          bottomExportPixelTrim);
271    Dialog(gszMsgBox, TgLoadString(cur_val_is_too_large ?
272          STID_ENTER_4_NUM_CUR_TOO_LARGE : STID_ENTER_4_NUM_OR_CR_ESC), szSpec);
273    ParseExportPixelTrim(szSpec, FALSE);
274 }
275 
GetXpmOutputVersion()276 int GetXpmOutputVersion()
277 {
278    return xpmOutputVersion;
279 }
280 
SetXpmOutputVersion(xpm_output_version)281 void SetXpmOutputVersion(xpm_output_version)
282    int xpm_output_version;
283 {
284    xpmOutputVersion = xpm_output_version;
285 }
286 
InitXBm()287 void InitXBm()
288 {
289    XGCValues values;
290    char *c_ptr;
291 
292    dummyBitmap = XCreatePixmap(mainDisplay, mainWindow, 1, 1, 1);
293 
294    values.foreground = 0;
295    values.background = 0;
296    values.function = GXcopy;
297    values.fill_style = FillSolid;
298    xbmGC = XCreateGC(mainDisplay, dummyBitmap,
299          GCForeground | GCBackground | GCFunction | GCFillStyle, &values);
300 
301    *gszHhtmlExportTemplate = '\0';
302 
303    importXBmRV = FALSE;
304    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XBmReverseVideo")) != NULL &&
305          UtilStrICmp(c_ptr, "true") == 0) {
306       importXBmRV = TRUE;
307    }
308    askForXBmSpec = FALSE;
309    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AskForXBmSpec")) != NULL &&
310          UtilStrICmp(c_ptr, "true") == 0) {
311       askForXBmSpec = TRUE;
312    }
313    stripEPSComments = FALSE;
314    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"StripEPSComments")) != NULL &&
315          UtilStrICmp(c_ptr, "false") != 0) {
316       fprintf(stderr, TgLoadString(STID_OBSOLETE_XDEF_USE_IGNORED),
317             TOOL_NAME, "StripEPSComments");
318       fprintf(stderr, "\n");
319    }
320 #ifdef _XPM3TOPPM
321    xpmOutputVersion = 3;
322 #else /* ~_XPM3TOPPM */
323    xpmOutputVersion = 1;
324 #endif /* _XPM3TOPPM */
325    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XPmOutputVersion")) != NULL) {
326       xpmOutputVersion = atoi(c_ptr);
327       if (xpmOutputVersion != 1 && xpmOutputVersion != 3) {
328 #ifdef _XPM3TOPPM
329          int def_version=3;
330 #else /* ~_XPM3TOPPM */
331          int def_version=1;
332 #endif /* _XPM3TOPPM */
333 
334          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
335                TOOL_NAME, "XPmOutputVersion", c_ptr, def_version);
336          fprintf(stderr, "\n");
337          xpmOutputVersion = def_version;
338       }
339    }
340    xpmInXGrabSCFormat = FALSE;
341    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XPmInXGrabSCFormat"))!=NULL &&
342          UtilStrICmp(c_ptr, "true") == 0) {
343       xpmInXGrabSCFormat = TRUE;
344    }
345    halfToneBitmap = FALSE;
346    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"HalfToneBitmap"))!=NULL &&
347          UtilStrICmp(c_ptr, "true") == 0) {
348       halfToneBitmap = TRUE;
349    }
350    thresholdBitmap = FALSE;
351    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ThresholdBitmap")) != NULL &&
352          !halfToneBitmap && UtilStrICmp(c_ptr, "true") == 0) {
353       thresholdBitmap = TRUE;
354    }
355    bitmapThreshold = (halfToneBitmap) ? 0.5 : 1.0;
356    strcpy(bitmapThresholdStr, ((halfToneBitmap) ? "0.5" : "1.0"));
357    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"BitmapThreshold"))!=NULL) {
358       strcpy(bitmapThresholdStr, c_ptr);
359       bitmapThreshold = (float) atof(c_ptr);
360       if (bitmapThreshold < 0 || bitmapThreshold > 1) {
361          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
362                TOOL_NAME, "BitmapThreshold", c_ptr,
363                ((halfToneBitmap) ? "0.5" : "1.0"));
364          fprintf(stderr, "\n");
365          bitmapThreshold = (halfToneBitmap) ? 0.5 : 1.0;
366          strcpy(bitmapThresholdStr, ((halfToneBitmap) ? "0.5" : "1.0"));
367       }
368    }
369    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitExportPixelTrim")) !=
370          NULL) {
371       ParseExportPixelTrim(c_ptr, TRUE);
372    }
373    unsignedInXBmExport = FALSE;
374    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"UnsignedInXBmExport")) !=
375          NULL && UtilStrICmp(c_ptr, "true") == 0) {
376       unsignedInXBmExport = TRUE;
377    }
378    commentInBitmapExport = FALSE;
379    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"CommentInBitmapExport")) !=
380          NULL && UtilStrICmp(c_ptr, "true") == 0) {
381       commentInBitmapExport = TRUE;
382    }
383    useImagePixelsForTrueColorExport = FALSE;
384    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
385          "UseImagePixelsForTrueColorExport")) != NULL &&
386          UtilStrICmp(c_ptr, "true") == 0) {
387       useImagePixelsForTrueColorExport = TRUE;
388    }
389    epsiThresholdPreviewBitmap = FALSE;
390    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
391          "EPSIThresholdPreviewBitmap")) != NULL &&
392          UtilStrICmp(c_ptr, "true") == 0) {
393       epsiThresholdPreviewBitmap = TRUE;
394    }
395    epsiPreviewBitmapThreshold = (float)0.5;
396    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,
397          "EPSIPreviewBitmapThreshold")) != NULL) {
398       epsiPreviewBitmapThreshold = (float) atof(c_ptr);
399       if (epsiPreviewBitmapThreshold < ((float)0) ||
400             epsiPreviewBitmapThreshold > (((float)1)+INT_TOL)) {
401          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
402                TOOL_NAME, "EPSIPreviewBitmapThreshold", c_ptr, "0.5");
403          fprintf(stderr, "\n");
404          epsiPreviewBitmapThreshold = (float)0.5;
405       }
406    }
407    InitEPS();
408 }
409 
ExportHalfToneBitmap()410 void ExportHalfToneBitmap()
411 {
412    halfToneBitmap = !halfToneBitmap;
413    Msg(TgLoadString(halfToneBitmap ?
414          STID_WILL_USE_FS_HALFTONE_BMP : STID_WILL_NOT_USE_FS_HALFTONE_BMP));
415 }
416 
ExportThresholdBitmap()417 void ExportThresholdBitmap()
418 {
419    thresholdBitmap = !thresholdBitmap;
420    if (thresholdBitmap) {
421       sprintf(gszMsgBox, TgLoadString(STID_WILL_USE_GIVE_SMPLE_THRESHOLD),
422             bitmapThresholdStr);
423    } else {
424       sprintf(gszMsgBox, TgLoadString(STID_WILL_NOT_USE_SIMPLE_THRESHOLD));
425    }
426    Msg(gszMsgBox);
427 }
428 
SetExportBitmapThreshold(buf)429 void SetExportBitmapThreshold(buf)
430    char *buf;
431 {
432    float threshold=(float)0;
433    char spec[MAXSTRING<<1];
434 
435    *spec = '\0';
436    if (buf != NULL && strcmp(buf, "-1") != 0) {
437       int len=0;
438       UtilStrCpyN(spec, sizeof(spec), buf);
439       UtilTrimBlanks(spec);
440       len = strlen(spec);
441       if (len > 0 && spec[len-1] == ')') spec[len-1] = '\0';
442    } else {
443       sprintf(gszMsgBox, TgLoadString(STID_ENTER_BMP_THRESHOLD_CUR_VAL),
444             bitmapThresholdStr);
445       *spec = '\0';
446       if (Dialog(gszMsgBox, NULL, spec) == INVALID) {
447          return;
448       }
449    }
450    UtilTrimBlanks(spec);
451    if (sscanf(spec, "%f", &threshold) != 1) {
452       sprintf(gszMsgBox, TgLoadString(STID_INVALID_THRESHOLD_REMAINS),
453             spec, bitmapThresholdStr);
454       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
455    } else if (threshold < (float)0 || threshold > (float)1) {
456       sprintf(gszMsgBox, TgLoadString(STID_INVALID_THRESHOLD_REMAINS),
457             spec, bitmapThresholdStr);
458       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
459    } else {
460       strcpy(bitmapThresholdStr, spec);
461       bitmapThreshold = threshold;
462       sprintf(gszMsgBox, TgLoadString(STID_USE_GIVEN_AS_BMP_THRESHOLD),
463             bitmapThresholdStr);
464       Msg(gszMsgBox);
465    }
466 }
467 
RefreshBitPixmapMenu(menu)468 int RefreshBitPixmapMenu(menu)
469    TgMenu *menu;
470 {
471    int ok=TRUE;
472 
473    /* ExportHalfToneBitmap */
474    ok &= TgSetMenuItemCheckById(menu, CMDID_EXPORTHALFTONEBITMAP,
475          halfToneBitmap);
476    /* ExportThresholdBitmap */
477    ok &= TgSetMenuItemCheckById(menu, CMDID_EXPORTTHRESHOLDBITMAP,
478          thresholdBitmap);
479 
480    ok &= TgEnableMenuItemById(menu, CMDID_EXPORTHALFTONEBITMAP,
481          (whereToPrint == XBM_FILE && !colorDump));
482    ok &= TgEnableMenuItemById(menu, CMDID_EXPORTTHRESHOLDBITMAP,
483          (whereToPrint == XBM_FILE && !colorDump));
484    ok &= TgEnableMenuItemById(menu, CMDID_SETEXPORTBITMAPTHRESHOLD,
485          (whereToPrint == XBM_FILE && !colorDump) && thresholdBitmap);
486 
487    return ok;
488 }
489 
CreateBitPixmapMenu(parent_menu,x,y,menu_info,status_str_xlated)490 TgMenu *CreateBitPixmapMenu(parent_menu, x, y, menu_info, status_str_xlated)
491    TgMenu *parent_menu;
492    int x, y;
493    TgMenuInfo *menu_info;
494    int status_str_xlated; /* ignored, always 0 */
495 {
496    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
497 
498    if (menu != NULL) {
499       menu->track_menubar = TRUE;
500       if (!RefreshBitPixmapMenu(menu)) {
501          return TgDestroyMenu(menu, TRUE);
502       }
503    }
504    return menu;
505 }
506 
507 static int transparentIndex=INVALID;
508 
509 static
FreeCachedStrings()510 void FreeCachedStrings()
511 {
512    register int i;
513 
514    if (colorChar != NULL) {
515       for (i = 0; i < numColorsToDump+3; i++) {
516          if (colorStr[i] != NULL) {
517             free(colorStr[i]);
518          } else {
519             break;
520          }
521       }
522       free(colorStr);
523       free(colorChar);
524       free(pixelValue);
525       free(colorIndexToDumpIndex);
526       free(dumpIndexToColorIndex);
527    }
528    colorStr = NULL;
529    colorChar = NULL;
530    pixelValue = colorIndexToDumpIndex = dumpIndexToColorIndex = NULL;
531    transparentIndex = INVALID;
532 }
533 
CleanUpXBm()534 void CleanUpXBm()
535 {
536    FreeCachedStrings();
537    CleanUpEPS();
538 
539    if (xbmGC != NULL) XFreeGC(mainDisplay, xbmGC);
540    XFreePixmap(mainDisplay, dummyBitmap);
541 
542    importXBmRV = FALSE;
543    askForXBmSpec = FALSE;
544 }
545 
546 static
MultiplyTwoByTwo(m1,m2)547 void MultiplyTwoByTwo(m1, m2)
548    float m1[2][2], m2[2][2];
549 {
550    float m3[2][2];
551 
552    m3[0][0] = m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0];
553    m3[0][1] = m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1];
554    m3[1][0] = m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0];
555    m3[1][1] = m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1];
556 
557    m1[0][0]=m3[0][0]; m1[0][1]=m3[0][1]; m1[1][0]=m3[1][0]; m1[1][1]=m3[1][1];
558 }
559 
CalcTransform(mtrx)560 void CalcTransform(mtrx)
561    register struct MtrxRec *mtrx;
562 {
563    float m1[2][2], m2[2][2], tmp_val;
564 
565    switch (mtrx->rotate) {
566    case ROTATE0:
567    case ROTATE180:
568       mtrx->h_scale = mtrx->w / mtrx->image_w;
569       mtrx->v_scale = mtrx->h / mtrx->image_h;
570       break;
571    case ROTATE90:
572    case ROTATE270:
573       mtrx->h_scale = mtrx->h / mtrx->image_w;
574       mtrx->v_scale = mtrx->w / mtrx->image_h;
575       break;
576    }
577    m1[0][0]=1.0; m1[0][1]=0.0; m1[1][0]=0.0; m1[1][1]=1.0;
578    if (mtrx->flip & HORI_EVEN) {
579       m2[0][0]=(-1.0); m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=1.0;
580       MultiplyTwoByTwo(m1, m2);
581    }
582    if (mtrx->flip & VERT_EVEN) {
583       m2[0][0]=1.0; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=(-1.0);
584       MultiplyTwoByTwo(m1, m2);
585    }
586    switch (mtrx->rotate) {
587    case ROTATE0:
588       if (mtrx->flip & (HORI_ODD | VERT_ODD)) {
589          m2[0][0]=rotatedCosine[ROTATE90]; m2[0][1]=rotatedSine[ROTATE90];
590          m2[1][0]=(-rotatedSine[ROTATE90]); m2[1][1]=rotatedCosine[ROTATE90];
591          MultiplyTwoByTwo(m1, m2);
592          if (mtrx->flip & HORI_ODD) {
593             m2[0][0]=(-1.0); m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=1.0;
594             MultiplyTwoByTwo(m1, m2);
595          }
596          if (mtrx->flip & VERT_ODD) {
597             m2[0][0]=1.0; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=(-1.0);
598             MultiplyTwoByTwo(m1, m2);
599          }
600          m2[0][0]=rotatedCosine[ROTATE270];
601          m2[0][1]=rotatedSine[ROTATE270];
602          m2[1][0]=(-rotatedSine[ROTATE270]);
603          m2[1][1]=rotatedCosine[ROTATE270];
604          MultiplyTwoByTwo(m1, m2);
605       }
606       break;
607    case ROTATE90:
608       m2[0][0]=rotatedCosine[ROTATE90]; m2[0][1]=rotatedSine[ROTATE90];
609       m2[1][0]=(-rotatedSine[ROTATE90]); m2[1][1]=rotatedCosine[ROTATE90];
610       MultiplyTwoByTwo(m1, m2);
611       if (mtrx->flip & HORI_ODD) {
612          m2[0][0]=(-1.0); m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=1.0;
613          MultiplyTwoByTwo(m1, m2);
614       }
615       if (mtrx->flip & VERT_ODD) {
616          m2[0][0]=1.0; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=(-1.0);
617          MultiplyTwoByTwo(m1, m2);
618       }
619       break;
620    case ROTATE180:
621       m2[0][0]=rotatedCosine[ROTATE90]; m2[0][1]=rotatedSine[ROTATE90];
622       m2[1][0]=(-rotatedSine[ROTATE90]); m2[1][1]=rotatedCosine[ROTATE90];
623       MultiplyTwoByTwo(m1, m2);
624       if (mtrx->flip & HORI_ODD) {
625          m2[0][0]=(-1.0); m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=1.0;
626          MultiplyTwoByTwo(m1, m2);
627       }
628       if (mtrx->flip & VERT_ODD) {
629          m2[0][0]=1.0; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=(-1.0);
630          MultiplyTwoByTwo(m1, m2);
631       }
632       m2[0][0]=rotatedCosine[ROTATE90]; m2[0][1]=rotatedSine[ROTATE90];
633       m2[1][0]=(-rotatedSine[ROTATE90]); m2[1][1]=rotatedCosine[ROTATE90];
634       MultiplyTwoByTwo(m1, m2);
635       break;
636    case ROTATE270:
637       m2[0][0]=rotatedCosine[ROTATE270]; m2[0][1]=rotatedSine[ROTATE270];
638       m2[1][0]=(-rotatedSine[ROTATE270]); m2[1][1]=rotatedCosine[ROTATE270];
639       MultiplyTwoByTwo(m1, m2);
640       if (mtrx->flip & HORI_ODD) {
641          m2[0][0]=(-1.0); m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=1.0;
642          MultiplyTwoByTwo(m1, m2);
643       }
644       if (mtrx->flip & VERT_ODD) {
645          m2[0][0]=1.0; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=(-1.0);
646          MultiplyTwoByTwo(m1, m2);
647       }
648       break;
649    }
650    m2[0][0]=mtrx->h_scale; m2[0][1]=0.0; m2[1][0]=0.0; m2[1][1]=mtrx->v_scale;
651    MultiplyTwoByTwo(m2, m1);
652 
653    mtrx->m[0][0]=m2[0][0]; mtrx->m[0][1]=m2[0][1];
654    mtrx->m[1][0]=m2[1][0]; mtrx->m[1][1]=m2[1][1];
655    tmp_val = m2[0][0]*m2[1][1] - m2[0][1]*m2[1][0];
656    if (fabs((double) tmp_val) < 1.0e-6) {
657       tmp_val = ((float)1000000);
658    } else {
659       tmp_val = ((float)1.0)/tmp_val;
660    }
661    mtrx->rev_m[0][0] = tmp_val*m2[1][1];
662    mtrx->rev_m[0][1] = (-tmp_val)*m2[0][1];
663    mtrx->rev_m[1][0] = (-tmp_val)*m2[1][0];
664    mtrx->rev_m[1][1] = tmp_val*m2[0][0];
665 
666    mtrx->transformed_w = mtrx->image_w*m2[0][0] + mtrx->image_h*m2[1][0];
667    mtrx->transformed_h = mtrx->image_w*m2[0][1] + mtrx->image_h*m2[1][1];
668 
669    switch (mtrx->rotate) {
670    case ROTATE0:
671       mtrx->dump_h_scale=mtrx->m[0][0]; mtrx->dump_v_scale=mtrx->m[1][1];
672       mtrx->degree=0;
673       break;
674    case ROTATE90:
675       mtrx->dump_h_scale=mtrx->m[1][0]; mtrx->dump_v_scale=(-mtrx->m[0][1]);
676       mtrx->degree=(-90);
677       break;
678    case ROTATE180:
679       mtrx->dump_h_scale=(-mtrx->m[0][0]);
680       mtrx->dump_v_scale=(-mtrx->m[1][1]);
681       mtrx->degree=(-180);
682       break;
683    case ROTATE270:
684       mtrx->dump_h_scale=(-mtrx->m[1][0]); mtrx->dump_v_scale=mtrx->m[0][1];
685       mtrx->degree=(-270);
686       break;
687    }
688 }
689 
MakeCachedBitmap(ObjPtr)690 void MakeCachedBitmap(ObjPtr)
691    struct ObjRec *ObjPtr;
692 {
693    register int r, c;
694    int w, h, flip, target_percent;
695    int num_cols, num_rows, image_w, image_h, watch_cursor;
696    int start_col, start_row, do_msg;
697    struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
698    struct MtrxRec mtrx;
699    Pixmap dest_bitmap;
700    XImage *src_image, *dest_image;
701 
702    if (xbm_ptr->real_type==XBM_EPS && xbm_ptr->bitmap==None) return;
703 
704    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
705    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
706    num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
707    num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
708 
709    if (ObjPtr->ctm==NULL && xbm_ptr->cached_bitmap!=None &&
710          xbm_ptr->cached_zoomed==zoomedIn && xbm_ptr->cached_zoom==zoomScale &&
711          xbm_ptr->cached_w==num_cols && xbm_ptr->cached_h==num_rows &&
712          xbm_ptr->cached_flip==xbm_ptr->flip) {
713       return;
714    }
715    if ((w>>zoomScale)==0 || (h>>zoomScale)==0) {
716       if (xbm_ptr->cached_bitmap != None) {
717          XFreePixmap(mainDisplay, xbm_ptr->cached_bitmap);
718       }
719       xbm_ptr->cached_bitmap = None;
720       return;
721    }
722    watch_cursor = watchCursorOnMainWindow;
723    if (!watch_cursor && !RedrawDuringScrolling()) {
724       SetWatchCursor(drawWindow);
725       SetWatchCursor(mainWindow);
726    } else {
727       CheckInterrupt(TRUE);
728    }
729    src_image = xbm_ptr->image;
730    flip = xbm_ptr->flip;
731    image_w = xbm_ptr->image_w;
732    image_h = xbm_ptr->image_h;
733    if (xbm_ptr->cached_bitmap != None) {
734       XFreePixmap(mainDisplay, xbm_ptr->cached_bitmap);
735    }
736    xbm_ptr->cached_bitmap = None;
737 
738    if (src_image == NULL) {
739       src_image = xbm_ptr->image = XGetImage(mainDisplay, xbm_ptr->bitmap,
740             0, 0, image_w, image_h, 1, ZPixmap);
741    }
742    do_msg = (((num_rows*num_cols)>=0x4000) && !RedrawDuringScrolling());
743    if (do_msg) {
744       SaveStatusStrings();
745       SetStringStatus(TgLoadCachedString(CSTID_CACHING_BITMAP));
746       XSync(mainDisplay, False);
747    }
748    dest_bitmap = XCreatePixmap(mainDisplay,dummyBitmap,num_cols,num_rows,1);
749    XFillRectangle(mainDisplay,dest_bitmap,xbmGC,0,0,num_cols,num_rows);
750    dest_image = XGetImage(mainDisplay, dest_bitmap, 0, 0, num_cols,
751          num_rows, 1, ZPixmap);
752 
753    if (ObjPtr->ctm == NULL) {
754       mtrx.image_w = (float)image_w; mtrx.image_h = (float)image_h;
755       mtrx.w = (float)num_cols; mtrx.h = (float)num_rows;
756       mtrx.rotate = ROTATE0; mtrx.flip = flip;
757 
758       CalcTransform(&mtrx);
759 
760       start_col = (mtrx.transformed_w >= 0.0) ? 0 : (-num_cols)+1;
761       start_row = (mtrx.transformed_h >= 0.0) ? 0 : (-num_rows)+1;
762 
763       target_percent = 5;
764       for (r = 0; r < num_rows; r++) {
765          double part_x, part_y;
766 
767          if (do_msg && ((r & 0xf) == 0)) {
768             int percent=(r*10000/num_rows)/100;
769 
770             if (percent >= target_percent) {
771                sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
772                      percent);
773                SetStringStatus(gszMsgBox);
774                XSync(mainDisplay, False);
775                while (target_percent <= percent) target_percent += 5;
776             }
777          }
778          part_x = ((double)(r+start_row)+0.5)*(mtrx.rev_m[1][0]);
779          part_y = ((double)(r+start_row)+0.5)*(mtrx.rev_m[1][1]);
780          for (c = 0; c < num_cols; c++) {
781             double x, y;
782 
783             x = part_x+((double)(c+start_col)+0.5)*(mtrx.rev_m[0][0]);
784             y = part_y+((double)(c+start_col)+0.5)*(mtrx.rev_m[0][1]);
785             if (x >= ((double)0) && x < ((double)image_w) &&
786                   y >= ((double)0) && y < ((double)image_h)) {
787                if (XGetPixel(src_image, (int)x, (int)y) == 1) {
788                   XPutPixel(dest_image, c, r, 1);
789                }
790             }
791          }
792       }
793    } else {
794       int abs_offset_x=ObjPtr->obbox.ltx-ObjPtr->x;
795       int abs_offset_y=ObjPtr->obbox.lty-ObjPtr->y;
796       double sx=(double)0.0, sy=(double)0.0;
797 
798       if (xbm_ptr->real_type != XBM_XBM) {
799          sx = (((double)xbm_ptr->eps_w)/((double)image_w));
800          sy = (((double)xbm_ptr->eps_h)/((double)image_h));
801       }
802       target_percent = 5;
803       for (r=0; r < num_rows; r++) {
804          int y=abs_offset_y+ABS_SIZE(r);
805          double dy=((double)y)+0.5;
806 
807          if (do_msg && ((r & 0xf) == 0)) {
808             int percent=(r*10000/num_rows)/100;
809 
810             if (percent >= target_percent) {
811                sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
812                      percent);
813                SetStringStatus(gszMsgBox);
814                XSync(mainDisplay, False);
815                while (target_percent <= percent) target_percent += 5;
816             }
817          }
818          for (c=0; c < num_cols; c++) {
819             int x=abs_offset_x+ABS_SIZE(c);
820             double dx=((double)x)+0.5;
821             double new_dx=(double)0, new_dy=(double)0;
822 
823             ReverseTransformDoublePointThroughCTM(dx, dy, ObjPtr->ctm,
824                   &new_dx, &new_dy);
825             if (xbm_ptr->real_type != XBM_XBM) {
826                double tmp_dx=((double)new_dx)/sx;
827                double tmp_dy=((double)new_dy)/sy;
828 
829                new_dx = tmp_dx + ((double)(ObjPtr->x - ObjPtr->orig_obbox.ltx));
830                new_dy = tmp_dy + ((double)(ObjPtr->y - ObjPtr->orig_obbox.lty));
831             } else {
832                new_dx += (double)(ObjPtr->x-ObjPtr->orig_obbox.ltx);
833                new_dy += (double)(ObjPtr->y-ObjPtr->orig_obbox.lty);
834             }
835             if (new_dx >= ((double)0) && new_dx < ((double)image_w) &&
836                   new_dy >= ((double)0) && new_dy < ((double)image_h)) {
837                int new_x=(int)new_dx, new_y=(int)new_dy;
838 
839                if (new_x < 0) new_x = 0;
840                if (new_x >= image_w) new_x = image_w-1;
841                if (new_y < 0) new_y = 0;
842                if (new_y >= image_h) new_y = image_h-1;
843                if (XGetPixel(src_image, new_x, new_y) == 1) {
844                   XPutPixel(dest_image, c, r, 1);
845                }
846             }
847          }
848       }
849       memcpy(&xbm_ptr->cached_ctm, ObjPtr->ctm, sizeof(struct XfrmMtrxRec));
850    }
851    if (do_msg) {
852       SetStringStatus(TgLoadCachedString(CSTID_FINISHED_CACHEING_BITMAP));
853       XSync(mainDisplay, False);
854    }
855    XPutImage(mainDisplay, dest_bitmap, xbmGC, dest_image, 0, 0, 0, 0,
856          num_cols, num_rows);
857    if (do_msg) RestoreStatusStrings();
858 
859    xbm_ptr->cached_bitmap = dest_bitmap;
860    xbm_ptr->cached_zoomed = zoomedIn;
861    xbm_ptr->cached_zoom = zoomScale;
862    xbm_ptr->cached_flip = xbm_ptr->flip;
863    xbm_ptr->cached_w = num_cols;
864    xbm_ptr->cached_h = num_rows;
865 
866    XDestroyImage(dest_image);
867 
868    if (!watch_cursor && !RedrawDuringScrolling()) {
869       SetDefaultCursor(mainWindow);
870       ShowCursor();
871    } else {
872       CheckInterrupt(TRUE);
873    }
874 }
875 
ExtractBitmap(OrigBitmap,OrigImage,X,Y,W,H,Bitmap,Image)876 int ExtractBitmap(OrigBitmap, OrigImage, X, Y, W, H, Bitmap, Image)
877    Pixmap OrigBitmap, *Bitmap;
878    XImage *OrigImage, **Image;
879    int X, Y, W, H;
880 {
881    register int j, i;
882    XImage *src_image;
883 
884    SetWatchCursor(drawWindow);
885    SetWatchCursor(mainWindow);
886 
887    if ((*Bitmap=XCreatePixmap(mainDisplay,mainWindow,W,H,1)) == None) {
888       FailAllocBitmapMessage(W, H);
889       SetDefaultCursor(mainWindow);
890       SetDefaultCursor(drawWindow);
891       return FALSE;
892    }
893 
894    if ((*Image=XGetImage(mainDisplay, *Bitmap, 0, 0, W, H, 1,
895          ZPixmap)) == NULL) {
896       MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
897             INFO_MB);
898       XFreePixmap(mainDisplay, *Bitmap); *Bitmap = None;
899       SetDefaultCursor(mainWindow);
900       SetDefaultCursor(drawWindow);
901       return FALSE;
902    }
903    if (OrigImage != NULL && X == 0 && Y == 0) {
904       src_image = OrigImage;
905    } else {
906       if ((src_image=XGetImage(mainDisplay, OrigBitmap, X, Y, W, H, 1,
907             ZPixmap)) == NULL) {
908          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
909                INFO_MB);
910          XFreePixmap(mainDisplay, *Bitmap);
911          *Bitmap = None;
912          XDestroyImage(*Image); *Image = NULL;
913          SetDefaultCursor(mainWindow);
914          SetDefaultCursor(drawWindow);
915          return FALSE;
916       }
917    }
918    for (i=0; i < H; i++) {
919       for (j=0; j < W; j++) {
920          XPutPixel(*Image, j, i, XGetPixel(src_image, j, i));
921       }
922    }
923    XPutImage(mainDisplay, *Bitmap, xbmGC, *Image, 0, 0, 0, 0, W, H);
924    SetDefaultCursor(mainWindow);
925    SetDefaultCursor(drawWindow);
926 
927    if (!(OrigImage != NULL && X == 0 && Y == 0)) XDestroyImage(src_image);
928    return TRUE;
929 }
930 
AutoTrimBitmap(OrigBitmap,pnImageW,pnImageH,pBitmap,pImage,pnEmptyImage,pnDontFreeOrigBitmap)931 int AutoTrimBitmap(OrigBitmap, pnImageW, pnImageH, pBitmap, pImage,
932       pnEmptyImage, pnDontFreeOrigBitmap)
933    Pixmap OrigBitmap, *pBitmap;
934    int *pnImageW, *pnImageH, *pnEmptyImage, *pnDontFreeOrigBitmap;
935    XImage **pImage;
936 {
937    int i=0, orig_w=(*pnImageW), orig_h=(*pnImageH);
938    int top=orig_h, left=orig_w, bottom=(-1), right=(-1);
939    XImage *image=NULL;
940 
941    *pnEmptyImage = *pnDontFreeOrigBitmap = FALSE;
942 
943    SetWatchCursor(drawWindow);
944    SetWatchCursor(mainWindow);
945    image = XGetImage(mainDisplay, OrigBitmap, 0, 0, orig_w, orig_h, 1, ZPixmap);
946 
947    if (image == NULL) {
948       MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
949             INFO_MB);
950       SetDefaultCursor(mainWindow);
951       SetDefaultCursor(drawWindow);
952       return FALSE;
953    }
954    for (i=0; i < orig_h; i++) {
955       int j=0;
956 
957       for (j=0; j < orig_w; j++) {
958          if (XGetPixel(image, j, i) != 0) {
959             if (i < top) top = i;
960             if (i > bottom) bottom = i;
961             if (j < left) left = j;
962             if (j > right) right = j;
963          }
964       }
965    }
966    SetDefaultCursor(mainWindow);
967    SetDefaultCursor(drawWindow);
968 
969    if (top == orig_h && left == orig_w && bottom == (-1) && right == (-1)) {
970       /* no image */
971       *pnEmptyImage = TRUE;
972       XDestroyImage(image);
973       return FALSE;
974    } else if (top == 0 && left == 0 && bottom == orig_w-1 &&
975          right == orig_h-1) {
976       *pnImageW = orig_w;
977       *pnImageH = orig_h;
978       *pBitmap = OrigBitmap;
979       *pImage = image;
980       *pnDontFreeOrigBitmap = TRUE;
981    } else {
982       /* trim */
983       int rc=0;
984 
985       *pnImageW = right-left+1;
986       *pnImageH = bottom-top+1;
987       rc = ExtractBitmap(OrigBitmap, image, left, top, *pnImageW, *pnImageH,
988             pBitmap, pImage);
989       XDestroyImage(image);
990 
991       return rc;
992    }
993    return TRUE;
994 }
995 
996 static
InvertXBmObject(ObjPtr)997 void InvertXBmObject(ObjPtr)
998    struct ObjRec *ObjPtr;
999 {
1000    int i, j, image_w, image_h, pixel, watch_cursor=watchCursorOnMainWindow;
1001    Pixmap bitmap=None;
1002    XImage *image=NULL;
1003 
1004    if (!watch_cursor) {
1005       SetWatchCursor(drawWindow);
1006       SetWatchCursor(mainWindow);
1007    }
1008    bitmap = ObjPtr->detail.xbm->bitmap;
1009 
1010    image_w = ObjPtr->detail.xbm->image_w;
1011    image_h = ObjPtr->detail.xbm->image_h;
1012    if (ObjPtr->detail.xbm->image == NULL) {
1013       if ((image=ObjPtr->detail.xbm->image = XGetImage(mainDisplay, bitmap,
1014             0, 0, image_w, image_h, 1, ZPixmap)) == NULL) {
1015          fprintf(stderr, "%s\n",
1016                TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM));
1017          fflush(stderr);
1018          SetDefaultCursor(mainWindow);
1019          SetDefaultCursor(drawWindow);
1020          if (!watch_cursor) {
1021             SetDefaultCursor(mainWindow);
1022             ShowCursor();
1023          }
1024          return;
1025       }
1026    } else {
1027       image = ObjPtr->detail.xbm->image;
1028    }
1029    for (i=0; i < image_h; i++) {
1030       for (j=0; j < image_w; j++) {
1031          pixel = XGetPixel(image, j, i);
1032          XPutPixel(image, j, i, ((pixel==1) ? 0 : 1));
1033       }
1034    }
1035    XPutImage(mainDisplay, bitmap, xbmGC, image, 0, 0, 0, 0, image_w, image_h);
1036 
1037    if (ObjPtr->detail.xbm->cached_bitmap != None) {
1038       XFreePixmap(mainDisplay, ObjPtr->detail.xbm->cached_bitmap);
1039    }
1040    ObjPtr->detail.xbm->cached_bitmap = None;
1041    if (zoomScale != 0) {
1042       ObjPtr->detail.xbm->cached_zoom = 0;
1043    }
1044    if (!watch_cursor) {
1045       SetDefaultCursor(mainWindow);
1046       ShowCursor();
1047    }
1048 }
1049 
1050 static
ObjListInvertable(LastObjPtr)1051 int ObjListInvertable(LastObjPtr)
1052    struct ObjRec *LastObjPtr;
1053 {
1054    struct ObjRec *obj_ptr;
1055 
1056    for (obj_ptr=LastObjPtr; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1057       switch (obj_ptr->type) {
1058       case OBJ_XBM: return TRUE;
1059 
1060       case OBJ_GROUP:
1061       case OBJ_ICON:
1062       case OBJ_SYM:
1063          if (ObjListInvertable(obj_ptr->detail.r->last)) return TRUE;
1064          break;
1065       case OBJ_PIN:
1066          if (ObjListInvertable(GetPinObj(obj_ptr)->detail.r->last)) return TRUE;
1067          break;
1068       }
1069    }
1070    return FALSE;
1071 }
1072 
1073 static
InvertObjListXBitmap(LastObjPtr)1074 void InvertObjListXBitmap(LastObjPtr)
1075    struct ObjRec *LastObjPtr;
1076 {
1077    struct ObjRec *obj_ptr;
1078 
1079    for (obj_ptr=LastObjPtr; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1080       switch (obj_ptr->type) {
1081       case OBJ_XBM: InvertXBmObject(obj_ptr); break;
1082 
1083       case OBJ_GROUP:
1084       case OBJ_ICON:
1085       case OBJ_SYM:
1086          InvertObjListXBitmap(obj_ptr->detail.r->last);
1087          break;
1088       case OBJ_PIN:
1089          InvertObjListXBitmap(GetPinObj(obj_ptr)->detail.r->last);
1090          break;
1091       }
1092    }
1093 }
1094 
InvertXBitmaps()1095 void InvertXBitmaps()
1096 {
1097    struct SelRec *sel_ptr;
1098    int changed=FALSE;
1099 
1100    if (topSel == NULL) {
1101       MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
1102       return;
1103    }
1104    StartCompositeCmd();
1105    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1106       switch (sel_ptr->obj->type) {
1107       case OBJ_XBM:
1108          changed = TRUE;
1109          PrepareToReplaceAnObj(sel_ptr->obj);
1110          InvertXBmObject(sel_ptr->obj);
1111          RecordReplaceAnObj(sel_ptr->obj);
1112          break;
1113 
1114       case OBJ_GROUP:
1115       case OBJ_ICON:
1116       case OBJ_SYM:
1117       case OBJ_PIN:
1118          if (ObjListInvertable(sel_ptr->obj->detail.r->last)) {
1119             changed = TRUE;
1120             PrepareToReplaceAnObj(sel_ptr->obj);
1121             InvertObjListXBitmap(sel_ptr->obj->detail.r->last);
1122             RecordReplaceAnObj(sel_ptr->obj);
1123          }
1124          break;
1125       }
1126    }
1127    EndCompositeCmd();
1128 
1129    if (changed) {
1130       SetFileModified(TRUE);
1131       HighLightReverse();
1132       RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1133             selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1134       HighLightForward();
1135    } else {
1136       MsgBox(TgLoadString(STID_NO_X11_BITMAP_OBJ_SELECTED), TOOL_NAME, INFO_MB);
1137    }
1138 }
1139 
1140 static
ParseGeomSpec(geom_spec,image_w,image_h,src_x,src_y,src_w,src_h)1141 void ParseGeomSpec(geom_spec, image_w, image_h, src_x, src_y, src_w, src_h)
1142    char *geom_spec;
1143    int image_w, image_h, *src_x, *src_y, *src_w, *src_h;
1144 {
1145    int bitmask;
1146    XSizeHints sizehints;
1147 
1148    *src_x = *src_y = 0;
1149    *src_w = image_w;
1150    *src_h = image_h;
1151 
1152    bitmask = XParseGeometry(geom_spec, &(sizehints.x), &(sizehints.y),
1153          (unsigned int *)&(sizehints.width),
1154          (unsigned int *)&(sizehints.height));
1155    if (bitmask & WidthValue) *src_w = sizehints.width;
1156    if (bitmask & HeightValue) *src_h = sizehints.height;
1157    if (bitmask & XValue) {
1158       *src_x = (bitmask & XNegative) ? image_w+sizehints.x : sizehints.x;
1159       if (bitmask & XNegative) {
1160          if (*src_w > image_w) *src_w = image_w;
1161          if (*src_x >= image_w || *src_x < 0) *src_x = image_w;
1162          if (*src_x-*src_w < 0) {
1163             *src_w = *src_x;
1164             *src_x = 0;
1165          } else {
1166             *src_x -= *src_w;
1167          }
1168       } else {
1169          if (*src_w > image_w) *src_w = image_w;
1170          if (*src_x >= image_w || *src_x < 0) *src_x = 0;
1171          if (*src_x+*src_w > image_w) *src_w = image_w-*src_x;
1172       }
1173    }
1174    if (bitmask & YValue) {
1175       *src_y = (bitmask & YNegative) ? image_h+sizehints.y : sizehints.y;
1176       if (bitmask & YNegative) {
1177          if (*src_h > image_h) *src_h = image_h;
1178          if (*src_y >= image_h || *src_y < 0) *src_y = image_h;
1179          if (*src_y-*src_h < 0) {
1180             *src_h = *src_y;
1181             *src_y = 0;
1182          } else {
1183             *src_y -= *src_h;
1184          }
1185       } else {
1186          if (*src_h > image_h) *src_h = image_h;
1187          if (*src_y >= image_h || *src_y < 0) *src_y = 0;
1188          if (*src_y+*src_h > image_h) *src_h = image_h-*src_y;
1189       }
1190    }
1191    if ((bitmask&WidthValue) && *src_x+*src_w>image_w) *src_w = image_w-*src_x;
1192    if ((bitmask&HeightValue) && *src_y+*src_h>image_h) *src_h = image_h-*src_y;
1193 }
1194 
1195 static
FindEqual(s)1196 char *FindEqual(s)
1197    register char *s;
1198 {
1199    while (*s != '=' && *s != '\0') s++;
1200    return ((*s == '=') ? (s) : (char*)NULL);
1201 }
1202 
ParseCutSpec(spec,image_w,image_h,mag,src_x,src_y,src_w,src_h)1203 void ParseCutSpec(spec, image_w, image_h, mag, src_x, src_y, src_w, src_h)
1204    char *spec;
1205    int image_w, image_h, * src_x, * src_y, * src_w, * src_h;
1206    float *mag;
1207 {
1208    char *geom_spec;
1209 
1210    *mag = 1.0;
1211 
1212    if ((geom_spec=FindEqual(spec)) == NULL) {
1213       ParseGeomSpec(spec,image_w,image_h,src_x,src_y,src_w,src_h);
1214    } else {
1215       *geom_spec = '\0';
1216       geom_spec++;
1217       ParseGeomSpec(geom_spec,image_w,image_h,src_x,src_y,src_w,src_h);
1218 
1219       sscanf(spec, "%f", mag);
1220       if (*mag <= 0.0) *mag = 1.0;
1221    }
1222 }
1223 
CutXBitmap()1224 void CutXBitmap()
1225 {
1226    int w, h, ltx, lty, rbx, rby, new_w, new_h;
1227    int src_x, src_y, src_w, src_h, image_w, image_h;
1228    char mag_spec[MAXSTRING];
1229    float h_scale=1.0, v_scale=1.0, mag;
1230    Pixmap dest_bitmap=None;
1231    XImage *dest_image=NULL;
1232    struct ObjRec *obj_ptr=topSel->obj, *new_obj_ptr;
1233    struct XBmRec *new_xbm_ptr;
1234 
1235    if (obj_ptr->detail.xbm->real_type==XBM_EPS) {
1236       MsgBox(TgLoadString(STID_CANT_CUT_AN_EPS_OBJECT), TOOL_NAME, INFO_MB);
1237       return;
1238    }
1239 
1240    src_x = 0;
1241    src_y = 0;
1242    src_w = image_w = obj_ptr->detail.xbm->image_w;
1243    src_h = image_h = obj_ptr->detail.xbm->image_h;
1244    mag = 1.0;
1245 
1246    h_scale = ((float)((float)(obj_ptr->obbox.rbx-obj_ptr->obbox.ltx)) /
1247          ((float)image_w));
1248    v_scale = ((float)((float)(obj_ptr->obbox.rby-obj_ptr->obbox.lty)) /
1249          ((float)image_h));
1250 
1251    *mag_spec = '\0';
1252    sprintf(gszMsgBox, TgLoadString(STID_ENTER_GEOM_SPEC_ORIG_SIZE),
1253          image_w, image_h);
1254    Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), mag_spec);
1255    UtilTrimBlanks(mag_spec);
1256    if (*mag_spec == '\0') return;
1257 
1258    ParseCutSpec(mag_spec,image_w,image_h,&mag,&src_x,&src_y,&src_w,&src_h);
1259    if (src_x==0 && src_y==0 && src_w==image_w && src_h==image_h && mag==1.0) {
1260       return;
1261    }
1262    if (src_w==0 || src_h==0) {
1263       MsgBox(TgLoadString(STID_XBM_CANT_HAVE_0_W_OR_H), TOOL_NAME, INFO_MB);
1264       return;
1265    }
1266 
1267    PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
1268    if (!ExtractBitmap(obj_ptr->detail.xbm->bitmap,
1269          obj_ptr->detail.xbm->image, src_x, src_y, src_w, src_h,
1270          &dest_bitmap, &dest_image)) {
1271       AbortPrepareCmd(CMD_REPLACE);
1272       return;
1273    }
1274 
1275    sprintf(gszMsgBox, TgLoadCachedString(CSTID_NEW_BMP_SIZE_IS_W_X_H),
1276          src_w, src_h);
1277    Msg(gszMsgBox);
1278 
1279    UnlinkObj(obj_ptr);
1280 
1281    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1282    HighLightReverse();
1283 
1284    w = new_w = (int)(((float)src_w) * mag);
1285    h = new_h = (int)(((float)src_h) * mag);
1286 
1287    new_obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
1288    if (new_obj_ptr == NULL) FailAllocMessage();
1289    memset(new_obj_ptr, 0, sizeof(struct ObjRec));
1290    DupObjBasics(obj_ptr, new_obj_ptr);
1291 
1292    new_xbm_ptr = (struct XBmRec *)malloc(sizeof(struct XBmRec));
1293    if (new_xbm_ptr == NULL) FailAllocMessage();
1294    memset(new_xbm_ptr, 0, sizeof(struct XBmRec));
1295    new_obj_ptr->detail.xbm = new_xbm_ptr;
1296 
1297    new_xbm_ptr->image = dest_image;
1298    new_xbm_ptr->image_w = src_w;
1299    new_xbm_ptr->image_h = src_h;
1300    new_xbm_ptr->bitmap = dest_bitmap;
1301    new_xbm_ptr->data = NULL;
1302    new_xbm_ptr->fill = obj_ptr->detail.xbm->fill;
1303    new_xbm_ptr->flip = obj_ptr->detail.xbm->flip;
1304    new_xbm_ptr->cached_zoom = 0;
1305    new_xbm_ptr->cached_bitmap = None;
1306    new_xbm_ptr->cached_flip = 0;
1307    new_xbm_ptr->cached_w = 0;
1308    new_xbm_ptr->cached_h = 0;
1309 
1310    new_w = round(h_scale * ((float)w));
1311    new_h = round(v_scale * ((float)h));
1312 
1313    new_obj_ptr->obbox.ltx = obj_ptr->obbox.ltx;
1314    new_obj_ptr->obbox.lty = obj_ptr->obbox.lty;
1315    new_obj_ptr->obbox.rbx = new_obj_ptr->bbox.rbx = obj_ptr->obbox.ltx+new_w;
1316    new_obj_ptr->obbox.rby = new_obj_ptr->bbox.rby = obj_ptr->obbox.lty+new_h;
1317 
1318    AdjObjBBox(new_obj_ptr);
1319 
1320    topSel->obj = botSel->obj = new_obj_ptr;
1321    AddObj(NULL, topObj, new_obj_ptr);
1322    RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
1323    FreeObj(obj_ptr);
1324 
1325    UpdSelBBox();
1326    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1327          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1328          selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1329          selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1330    HighLightForward();
1331    SetFileModified(TRUE);
1332    justDupped = FALSE;
1333 }
1334 
1335 static
UpdateColorsLookupTable(color_index)1336 void UpdateColorsLookupTable(color_index)
1337    int color_index;
1338 {
1339    if (colorIndexToDumpIndex[color_index] == INVALID) {
1340       if (colorStr[numColorsToDump] != NULL) {
1341          free(colorStr[numColorsToDump]);
1342       }
1343       pixelValue[numColorsToDump] = colorPixels[color_index];
1344       colorIndexToDumpIndex[color_index] = numColorsToDump;
1345       dumpIndexToColorIndex[numColorsToDump] = color_index;
1346       colorStr[numColorsToDump] = (char *) malloc(
1347             (strlen(colorMenuItems[color_index])+1)*sizeof(char));
1348       if (colorStr[numColorsToDump] == NULL) FailAllocMessage();
1349       strcpy(colorStr[numColorsToDump], colorMenuItems[color_index]);
1350       numColorsToDump++;
1351    }
1352 }
1353 
1354 static
BuildStrSegColors(pStrSeg,pUserData)1355 void BuildStrSegColors(pStrSeg, pUserData)
1356    StrSegInfo *pStrSeg;
1357    void *pUserData;
1358 {
1359    UpdateColorsLookupTable(pStrSeg->color);
1360 }
1361 
1362 static
BuildObjXPmColors(ObjPtr)1363 void BuildObjXPmColors(ObjPtr)
1364    struct ObjRec *ObjPtr;
1365 {
1366    register int i, color_index;
1367    register struct ObjRec *obj_ptr;
1368    register struct AttrRec *attr_ptr;
1369    struct XPmRec *xpm_ptr;
1370    int start_index, new_alloc;
1371 
1372    switch (ObjPtr->type) {
1373    case OBJ_POLY:
1374    case OBJ_BOX:
1375    case OBJ_OVAL:
1376    case OBJ_POLYGON:
1377    case OBJ_ARC:
1378    case OBJ_RCBOX:
1379    case OBJ_XBM:
1380       UpdateColorsLookupTable(ObjPtr->color);
1381       if (ObjPtr->type == OBJ_XBM) {
1382          if (ObjPtr->detail.xbm->real_type==XBM_EPS &&
1383                ObjPtr->detail.xbm->bitmap==None) {
1384             char color_str[COLORSTRLEN];
1385 
1386             new_alloc = FALSE;
1387             GetDrawingFgColorStr(INVALID, INVALID, color_str,
1388                   sizeof(color_str));
1389             color_index = QuickFindColorIndex(NULL, color_str, &new_alloc,
1390                   FALSE);
1391             if (color_index != INVALID) {
1392                if (new_alloc) ExpandTmpStorage();
1393                UpdateColorsLookupTable(color_index);
1394             }
1395          }
1396       }
1397       break;
1398 
1399    case OBJ_TEXT:
1400       UpdateColorsLookupTable(ObjPtr->color);
1401       DoFuncOnStrSegForMiniLines(&ObjPtr->detail.t->minilines,
1402             BuildStrSegColors, NULL);
1403       break;
1404 
1405    case OBJ_XPM:
1406       xpm_ptr = ObjPtr->detail.xpm;
1407       start_index = (xpm_ptr->first_pixel_is_bg) ? 1 : 0;
1408       for (i=start_index; i < xpm_ptr->ncolors; i++) {
1409          /* do not translate -- program constants */
1410          if (UtilStrICmp(xpm_ptr->color_str[i], "None") == 0) {
1411             if (whereToPrint == XBM_FILE && colorDump &&
1412                   transparentIndex == (-1)) {
1413                /*
1414                 * Transparent stuff pretty much only works for straight
1415                 *         XPM output and nothing else.  None of the
1416                 *         convertors (e.g., xpmtoppm) can handle the
1417                 *         None color in an XPM file.
1418                 */
1419                if (colorStr[numColorsToDump] != NULL) {
1420                   free(colorStr[numColorsToDump]);
1421                }
1422                pixelValue[numColorsToDump] = (-1);
1423                colorStr[numColorsToDump] = UtilStrDup("None");
1424                transparentIndex = numColorsToDump++;
1425             }
1426          } else if ((color_index=QuickFindColorIndex(NULL,
1427                xpm_ptr->color_str[i], &new_alloc, TRUE)) != INVALID) {
1428             if (new_alloc) ExpandTmpStorage();
1429             UpdateColorsLookupTable(color_index);
1430          }
1431       }
1432       if (!PRTGIF && colorLayers && needToRedrawColorWindow) {
1433          RedrawColorWindow();
1434       }
1435       break;
1436 
1437    case OBJ_GROUP:
1438    case OBJ_ICON:
1439    case OBJ_SYM:
1440       for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
1441             obj_ptr=obj_ptr->next) {
1442          BuildObjXPmColors(obj_ptr);
1443       }
1444       break;
1445    case OBJ_PIN:
1446       obj_ptr = GetPinObj(ObjPtr);
1447       BuildObjXPmColors(obj_ptr);
1448       break;
1449    }
1450    for (attr_ptr=ObjPtr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
1451       BuildObjXPmColors(attr_ptr->obj);
1452    }
1453 }
1454 
1455 typedef struct tagTmpBucketInfo {
1456    int pixel;
1457    struct tagTmpBucketInfo *next;
1458 } TmpBucketInfo;
1459 
1460 static int numTmpBuckets=0;
1461 static TmpBucketInfo **ppTmpBuckets=NULL;
1462 static int tmpRedShift=0, tmpGreenShift=0, tmpBlueShift=0;
1463 
1464 static
CleanUpTmpBuckets()1465 void CleanUpTmpBuckets()
1466 {
1467    int i=0;
1468 
1469    if (ppTmpBuckets != NULL) {
1470       for (i=0; i < numTmpBuckets; i++) {
1471          TmpBucketInfo *ptbi=NULL, *ptbi_next=NULL;
1472 
1473          for (ptbi=ppTmpBuckets[i]; ptbi != NULL; ptbi=ptbi_next) {
1474             ptbi_next = ptbi->next;
1475             free(ptbi);
1476          }
1477       }
1478       free(ppTmpBuckets);
1479    }
1480    tmpRedShift = tmpGreenShift = tmpBlueShift = 0;
1481    numTmpBuckets = 0;
1482    ppTmpBuckets = NULL;
1483 }
1484 
1485 static
SetTmpShift(mask,pn_shifts)1486 int SetTmpShift(mask, pn_shifts)
1487    unsigned long mask;
1488    int *pn_shifts;
1489 {
1490    int i=0;
1491 
1492    if (mask == 0L) return FALSE;
1493 
1494    while ((mask & 0x1) == 0) {
1495       i++;
1496       mask >>= 1;
1497    }
1498    *pn_shifts = i;
1499 
1500    return TRUE;
1501 }
1502 
1503 static
BadMask(cWhich,mask)1504 int BadMask(cWhich, mask)
1505    char cWhich;
1506    unsigned long mask;
1507 {
1508    switch (cWhich) {
1509    case 'r':
1510       sprintf(gszMsgBox, TgLoadString(STID_BAD_RED_MASK_TRUE_COLOR_DPY),
1511             (long)mask, TOOL_NAME, "UseImagePixelsForTrueColorExport");
1512       break;
1513    case 'g':
1514       sprintf(gszMsgBox, TgLoadString(STID_BAD_GREEN_MASK_TRUE_COLOR_DPY),
1515             (long)mask, TOOL_NAME, "UseImagePixelsForTrueColorExport");
1516       break;
1517    case 'b':
1518       sprintf(gszMsgBox, TgLoadString(STID_BAD_BLUE_MASK_TRUE_COLOR_DPY),
1519             (long)mask, TOOL_NAME, "UseImagePixelsForTrueColorExport");
1520       break;
1521    }
1522    if (PRTGIF) {
1523       fprintf(stderr, "%s\n", gszMsgBox);
1524    } else {
1525       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1526    }
1527    CleanUpTmpBuckets();
1528 
1529    return FALSE;
1530 }
1531 
1532 static
InitTmpBuckets()1533 int InitTmpBuckets()
1534 {
1535    numTmpBuckets = 257;
1536    ppTmpBuckets = (TmpBucketInfo**)malloc(numTmpBuckets*sizeof(TmpBucketInfo*));
1537    if (ppTmpBuckets == NULL) FailAllocMessage();
1538    memset(ppTmpBuckets, 0, numTmpBuckets*sizeof(TmpBucketInfo*));
1539 
1540    if (mainVisual->class != TrueColor) {
1541       return TRUE;
1542    }
1543    if (!SetTmpShift(mainVisual->red_mask, &tmpRedShift)) {
1544       return BadMask('r', mainVisual->red_mask);
1545    }
1546    if (!SetTmpShift(mainVisual->green_mask, &tmpGreenShift)) {
1547       return BadMask('g', mainVisual->green_mask);
1548    }
1549    if (!SetTmpShift(mainVisual->blue_mask, &tmpBlueShift)) {
1550       return BadMask('b', mainVisual->blue_mask);
1551    }
1552    return TRUE;
1553 }
1554 
1555 static
TmpPixelHash(pixel)1556 int TmpPixelHash(pixel)
1557    int pixel;
1558 {
1559    return (((pixel)==(-1)) ? (numTmpBuckets-1) : (pixel % numTmpBuckets));
1560 }
1561 
1562 static
GetTmpValue(pixel,mask,shift,pn_value)1563 void GetTmpValue(pixel, mask, shift, pn_value)
1564    int pixel, shift, *pn_value;
1565    unsigned long mask;
1566 {
1567    double d_val=(double)0;
1568    int value=0;
1569 
1570    pixel = (int)(pixel & mask);
1571    pixel >>= shift;
1572    mask >>= shift;
1573    d_val = ((double)pixel) / ((double)mask) * ((double)0x0ff);
1574    value = round(d_val);
1575    if (value > 0x0ff) value = 0x0ff;
1576    if (value < 0) value = 0;
1577    *pn_value = value;
1578 }
1579 
1580 static
GetTmpColorStr(pixel,color_str)1581 void GetTmpColorStr(pixel, color_str)
1582    int pixel;
1583    char *color_str;
1584 {
1585    int red_value=0, green_value=0, blue_value=0;
1586 
1587    if (mainVisual->class == TrueColor) {
1588       GetTmpValue(pixel, mainVisual->red_mask, tmpRedShift, &red_value);
1589       GetTmpValue(pixel, mainVisual->green_mask, tmpGreenShift, &green_value);
1590       GetTmpValue(pixel, mainVisual->blue_mask, tmpBlueShift, &blue_value);
1591       sprintf(color_str, "#%c%c%c%c%c%c",
1592             hexValue[(red_value>>4)&0x0f], hexValue[red_value&0x0f],
1593             hexValue[(green_value>>4)&0x0f], hexValue[green_value&0x0f],
1594             hexValue[(blue_value>>4)&0x0f], hexValue[blue_value&0x0f]);
1595    } else {
1596       XColor xcolor;
1597 
1598       memset(&xcolor, 0, sizeof(XColor));
1599       xcolor.pixel = pixel;
1600       XQueryColor(mainDisplay, mainColormap, &xcolor);
1601       red_value = xcolor.red;
1602       green_value = xcolor.green;
1603       blue_value = xcolor.blue;
1604       sprintf(color_str, "#%c%c%c%c%c%c",
1605             hexValue[(red_value>>12)&0x0f], hexValue[(red_value>>8)&0x0f],
1606             hexValue[(green_value>>12)&0x0f], hexValue[(green_value>>8)&0x0f],
1607             hexValue[(blue_value>>12)&0x0f], hexValue[(blue_value>>8)&0x0f]);
1608    }
1609 }
1610 
1611 static
UpdateColorsLookupTableForPixel(pixel,can_alloc)1612 void UpdateColorsLookupTableForPixel(pixel, can_alloc)
1613    int pixel, can_alloc;
1614 {
1615    char color_str[COLORSTRLEN];
1616    int bucket=TmpPixelHash(pixel);
1617    TmpBucketInfo *ptbi=NULL;
1618 
1619    for (ptbi=ppTmpBuckets[bucket]; ptbi != NULL; ptbi=ptbi->next) {
1620       if (ptbi->pixel == pixel) {
1621          return;
1622       }
1623    }
1624    ptbi = (TmpBucketInfo*)malloc(sizeof(TmpBucketInfo));
1625    if (ptbi == NULL) FailAllocMessage();
1626    memset(ptbi, 0, sizeof(TmpBucketInfo));
1627    ptbi->next = ppTmpBuckets[bucket];
1628    ppTmpBuckets[bucket] = ptbi;
1629    ptbi->pixel = pixel;
1630 
1631    if (can_alloc && numColorsToDump >= maxColors) {
1632       maxColors++;
1633       ExpandTmpStorage();
1634    }
1635    UtilFree(colorStr[numColorsToDump]);
1636    pixelValue[numColorsToDump] = pixel;
1637    *color_str = '\0';
1638    GetTmpColorStr(pixel, color_str);
1639    colorStr[numColorsToDump] = UtilStrDup(color_str);
1640    numColorsToDump++;
1641 }
1642 
1643 static
BuildXPmColors(image,w,h,left,top,right,bottom,use_pixels)1644 void BuildXPmColors(image, w, h, left, top, right, bottom, use_pixels)
1645    XImage *image;
1646    int w, h, left, top, right, bottom, use_pixels;
1647 {
1648    int i;
1649 
1650    FreeCachedStrings();
1651    if (colorChar == NULL) {
1652       pixelValue = (int*)malloc((maxColors+3)*sizeof(int));
1653       if (pixelValue == NULL) FailAllocMessage();
1654       colorIndexToDumpIndex = (int*)malloc((maxColors+3)*sizeof(int));
1655       dumpIndexToColorIndex = (int*)malloc((maxColors+3)*sizeof(int));
1656       if (colorIndexToDumpIndex == NULL || dumpIndexToColorIndex == NULL) {
1657          FailAllocMessage();
1658       }
1659       if (maxColors > 20) {
1660          charsPerPixel = 2;
1661          colorChar = (char*)malloc(((maxColors<<1)+6)*sizeof(char));
1662       } else {
1663          charsPerPixel = 1;
1664          colorChar = (char*)malloc((maxColors+3)*sizeof(char));
1665       }
1666       if (colorChar == NULL) FailAllocMessage();
1667       colorStr = (char**)malloc((maxColors+3)*sizeof(char*));
1668       if (colorStr == NULL) FailAllocMessage();
1669       memset(colorStr, 0, (maxColors+3)*sizeof(char*));
1670    }
1671    for (i = 0; i < maxColors+3; i++) {
1672       colorIndexToDumpIndex[i] = dumpIndexToColorIndex[i] = INVALID;
1673    }
1674    pixelValue[0] = GetDrawingBgPixel(INVALID, INVALID);
1675    if (myFileBgColorStr == NULL) {
1676       colorStr[0] = (char*)malloc((strlen(myBgColorStr)+1)*sizeof(char));
1677       if (colorStr[0] == NULL) FailAllocMessage();
1678       strcpy(colorStr[0], myBgColorStr);
1679    } else {
1680       colorStr[0] = (char*)malloc((strlen(myFileBgColorStr)+1)*sizeof(char));
1681       if (colorStr[0] == NULL) FailAllocMessage();
1682       strcpy(colorStr[0], myFileBgColorStr);
1683    }
1684    numColorsToDump = 1;
1685 
1686    if ((use_pixels || (mainVisual->class == TrueColor &&
1687          useImagePixelsForTrueColorExport)) && !InitTmpBuckets()) {
1688       if (!use_pixels) {
1689          useImagePixelsForTrueColorExport = FALSE;
1690       } else {
1691          use_pixels = FALSE;
1692       }
1693    }
1694    if ((use_pixels || (mainVisual->class == TrueColor &&
1695          useImagePixelsForTrueColorExport))) {
1696       SetStringStatus(TgLoadCachedString(CSTID_BLD_COLOR_TBL_FROM_PIXEL_DOTS));
1697       for (i=top; i < h-bottom; i++) {
1698          int j=0;
1699 
1700          for (j=left; j < w-right; j++) {
1701             int pixel=XGetPixel(image,j-left,i-top);
1702 
1703             UpdateColorsLookupTableForPixel(pixel, FALSE);
1704          }
1705       }
1706       CleanUpTmpBuckets();
1707    } else {
1708       struct ObjRec *obj_ptr=NULL;
1709 
1710       for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1711          BuildObjXPmColors(obj_ptr);
1712       }
1713    }
1714    colorChar[0] = '`';
1715    if (charsPerPixel > 1) colorChar[1] = '`';
1716    if (numColorsToDump >= 256) {
1717       for (i=1; i < numColorsToDump; i++) {
1718          if (charsPerPixel == 1) {
1719             colorChar[i] = (char)(((int)('a'))+i-1);
1720          } else {
1721             int left=(int)(i/80), right=(i%80);
1722 
1723             if (left >= 31) {
1724                colorChar[i*2] = (char)(((int)('/'))+left-31);
1725             } else {
1726                colorChar[i*2] = (char)(((int)('`'))+left);
1727             }
1728             if (right >= 31) {
1729                colorChar[i*2+1] = (char)(((int)('/'))+right-31);
1730             } else {
1731                colorChar[i*2+1] = (char)(((int)('`'))+right);
1732             }
1733          }
1734       }
1735    } else {
1736       for (i=1; i < numColorsToDump; i++) {
1737          if (charsPerPixel == 1) {
1738             colorChar[i] = (char)(((int)('a'))+i-1);
1739          } else {
1740             colorChar[i*2] = (char)(((int)('a'))+(int)(i/10));
1741             colorChar[i*2+1] = (char)(((int)('0'))+(i%10));
1742          }
1743       }
1744    }
1745 }
1746 
1747 static
ColorStrToXPmStr(index,color_str)1748 void ColorStrToXPmStr(index, color_str)
1749    int index;
1750    char *color_str;
1751 {
1752    char s[3];
1753    int i, value;
1754 
1755    if (*(colorStr[index]) == '#') {
1756       strcpy(color_str, colorStr[index]);
1757    } else {
1758       for (i = 0; i < maxColors; i++) {
1759          if (colorPixels[i] ==  pixelValue[index]) {
1760             break;
1761          }
1762       }
1763       if (i == maxColors) {
1764          strcpy(color_str, colorStr[index]);
1765       } else {
1766          strcpy(color_str, "#");
1767          value = (int)(((float)tgifColors[i].red/maxRGB) * 0x100);
1768          if (value > 255) {
1769             value = 255;
1770          } else if (value < 255) {
1771             value = 0;
1772          }
1773          sprintf(s, "%c%c", hexValue[(value>>4)&0x0f], hexValue[value&0x0f]);
1774          strcat(color_str, s);
1775          strcat(color_str, s);
1776 
1777          value = (int)(((float)tgifColors[i].green/maxRGB) * 0x100);
1778          if (value > 255) {
1779             value = 255;
1780          } else if (value < 255) {
1781             value = 0;
1782          }
1783          sprintf(s, "%c%c", hexValue[(value>>4)&0x0f], hexValue[value&0x0f]);
1784          strcat(color_str, s);
1785          strcat(color_str, s);
1786 
1787          value = (int)(((float)tgifColors[i].blue/maxRGB) * 0x100);
1788          if (value > 255) {
1789             value = 255;
1790          } else if (value < 255) {
1791             value = 0;
1792          }
1793          sprintf(s, "%c%c", hexValue[(value>>4)&0x0f], hexValue[value&0x0f]);
1794          strcat(color_str, s);
1795          strcat(color_str, s);
1796       }
1797    }
1798 }
1799 
1800 static
DumpXPmColors(FP)1801 void DumpXPmColors(FP)
1802    FILE *FP;
1803 {
1804    int i, j;
1805    char s[MAXSTRING];
1806 
1807    if (xpmOutputVersion == 1) {
1808       if (xpmInXGrabSCFormat) {
1809          for (i=0; i < numColorsToDump-1; i++) {
1810             if (fprintf(FP, "\"") == EOF) writeFileFailed = TRUE;
1811             for (j = 0; j < charsPerPixel; j++) {
1812                if (fprintf(FP, "%c", colorChar[i*charsPerPixel+j]) == EOF) {
1813                   writeFileFailed = TRUE;
1814                }
1815             }
1816             ColorStrToXPmStr(i, s);
1817             if (fprintf(FP, "\", \"%s\"\n", s) == EOF) writeFileFailed = TRUE;
1818          }
1819          if (fprintf(FP, "\"") == EOF) writeFileFailed = TRUE;
1820          for (j = 0; j < charsPerPixel; j++) {
1821             if (fprintf(FP, "%c", colorChar[i*charsPerPixel+j]) == EOF) {
1822                writeFileFailed = TRUE;
1823             }
1824          }
1825          ColorStrToXPmStr(i, s);
1826          if (fprintf(FP, "\", \"%s\"\n} ;\n", s) == EOF) {
1827             writeFileFailed = TRUE;
1828          }
1829       } else {
1830          for (i=0; i < numColorsToDump-1; i++) {
1831             if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
1832             for (j = 0; j < charsPerPixel; j++) {
1833                if (fprintf(FP, "%c", colorChar[i*charsPerPixel+j]) == EOF) {
1834                   writeFileFailed = TRUE;
1835                }
1836             }
1837             if (fprintf(FP, "\", \"%s\",\n", colorStr[i]) == EOF) {
1838                writeFileFailed = TRUE;
1839             }
1840          }
1841          if (fprintf(FP, "   \"") == EOF) writeFileFailed = TRUE;
1842          for (j = 0; j < charsPerPixel; j++) {
1843             if (fprintf(FP, "%c", colorChar[i*charsPerPixel+j]) == EOF) {
1844                writeFileFailed = TRUE;
1845             }
1846          }
1847          if (fprintf(FP, "\", \"%s\"\n};\n", colorStr[i]) == EOF) {
1848             writeFileFailed = TRUE;
1849          }
1850       }
1851    } else {
1852       /* xpmOutputVersion is 3 */
1853       for (i=0; i < numColorsToDump; i++) {
1854          if (fprintf(FP, "\"") == EOF) writeFileFailed = TRUE;
1855          for (j = 0; j < charsPerPixel; j++) {
1856             if (fprintf(FP, "%c", colorChar[i*charsPerPixel+j]) == EOF) {
1857                writeFileFailed = TRUE;
1858             }
1859          }
1860          if (fprintf(FP, " c %s\",\n", colorStr[i]) == EOF) {
1861             writeFileFailed = TRUE;
1862          }
1863       }
1864    }
1865 }
1866 
1867 static
SetupTrueColorInfoFromImage(image,ptci)1868 int SetupTrueColorInfoFromImage(image, ptci)
1869    XImage *image;
1870    TrueColorInfo *ptci;
1871 {
1872    unsigned int r_mask=0, g_mask=0, b_mask=0;
1873    unsigned int r_maxval=0, g_maxval=0, b_maxval=0;
1874    unsigned int r_bits=0, g_bits=0, b_bits=0;
1875    int r_shift=(-1), g_shift=(-1), b_shift=(-1);
1876    unsigned int shifts=0;
1877 
1878    ptci->r_mask = r_mask = image->red_mask;
1879    ptci->g_mask = g_mask = image->green_mask;
1880    ptci->b_mask = b_mask = image->blue_mask;
1881    if (r_mask == 0 && g_mask == 0 && b_mask == 0) {
1882       if (PRTGIF && !cmdLineOpenDisplay) {
1883          FatalUnexpectedError(
1884                /* debug, do not translate */
1885                "Unimplemented in SetupTrueColorInfoFromImage().", NULL);
1886          return FALSE;
1887       }
1888       return SetupTrueColorInfo(ptci);
1889    }
1890    for (shifts=0; r_mask|g_mask|b_mask; shifts++) {
1891       if (r_mask & 0x1) {
1892          if (r_shift == (-1)) {
1893             r_shift = shifts;
1894             r_maxval = r_mask;
1895          }
1896          r_bits++;
1897       }
1898       if (g_mask & 0x1) {
1899          if (g_shift == (-1)) {
1900             g_shift = shifts;
1901             g_maxval = g_mask;
1902          }
1903          g_bits++;
1904       }
1905       if (b_mask & 0x1) {
1906          if (b_shift == (-1)) {
1907             b_shift = shifts;
1908             b_maxval = b_mask;
1909          }
1910          b_bits++;
1911       }
1912       r_mask >>= 1;
1913       g_mask >>= 1;
1914       b_mask >>= 1;
1915    }
1916    ptci->r_shift = (unsigned int)r_shift;
1917    ptci->g_shift = (unsigned int)g_shift;
1918    ptci->b_shift = (unsigned int)b_shift;
1919    ptci->dr_maxval = (double)r_maxval;
1920    ptci->dg_maxval = (double)g_maxval;
1921    ptci->db_maxval = (double)b_maxval;
1922    ptci->dr_maxval_div255 = ptci->dr_maxval / ((double)255);
1923    ptci->dg_maxval_div255 = ptci->dg_maxval / ((double)255);
1924    ptci->db_maxval_div255 = ptci->db_maxval / ((double)255);
1925    ptci->num_r_bits = r_bits;
1926    ptci->num_g_bits = g_bits;
1927    ptci->num_b_bits = b_bits;
1928 
1929    if (r_shift==(-1) || g_shift==(-1) || b_shift==(-1)) {
1930       return FALSE;
1931    }
1932    return TRUE;
1933 }
1934 
InitTrueColorInfo(image,ptci,image_w)1935 int InitTrueColorInfo(image, ptci, image_w)
1936    XImage *image;
1937    TrueColorInfo *ptci;
1938    int image_w;
1939 {
1940    unsigned int bytes_per_pixel=image->bits_per_pixel/8;
1941 
1942    memset(ptci, 0, sizeof(TrueColorInfo));
1943    if (bytes_per_pixel > 4) {
1944 #ifdef _TGIF_DBG /* debug, do not translate */
1945       fprintf(stderr, "bytes_per_pixel (%1d) > 4 in InitTrueColorInfo().\n",
1946             bytes_per_pixel);
1947 #endif /* _TGIF_DBG */
1948       return FALSE;
1949    }
1950    if ((unsigned int)(image->bytes_per_line/image_w) != bytes_per_pixel) {
1951 #ifdef _TGIF_DBG /* debug, do not translate */
1952       fprintf(stderr, "bytes_per_pixel (%1d) != %1d %s.\n",
1953             bytes_per_pixel, (unsigned int)(image->bytes_per_line/image_w),
1954             "in InitTrueColorInfo()");
1955 #endif /* _TGIF_DBG */
1956       return FALSE;
1957    }
1958    return SetupTrueColorInfoFromImage(image, ptci);
1959 }
1960 
1961 /*
1962  * static
1963  * void MapPixToEPSI(SrcX, SrcY, SrcW, SrcH, DestW, DestH, DestX, DestY)
1964  *    int SrcX, SrcY, SrcW, SrcH, DestW, DestH, * DestX, * DestY;
1965  * {
1966  *    if (pageStyle == LANDSCAPE)
1967  *    {
1968  *       *DestY = (int)round(((float)DestH) -
1969  *             ((((float)DestH)*((float)SrcX))/((float)SrcW)));
1970  *       *DestX = (int)round((((float)DestW)*((float)SrcY))/((float)SrcH));
1971  *    }
1972  *    else
1973  *    {
1974  *       *DestX = (int)round((((float)DestW)*((float)SrcX))/((float)SrcW));
1975  *       *DestY = (int)round((((float)DestH)*((float)SrcY))/((float)SrcH));
1976  *    }
1977  *    if (*DestX >= DestW) *DestX = DestW-1; if (*DestX < 0) *DestX = 0;
1978  *    if (*DestY >= DestH) *DestY = DestH-1; if (*DestY < 0) *DestY = 0;
1979  * }
1980  */
1981 
1982 static
MapEPSIToPix(DestX,DestY,DestW,DestH,SrcW,SrcH,SrcX,SrcY)1983 void MapEPSIToPix(DestX, DestY, DestW, DestH, SrcW, SrcH, SrcX, SrcY)
1984    int DestX, DestY, DestW, DestH, SrcW, SrcH, * SrcX, * SrcY;
1985 {
1986    if (pageStyle == LANDSCAPE) {
1987       *SrcX = (int)round(((float)(DestH-DestY))*((float)SrcW)/((float)DestH));
1988       *SrcY = (int)round((((float)SrcH)*((float)DestX))/((float)DestW));
1989    } else {
1990       *SrcX = (int)round((((float)SrcW)*((float)DestX))/((float)DestW));
1991       *SrcY = (int)round((((float)SrcH)*((float)DestY))/((float)DestH));
1992    }
1993    if (*SrcX >= SrcW) *SrcX = SrcW-1; if (*SrcX < 0) *SrcX = 0;
1994    if (*SrcY >= SrcH) *SrcY = SrcH-1; if (*SrcY < 0) *SrcY = 0;
1995 }
1996 
GenPreviewBitmap(FP,llxPage,llyPage,urxPage,uryPage)1997 void GenPreviewBitmap(FP, llxPage, llyPage, urxPage, uryPage)
1998    FILE *FP;
1999    int llxPage, llyPage, urxPage, uryPage;
2000 {
2001    int col=0, row=0, ltx=0, lty=0, w=0, h=0, x=0, y=0;
2002    int **data=NULL, num_image_bytes_per_row=0;
2003    int image_w=urxPage-llxPage, image_h=uryPage-llyPage, num_lines=0;
2004    Pixmap pixmap=None;
2005    XImage *image=NULL;
2006    TrueColorInfo tci;
2007 
2008    if (image_w == 0 || image_h == 0) return;
2009    if ((pixmap=DrawAllOnPixmap(&ltx, &lty, &w, &h, TRUE)) == None) return;
2010 
2011    image = XGetImage(mainDisplay, pixmap, 0, 0, w, h, AllPlanes, ZPixmap);
2012    if (image == NULL) {
2013       MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME, INFO_MB);
2014       XFreePixmap(mainDisplay, pixmap);
2015       return;
2016    }
2017    if (fullTrueColorMode) {
2018       if (!InitTrueColorInfo(image, &tci, w)) {
2019          XDestroyImage(image);
2020          XFreePixmap(mainDisplay, pixmap);
2021          return;
2022       }
2023    }
2024    if (image_w < 0) image_w = (-image_w);
2025    if (image_h < 0) image_h = (-image_h);
2026    num_image_bytes_per_row = ((image_w & 0x7) ? (image_w>>3)+1 : (image_w>>3));
2027    num_lines = ((image_w & 0x7) ? (((image_w>>3)+1)<<1) : ((image_w>>3)<<1));
2028    num_lines = ((num_lines & 0x3f) ? (num_lines>>6)+1 : (num_lines>>6));
2029 
2030    if ((data=(int**)malloc(image_h*sizeof(int*))) == NULL) {
2031       FailAllocMessage();
2032       return;
2033    }
2034    for (row=0; row < image_h; row++) {
2035       if ((data[row]=(int*)malloc(num_image_bytes_per_row*sizeof(int))) ==
2036             NULL) {
2037          FailAllocMessage();
2038          return;
2039       } else {
2040          for (col=0; col<num_image_bytes_per_row; col++) data[row][col] = 0;
2041       }
2042    }
2043    fprintf(FP, "%%%%BeginPreview: %1d %1d 1 %1d\n", image_w, image_h,
2044          num_lines*image_h);
2045    for (row=0; row < image_h; row++) {
2046       int bg_pixel=GetDrawingBgPixel(INVALID, INVALID);
2047 
2048       for (col=0; col < image_w; col++) {
2049          int pixel=XGetPixel(image, x, y);
2050 
2051          MapEPSIToPix(col, row, image_w, image_h, w, h, &x, &y);
2052          if (epsiThresholdPreviewBitmap) {
2053             double gray=(double)0;
2054 
2055             if (fullTrueColorMode) {
2056                uint32_t pix=(uint32_t)(unsigned int)pixel;
2057                unsigned int r=0, g=0, b=0;
2058                double dr=(double)0, dg=(double)0, db=(double)0;
2059 
2060                r = (pix & tci.r_mask) >> tci.r_shift;
2061                g = (pix & tci.g_mask) >> tci.g_shift;
2062                b = (pix & tci.b_mask) >> tci.b_shift;
2063                dr = ((double)r) / tci.dr_maxval;
2064                dg = ((double)g) / tci.dg_maxval;
2065                db = ((double)b) / tci.db_maxval;
2066                gray = (double)(0.299*dr + 0.587*dg + 0.114*db);
2067             } else {
2068                int k=0, found_index=INVALID;
2069 
2070                for (k=0; k < maxColors; k++) {
2071                   if (colorPixels[k] == pixel) {
2072                      found_index = k;
2073                      break;
2074                   }
2075                }
2076                if (found_index == INVALID) {
2077                   if (pixel == bg_pixel) {
2078                      gray = (double)1.0;
2079                   } else {
2080                      sprintf(gszMsgBox,
2081                            TgLoadString(STID_UNRECOG_GIVEN_PIXEL_VAL_1_USE),
2082                            pixel, (long)pixel);
2083                      Msg(gszMsgBox);
2084                      gray = (double)0.0;
2085                   }
2086                } else {
2087                   gray = 0.299*((double)tgifColors[found_index].red/maxRGB) +
2088                         0.587*((double)tgifColors[found_index].green/maxRGB) +
2089                         0.114*((double)tgifColors[found_index].blue/maxRGB);
2090                }
2091             }
2092             if (gray < epsiPreviewBitmapThreshold) {
2093                data[row][col>>3] |= (1<<(7 - (col & 0x7)));
2094             }
2095          } else {
2096             if (pixel != bg_pixel) {
2097                data[row][col>>3] |= (1<<(7 - (col & 0x7)));
2098             }
2099          }
2100       }
2101    }
2102    for (row=0; row < image_h; row++) {
2103       int byte_count=0;
2104 
2105       fprintf(FP, "%% ");
2106       for (col=0; col < num_image_bytes_per_row; col++) {
2107          if (byte_count++ == 32) {
2108             byte_count = 1;
2109             fprintf(FP, "\n%% ");
2110          }
2111          fprintf(FP, "%c", hexValue[(data[row][col]>>4) & 0xf]);
2112          fprintf(FP, "%c", hexValue[data[row][col] & 0xf]);
2113       }
2114       fprintf(FP, "\n");
2115    }
2116    fprintf(FP, "%%%%EndImage\n");
2117    fprintf(FP, "%%%%EndPreview\n");
2118 
2119    for (row=0; row < image_h; row++) free(data[row]);
2120    free(data);
2121    XDestroyImage(image);
2122    XFreePixmap(mainDisplay, pixmap);
2123 }
2124 
2125 static char defXpmToGif[]="xpmtoppm %s | ppmtogif";
2126 static char defXpmToPng[]="xpmtoppm %s | pnmtopng";
2127 static char defXpmToJpeg[]="xpmtoppm %s | cjpeg";
2128 static char defPpmToGif[]="ppmquant 222 %s | ppmtogif";
2129 static char defPpmToPng[]="pnmtopng %s";
2130 static char defPpmToPngWithTrans[]="pnmtopng -transparent %s %s";
2131 static char defPpmToJpeg[]="cjpeg %s";
2132 static char defPpm6ToXpm3[]="ppmtoxpm %s";
2133 static char defXpmDeckToGifAnim[]="gifsicle -lforever --delay 10";
2134 
2135 static
InitImageMap()2136 void InitImageMap()
2137 {
2138    char *c_ptr;
2139 
2140    if (generateImageMap != INVALID) return;
2141 
2142    generateImageMap = FALSE;
2143    if (!PRTGIF || cmdLineOpenDisplay) {
2144       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GenerateImageMap")) !=
2145             NULL && UtilStrICmp(c_ptr, "true") == 0) {
2146          generateImageMap = TRUE;
2147       }
2148    }
2149    strcpy(xpmToGifCmd, defXpmToGif);
2150    if (!PRTGIF || cmdLineOpenDisplay) {
2151       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XpmToGif")) != NULL) {
2152          int count=0;
2153 
2154          strcpy(xpmToGifCmd, c_ptr);
2155          UtilTrimBlanks(xpmToGifCmd);
2156          for (c_ptr=strstr(xpmToGifCmd,"%s"); c_ptr!=NULL;
2157                c_ptr=strstr(++c_ptr,"%s")) {
2158             count++;
2159          }
2160          if (count != 1) {
2161             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2162                   TOOL_NAME, "XpmToGif", xpmToGifCmd, defXpmToGif);
2163             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2164             strcpy(xpmToGifCmd, defXpmToGif);
2165          }
2166       }
2167    }
2168    strcpy(ppmToGifCmd, defPpmToGif);
2169    if (!PRTGIF || cmdLineOpenDisplay) {
2170       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PpmToGif")) != NULL) {
2171          int count=0;
2172 
2173          strcpy(ppmToGifCmd, c_ptr);
2174          UtilTrimBlanks(ppmToGifCmd);
2175          for (c_ptr=strstr(ppmToGifCmd,"%s"); c_ptr!=NULL;
2176                c_ptr=strstr(++c_ptr,"%s")) {
2177             count++;
2178          }
2179          if (count != 1) {
2180             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2181                   TOOL_NAME, "PpmToGif", ppmToGifCmd, defPpmToGif);
2182             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2183             strcpy(ppmToGifCmd, defPpmToGif);
2184          }
2185       }
2186    }
2187    strcpy(gifFileExtension, "gif");
2188    if (!PRTGIF || cmdLineOpenDisplay) {
2189       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GifFileExtension")) !=
2190             NULL) {
2191          strcpy(gifFileExtension, c_ptr);
2192       }
2193    }
2194    strcpy(xpmToPngCmd, defXpmToPng);
2195    if (!PRTGIF || cmdLineOpenDisplay) {
2196       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XpmToPng")) != NULL) {
2197          int count=0;
2198 
2199          strcpy(xpmToPngCmd, c_ptr);
2200          UtilTrimBlanks(xpmToPngCmd);
2201          for (c_ptr=strstr(xpmToPngCmd,"%s"); c_ptr!=NULL;
2202                c_ptr=strstr(++c_ptr,"%s")) {
2203             count++;
2204          }
2205          if (count != 1) {
2206             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2207                   TOOL_NAME, "XpmToPng", xpmToPngCmd, defXpmToPng);
2208             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2209             strcpy(xpmToPngCmd, defXpmToPng);
2210          }
2211       }
2212    }
2213    strcpy(ppmToPngCmd, defPpmToPng);
2214    if (!PRTGIF || cmdLineOpenDisplay) {
2215       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PpmToPng")) != NULL) {
2216          int count=0;
2217 
2218          strcpy(ppmToPngCmd, c_ptr);
2219          UtilTrimBlanks(ppmToPngCmd);
2220          for (c_ptr=strstr(ppmToPngCmd,"%s"); c_ptr!=NULL;
2221                c_ptr=strstr(++c_ptr,"%s")) {
2222             count++;
2223          }
2224          if (count != 1) {
2225             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2226                   TOOL_NAME, "PpmToPng", ppmToPngCmd, defPpmToPng);
2227             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2228             strcpy(ppmToPngCmd, defPpmToPng);
2229          }
2230       }
2231    }
2232    strcpy(ppmToPngWithTransCmd, defPpmToPngWithTrans);
2233    if (!PRTGIF || cmdLineOpenDisplay) {
2234       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,
2235             "PpmToPngWithTransparentColor")) != NULL) {
2236          int count=0;
2237 
2238          strcpy(ppmToPngWithTransCmd, c_ptr);
2239          UtilTrimBlanks(ppmToPngWithTransCmd);
2240          for (c_ptr=strstr(ppmToPngWithTransCmd,"%s"); c_ptr!=NULL;
2241                c_ptr=strstr(++c_ptr,"%s")) {
2242             count++;
2243          }
2244          if (count != 2) {
2245             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2246                   TOOL_NAME, "PpmToPngWithTransparentColor",
2247                   ppmToPngWithTransCmd, defPpmToPngWithTrans);
2248             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2249             strcpy(ppmToPngWithTransCmd, defPpmToPngWithTrans);
2250          }
2251       }
2252    }
2253    strcpy(pngFileExtension, "png");
2254    if (!PRTGIF || cmdLineOpenDisplay) {
2255       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PngFileExtension")) !=
2256             NULL) {
2257          strcpy(pngFileExtension, c_ptr);
2258       }
2259    }
2260    strcpy(xpmToJpegCmd, defXpmToJpeg);
2261    if (!PRTGIF || cmdLineOpenDisplay) {
2262       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XpmToJpeg")) != NULL) {
2263          int count=0;
2264 
2265          strcpy(xpmToJpegCmd, c_ptr);
2266          UtilTrimBlanks(xpmToJpegCmd);
2267          for (c_ptr=strstr(xpmToJpegCmd,"%s"); c_ptr!=NULL;
2268                c_ptr=strstr(++c_ptr,"%s")) {
2269             count++;
2270          }
2271          if (count != 1) {
2272             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2273                   TOOL_NAME, "XpmToJpeg", xpmToJpegCmd, defXpmToJpeg);
2274             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2275             strcpy(xpmToJpegCmd, defXpmToJpeg);
2276          }
2277       }
2278    }
2279    strcpy(ppmToJpegCmd, defPpmToJpeg);
2280    if (!PRTGIF || cmdLineOpenDisplay) {
2281       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PpmToJpeg")) != NULL) {
2282          int count=0;
2283 
2284          strcpy(ppmToJpegCmd, c_ptr);
2285          UtilTrimBlanks(ppmToJpegCmd);
2286          for (c_ptr=strstr(ppmToJpegCmd,"%s"); c_ptr!=NULL;
2287                c_ptr=strstr(++c_ptr,"%s")) {
2288             count++;
2289          }
2290          if (count != 1) {
2291             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2292                   TOOL_NAME, "PpmToJpeg", ppmToJpegCmd, defPpmToJpeg);
2293             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2294             strcpy(ppmToJpegCmd, defPpmToJpeg);
2295          }
2296       }
2297    }
2298    strcpy(ppm6ToXpm3Cmd, defPpm6ToXpm3);
2299    if (!PRTGIF || cmdLineOpenDisplay) {
2300       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"Ppm6ToXpm3")) != NULL) {
2301          int count=0;
2302 
2303          strcpy(ppm6ToXpm3Cmd, c_ptr);
2304          UtilTrimBlanks(ppm6ToXpm3Cmd);
2305          for (c_ptr=strstr(ppm6ToXpm3Cmd,"%s"); c_ptr!=NULL;
2306                c_ptr=strstr(++c_ptr,"%s")) {
2307             count++;
2308          }
2309          if (count != 1) {
2310             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2311                   TOOL_NAME, "PpmToJpeg", ppm6ToXpm3Cmd, defPpm6ToXpm3);
2312             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2313             strcpy(ppm6ToXpm3Cmd, defPpm6ToXpm3);
2314          }
2315       }
2316    }
2317    strcpy(jpegFileExtension, "jpeg");
2318    if (!PRTGIF || cmdLineOpenDisplay) {
2319       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"JpegFileExtension")) !=
2320             NULL) {
2321          strcpy(jpegFileExtension, c_ptr);
2322       }
2323    }
2324 #ifdef _XPM3TOPPM
2325    useXPmVersion1ForImageMap = FALSE;
2326 #else /* ~_XPM3TOPPM */
2327    useXPmVersion1ForImageMap = TRUE;
2328 #endif /* _XPM3TOPPM */
2329    if (!PRTGIF || cmdLineOpenDisplay) {
2330       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,
2331             "UseXPmVersion1ForImageMap")) != NULL) {
2332          if (UtilStrICmp("false",c_ptr) == 0) {
2333             useXPmVersion1ForImageMap = FALSE;
2334          } else if (UtilStrICmp("true",c_ptr) == 0) {
2335             useXPmVersion1ForImageMap = TRUE;
2336          }
2337       }
2338    }
2339    useXPmVersion1ForXPmDeck = TRUE;
2340    if (!PRTGIF || cmdLineOpenDisplay) {
2341       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,
2342             "UseXPmVersion1ForXPmDeck")) != NULL &&
2343             UtilStrICmp("false",c_ptr) == 0) {
2344          useXPmVersion1ForXPmDeck = FALSE;
2345       }
2346    }
2347    strcpy(imageMapFileExtension, "map");
2348    if (!PRTGIF || cmdLineOpenDisplay) {
2349       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
2350             "ImageMapFileExtension")) != NULL) {
2351          strcpy(imageMapFileExtension, c_ptr);
2352       }
2353    }
2354    imageMapFileFormat = IMF_FORMAT_NCSA;
2355    if (!PRTGIF || cmdLineOpenDisplay) {
2356       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ImageMapFileFormat")) !=
2357             NULL) {
2358          if (strcmp(c_ptr, "NCSA") == 0) {
2359             imageMapFileFormat = IMF_FORMAT_NCSA;
2360          } else if (strcmp(c_ptr, "CERN") == 0) {
2361             imageMapFileFormat = IMF_FORMAT_CERN;
2362          } else {
2363             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2364                   TOOL_NAME, "ImageMapFileFormat", c_ptr, "NCSA");
2365             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2366          }
2367       }
2368    }
2369    strcpy(htmlFileExtension, "html");
2370    if (!PRTGIF || cmdLineOpenDisplay) {
2371       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
2372             "HtmlFileExtension")) != NULL && (*c_ptr != '\0')) {
2373          strcpy(htmlFileExtension, c_ptr);
2374       }
2375    }
2376    generateHtmlHref = TRUE;
2377    if (!PRTGIF || cmdLineOpenDisplay) {
2378       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "GenerateHtmlHref")) !=
2379             NULL) {
2380          if (UtilStrICmp(c_ptr, "false") == 0) {
2381             generateHtmlHref = FALSE;
2382          }
2383       }
2384    }
2385    strcpy(xpmDeckToGifAnimCmd, defXpmDeckToGifAnim);
2386    if (!PRTGIF || cmdLineOpenDisplay) {
2387       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"XpmDeckToGifAnim")) !=
2388             NULL) {
2389          strcpy(xpmDeckToGifAnimCmd, c_ptr);
2390          UtilTrimBlanks(xpmDeckToGifAnimCmd);
2391          if (strstr(xpmDeckToGifAnimCmd, "%s") != NULL) {
2392             sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
2393                   TOOL_NAME, "XpmDeckToGifAnim", xpmDeckToGifAnimCmd,
2394                   defXpmDeckToGifAnim);
2395             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2396             strcpy(xpmDeckToGifAnimCmd, defXpmDeckToGifAnim);
2397          }
2398       }
2399    }
2400 }
2401 
2402 static
ModifyToGenerateHtmlHref(value_str)2403 char *ModifyToGenerateHtmlHref(value_str)
2404    char *value_str;
2405    /* data in value_str is not supposed to be touched on return */
2406 {
2407    char *href=NULL, *name=NULL, *pound=NULL, *dot=NULL;
2408    int len=0;
2409 
2410    if (generateHtmlHref && imageMapFileFormat==IMF_FORMAT_SPYG) {
2411       if (value_str[0] == '#' && strchr(value_str, DIR_SEP) == NULL &&
2412             (((!(PRTGIF && !cmdLineOpenDisplay)) && dumpOneFilePerPage) ||
2413             (PRTGIF && !cmdLineOpenDisplay && cmdLineOneFilePerPage))) {
2414          char page_spec[MAXSTRING];
2415          int page_num=0;
2416 
2417          if (GetPageNumFromPageSpec(&value_str[1], &page_num)) {
2418             sprintf(page_spec, "%1d", page_num);
2419 
2420             if ((name=UtilStrRChr(curFileName, DIR_SEP)) == NULL) {
2421                name = curFileName;
2422             } else {
2423                name++;
2424             }
2425             pound = strchr(name, '#');
2426             if (pound != NULL) *pound = '\0';
2427             dot = UtilStrRChr(name, '.');
2428             if (dot != NULL) {
2429                *dot = '\0';
2430                len = strlen(name)+strlen(page_spec)+strlen(htmlFileExtension)+3;
2431                href = (char*)malloc((len+1)*sizeof(char));
2432                if (href == NULL) FailAllocMessage();
2433                sprintf(href, "%s-%1d.%s", name, page_num, htmlFileExtension);
2434                *dot = '.';
2435             }
2436             if (pound != NULL) *pound = '#';
2437          } else {
2438             /* Cannot get page number information, may be it's okay! */
2439          }
2440       } else {
2441          if ((name=UtilStrRChr(value_str, DIR_SEP)) == NULL) {
2442             name = value_str;
2443          } else {
2444             name++;
2445          }
2446          pound = strchr(name, '#');
2447          if (pound != NULL) *pound = '\0';
2448          dot = UtilStrRChr(name, '.');
2449          if (dot != NULL && ((UtilStrICmp(&dot[1], "obj")==0 ||
2450                UtilStrICmp(&dot[1], OBJ_FILE_EXT)==0) ||
2451                UtilStrICmp(&dot[1], "sym")==0 ||
2452                UtilStrICmp(&dot[1], SYM_FILE_EXT)==0)) {
2453             *dot = '\0';
2454             len = strlen(value_str)+strlen(htmlFileExtension)+2;
2455             if (pound != NULL) len += strlen(&pound[1])+1;
2456             href = (char*)malloc((len+1)*sizeof(char));
2457             if (href == NULL) FailAllocMessage();
2458             if (pound != NULL) {
2459                sprintf(href, "%s.%s#%s", value_str, htmlFileExtension,
2460                      &pound[1]);
2461             } else {
2462                sprintf(href, "%s.%s", value_str, htmlFileExtension);
2463             }
2464             *dot = '.';
2465          }
2466          if (pound != NULL) *pound = '#';
2467       }
2468    }
2469    return href;
2470 }
2471 
2472 static
GenerateObjImageMap(FP,ObjPtr,LtX,LtY)2473 int GenerateObjImageMap(FP, ObjPtr, LtX, LtY)
2474    FILE *FP;
2475    struct ObjRec *ObjPtr;
2476    int LtX, LtY;
2477 {
2478    register int i;
2479    int n, something_generated=FALSE;
2480    struct AttrRec *attr_ptr;
2481    struct ObjRec *obj_ptr;
2482    IntPoint *v=NULL;
2483 
2484    if ((attr_ptr=FindAttrWithName(ObjPtr, "href=", NULL)) != NULL) {
2485       char *href=ModifyToGenerateHtmlHref(attr_ptr->attr_value.s);
2486 
2487       switch (ObjPtr->type) {
2488       case OBJ_POLY:
2489       case OBJ_POLYGON:
2490          if (ObjPtr->type == OBJ_POLY) {
2491             n = ObjPtr->detail.p->n;
2492             v = ObjPtr->detail.p->vlist;
2493          } else {
2494             n = ObjPtr->detail.g->n;
2495             v = ObjPtr->detail.g->vlist;
2496          }
2497          switch (imageMapFileFormat) {
2498          case IMF_FORMAT_NCSA:
2499             fprintf(FP, "\npoly %s", attr_ptr->attr_value.s);
2500             for (i=0; i < n; i++) {
2501                fprintf(FP, " %1d,%1d", v[i].x-LtX, v[i].y-LtY);
2502             }
2503             fprintf(FP, "\n");
2504             break;
2505          case IMF_FORMAT_CERN:
2506             fprintf(FP, "\npoly");
2507             for (i=0; i < n; i++) {
2508                fprintf(FP, " (%1d,%1d)", v[i].x-LtX, v[i].y-LtY);
2509             }
2510             fprintf(FP, " %s\n", attr_ptr->attr_value.s);
2511             break;
2512          case IMF_FORMAT_SPYG:
2513             fprintf(FP, "<AREA SHAPE=\"POLY\" COORDS=\"");
2514             for (i=0; i < n; i++) {
2515                fprintf(FP, "%s%1d,%1d", (i==0 ? "" : ","),
2516                      v[i].x-LtX, v[i].y-LtY);
2517             }
2518             fprintf(FP, "\" HREF=\"%s\">\n",
2519                   (href != NULL ? href : attr_ptr->attr_value.s));
2520             break;
2521          default: break;
2522          }
2523          break;
2524       case OBJ_OVAL:
2525          if (ObjPtr->obbox.rbx-ObjPtr->obbox.ltx ==
2526                ObjPtr->obbox.rby-ObjPtr->obbox.lty) {
2527             switch (imageMapFileFormat) {
2528             case IMF_FORMAT_NCSA:
2529                fprintf(FP, "\ncircle %s %1d,%1d %1d,%1d\n",
2530                      attr_ptr->attr_value.s,
2531                      ((ObjPtr->obbox.ltx+ObjPtr->obbox.rbx)>>1)-LtX,
2532                      ((ObjPtr->obbox.lty+ObjPtr->obbox.rby)>>1)-LtY,
2533                      ObjPtr->obbox.rbx-LtX,
2534                      ((ObjPtr->obbox.lty+ObjPtr->obbox.rby)>>1)-LtY);
2535                break;
2536             case IMF_FORMAT_CERN:
2537                fprintf(FP, "\ncircle (%1d,%1d) %1d %s\n",
2538                      ((ObjPtr->obbox.ltx+ObjPtr->obbox.rbx)>>1)-LtX,
2539                      ((ObjPtr->obbox.lty+ObjPtr->obbox.rby)>>1)-LtY,
2540                      (ObjPtr->obbox.rbx-ObjPtr->obbox.ltx)>>1,
2541                      attr_ptr->attr_value.s);
2542                break;
2543             case IMF_FORMAT_SPYG:
2544                fprintf(FP, "<AREA SHAPE=\"CIRCLE\" COORDS=\"");
2545                fprintf(FP, "%1d,%1d,%1d",
2546                      ((ObjPtr->obbox.ltx+ObjPtr->obbox.rbx)>>1)-LtX,
2547                      ((ObjPtr->obbox.lty+ObjPtr->obbox.rby)>>1)-LtY,
2548                      (ObjPtr->obbox.rbx-ObjPtr->obbox.ltx)>>1);
2549                fprintf(FP, "\" HREF=\"%s\">\n",
2550                   (href != NULL ? href : attr_ptr->attr_value.s));
2551                break;
2552             default: break;
2553             }
2554          } else {
2555             switch (imageMapFileFormat) {
2556             case IMF_FORMAT_NCSA:
2557                fprintf(FP, "\nrect %s %1d,%1d %1d,%1d\n",
2558                      attr_ptr->attr_value.s,
2559                      ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2560                      ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY);
2561                break;
2562             case IMF_FORMAT_CERN:
2563                fprintf(FP, "\nrect (%1d,%1d) (%1d,%1d) %s\n",
2564                      ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2565                      ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY,
2566                      attr_ptr->attr_value.s);
2567                break;
2568             case IMF_FORMAT_SPYG:
2569                fprintf(FP, "<AREA SHAPE=\"RECT\" COORDS=\"");
2570                fprintf(FP, "%1d,%1d,%1d,%1d",
2571                      ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2572                      ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY);
2573                fprintf(FP, "\" HREF=\"%s\">\n",
2574                   (href != NULL ? href : attr_ptr->attr_value.s));
2575                break;
2576             default: break;
2577             }
2578          }
2579          break;
2580       default:
2581          switch (imageMapFileFormat) {
2582          case IMF_FORMAT_NCSA:
2583             fprintf(FP, "\nrect %s %1d,%1d %1d,%1d\n",
2584                   attr_ptr->attr_value.s,
2585                   ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2586                   ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY);
2587             break;
2588          case IMF_FORMAT_CERN:
2589             fprintf(FP, "\nrect (%1d,%1d) (%1d,%1d) %s\n",
2590                   ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2591                   ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY,
2592                   attr_ptr->attr_value.s);
2593             break;
2594          case IMF_FORMAT_SPYG:
2595             fprintf(FP, "<AREA SHAPE=\"RECT\" COORDS=\"");
2596             fprintf(FP, "%1d,%1d,%1d,%1d",
2597                   ObjPtr->obbox.ltx-LtX, ObjPtr->obbox.lty-LtY,
2598                   ObjPtr->obbox.rbx-LtX, ObjPtr->obbox.rby-LtY);
2599             fprintf(FP, "\" HREF=\"%s\">\n",
2600                   (href != NULL ? href : attr_ptr->attr_value.s));
2601             break;
2602          default: break;
2603          }
2604          break;
2605       }
2606       if (href != NULL) free(href);
2607       return TRUE;
2608    }
2609    switch (ObjPtr->type) {
2610    case OBJ_GROUP:
2611    case OBJ_ICON:
2612    case OBJ_SYM:
2613       for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
2614             obj_ptr=obj_ptr->next) {
2615          if (GenerateObjImageMap (FP, obj_ptr, LtX, LtY)) {
2616             something_generated = TRUE;;
2617          }
2618       }
2619       break;
2620    case OBJ_PIN:
2621       obj_ptr = GetPinObj(ObjPtr);
2622       if (GenerateObjImageMap(FP, obj_ptr, LtX, LtY)) {
2623          something_generated = TRUE;;
2624       }
2625       break;
2626    }
2627    return something_generated;
2628 }
2629 
2630 static
GenerateHtmlHeader(map_fp)2631 void GenerateHtmlHeader(map_fp)
2632    FILE *map_fp;
2633 {
2634    struct AttrRec *attr_ptr;
2635 
2636    fprintf(map_fp, "<HTML>\n<HEAD>\n");
2637    if (curPage->name != NULL && *curPage->name != '\0') {
2638       fprintf(map_fp, "<TITLE>\n%s\n</TITLE>\n", curPage->name);
2639    } else if ((attr_ptr=FindFileAttrWithName("title=")) != NULL) {
2640       fprintf(map_fp, "<TITLE>\n%s\n</TITLE>\n",
2641             attr_ptr->attr_value.s);
2642    }
2643    if ((attr_ptr=FindFileAttrWithName("base=")) != NULL) {
2644       fprintf(map_fp, "<BASE HREF=\"%s\">\n", attr_ptr->attr_value.s);
2645    }
2646    if ((attr_ptr=FindFileAttrWithName("made=")) != NULL) {
2647       fprintf(map_fp, "<LINK REV=\"made\" HREF=\"%s\">\n",
2648             attr_ptr->attr_value.s);
2649    }
2650    if ((attr_ptr=FindFileAttrWithName("keywords=")) != NULL) {
2651       fprintf(map_fp, "<META HTTP-EQUIV=\"Keywords\" CONTENT=\"%s\">\n",
2652             attr_ptr->attr_value.s);
2653    }
2654    fprintf(map_fp, "</HEAD>\n<BODY>\n");
2655 }
2656 
2657 static
GenerateUseMapHeader(map_fp,gif_fname,map_fname)2658 void GenerateUseMapHeader(map_fp, gif_fname, map_fname)
2659    FILE *map_fp;
2660    char *gif_fname, *map_fname;
2661 {
2662    char *gif_fname_ptr=UtilStrRChr(gif_fname, DIR_SEP);
2663    char *map_fname_ptr=UtilStrRChr(map_fname, DIR_SEP);
2664    int page_num=0;
2665    struct AttrRec *attr_ptr;
2666 
2667    if (gif_fname_ptr != NULL) gif_fname_ptr++;
2668    if (map_fname_ptr != NULL) map_fname_ptr++;
2669    fprintf(map_fp, "<H1>\n");
2670    attr_ptr = FindFileAttrWithName("alt=");
2671    if (attr_ptr != NULL) {
2672       fprintf(map_fp, "<IMG ALT=\"%s\" SRC=\"%s\" USEMAP=\"%s#p%1d\">\n",
2673             attr_ptr->attr_value.s,
2674             (gif_fname_ptr==NULL ? "unknown" : gif_fname_ptr),
2675             (map_fname_ptr==NULL ? "unknown" : map_fname_ptr), page_num);
2676    } else {
2677       fprintf(map_fp, "<IMG SRC=\"%s\" USEMAP=\"%s#p%1d\">\n",
2678             (gif_fname_ptr==NULL ? "unknown" : gif_fname_ptr),
2679             (map_fname_ptr==NULL ? "unknown" : map_fname_ptr), page_num);
2680    }
2681    fprintf(map_fp, "</H1>\n");
2682    fprintf(map_fp, "<MAP NAME=\"p%1d\">\n", page_num);
2683 }
2684 
2685 static
GenerateUseMapTrailer(map_fp,W,H)2686 void GenerateUseMapTrailer(map_fp, W, H)
2687    FILE *map_fp;
2688    int W, H;
2689 {
2690    struct AttrRec *attr_ptr=FindFileAttrWithName("href=");
2691 
2692    if (attr_ptr != NULL) {
2693       char *href=ModifyToGenerateHtmlHref(attr_ptr->attr_value.s);
2694 
2695       fprintf(map_fp, "<AREA SHAPE=\"RECT\" COORDS=\"");
2696       fprintf(map_fp, "0,0,%1d,%1d", W, H);
2697       fprintf(map_fp, "\" HREF=\"%s\">\n",
2698             (href != NULL ? href : attr_ptr->attr_value.s));
2699       if (href != NULL) free(href);
2700    }
2701    fprintf(map_fp, "</MAP>\n");
2702 }
2703 
2704 static
GenerateHtmlTrailer(map_fp)2705 void GenerateHtmlTrailer(map_fp)
2706    FILE *map_fp;
2707 {
2708    fprintf(map_fp, "</BODY>\n</HTML>\n");
2709 }
2710 
2711 static
OpenMapFile(pszMapFile)2712 FILE *OpenMapFile(pszMapFile)
2713    char *pszMapFile;
2714 {
2715    FILE *pFile=fopen(pszMapFile, "w");
2716 
2717    if (pFile == NULL) {
2718       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
2719             pszMapFile);
2720       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2721       return NULL;
2722    }
2723    return pFile;
2724 }
2725 
2726 static
DumpCommentInBitmapExport(fp)2727 void DumpCommentInBitmapExport(fp)
2728    FILE *fp;
2729 {
2730    if (commentInBitmapExport) {
2731       fprintf(fp, "/*\n");
2732       fprintf(fp, " * @%s%s\n", "(#)$H", "eader$");
2733       fprintf(fp, " */\n");
2734    }
2735 }
2736 
2737 static
ColorNameToXPmStr(color_name,s)2738 void ColorNameToXPmStr(color_name, s)
2739    char *color_name, *s;
2740 {
2741    if (*color_name == '#') {
2742       strcpy(s, color_name);
2743    } else {
2744       XColor exact_def;
2745 
2746       if (TgifParseColor(color_name, &exact_def)) {
2747          unsigned int r=0, g=0, b=0;
2748          double dr=(double)0, dg=(double)0, db=(double)0;
2749 
2750          dr = ((double)exact_def.red) / ((double)maxRGB) * ((double)255);
2751          dg = ((double)exact_def.green) / ((double)maxRGB) * ((double)255);
2752          db = ((double)exact_def.blue) / ((double)maxRGB) * ((double)255);
2753          r = (unsigned int)round(dr);
2754          g = (unsigned int)round(dg);
2755          b = (unsigned int)round(db);
2756          if (r > 255) r = 255;
2757          if (g > 255) g = 255;
2758          if (b > 255) b = 255;
2759          sprintf(s, "#%02x%02x%02x", r, g, b);
2760       } else {
2761          strcpy(s, color_name);
2762       }
2763    }
2764 }
2765 
2766 static
Xpm3ToXpm1(gif_fname)2767 int Xpm3ToXpm1(gif_fname)
2768    char *gif_fname;
2769 {
2770    int i=0, j=0, rc=0, ncolors=0, chars_per_pixel=0, line_len=0;
2771    int first_pixel_is_bg=FALSE, image_w=0, image_h=0, w=0, h=0;
2772    char *color_char=NULL, **color_str=NULL, *xpm_data=NULL, *xpm_data_ptr=NULL;
2773    char *psz=NULL, name[MAXPATHLENGTH], s[MAXSTRING];
2774    int watch_cursor=watchCursorOnMainWindow, saved_color_display=colorDisplay;
2775    FILE *fp=NULL;
2776 
2777    psz = UtilStrRChr(gif_fname, DIR_SEP);
2778    if (psz == NULL) {
2779       UtilStrCpyN(name, sizeof(name), gif_fname);
2780    } else {
2781       UtilStrCpyN(name, sizeof(name), &psz[1]);
2782    }
2783    psz = UtilStrRChr(name, '.');
2784    if (psz != NULL) {
2785       *psz = '\0';
2786    }
2787    UtilTrimBlanks(name);
2788    if (*name == '\0') {
2789 #ifdef _TGIF_DBG /* debug, do not translate */
2790       fprintf(stderr, "Unexpected empty string in Xpm3ToXpm1().\n");
2791 #endif /* _TGIF_DBG */
2792       return FALSE;
2793    }
2794    if (!watch_cursor) {
2795       SetWatchCursor(drawWindow);
2796       SetWatchCursor(mainWindow);
2797    }
2798    colorDisplay = FALSE;
2799    rc = MyReadPixmapFile(gif_fname,
2800          &image_w, &image_h, &w, &h, NULL, NULL, NULL, NULL,
2801          &ncolors, &chars_per_pixel, &first_pixel_is_bg, &color_char,
2802          &color_str, NULL, &xpm_data);
2803    colorDisplay = saved_color_display;
2804    if (rc != BitmapSuccess) {
2805       if (!watch_cursor) {
2806          SetDefaultCursor(mainWindow);
2807          ShowCursor();
2808       }
2809       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_IMPORT_XPM_FILE), gif_fname);
2810       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2811       return FALSE;
2812    }
2813    if ((fp=fopen(gif_fname, "w")) == NULL) {
2814       if (!watch_cursor) {
2815          SetDefaultCursor(mainWindow);
2816          ShowCursor();
2817       }
2818       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
2819             gif_fname);
2820       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2821       return FALSE;
2822    }
2823    writeFileFailed = FALSE;
2824 
2825    /* DumpXpmHeader(fp, w, h, name, 0, 0, 0, 0); */
2826 
2827    DumpCommentInBitmapExport(fp);
2828    /* do not translate -- program constants */
2829    fprintf(fp, "#define %s_format 1\n", name);
2830    fprintf(fp, "#define %s_width %1d\n", name, image_w);
2831    fprintf(fp, "#define %s_height %1d\n", name, image_h);
2832    fprintf(fp, "#define %s_ncolors %1d\n", name, ncolors);
2833    fprintf(fp, "#define %s_chars_per_pixel %1d\n", name, chars_per_pixel);
2834    if (xpmInXGrabSCFormat) {
2835       fprintf(fp, "static char * %s_colors[] = {\n", name);
2836    } else {
2837       fprintf(fp, "static char *%s_colors[] = {\n", name);
2838    }
2839    /* DumpXPmColors(fp); */
2840    if (xpmInXGrabSCFormat) {
2841       for (i=0; i < ncolors-1; i++) {
2842          if (fprintf(fp, "\"") == EOF) writeFileFailed = TRUE;
2843          for (j = 0; j < chars_per_pixel; j++) {
2844             if (fprintf(fp, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
2845                writeFileFailed = TRUE;
2846             }
2847          }
2848          ColorNameToXPmStr(color_str[i], s);
2849          if (fprintf(fp, "\", \"%s\"\n", s) == EOF) writeFileFailed = TRUE;
2850       }
2851       if (fprintf(fp, "\"") == EOF) writeFileFailed = TRUE;
2852       for (j = 0; j < chars_per_pixel; j++) {
2853          if (fprintf(fp, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
2854             writeFileFailed = TRUE;
2855          }
2856       }
2857       ColorNameToXPmStr(color_str[i], s);
2858       if (fprintf(fp, "\", \"%s\"\n} ;\n", s) == EOF) {
2859          writeFileFailed = TRUE;
2860       }
2861    } else {
2862       for (i=0; i < ncolors-1; i++) {
2863          if (fprintf(fp, "   \"") == EOF) writeFileFailed = TRUE;
2864          for (j = 0; j < chars_per_pixel; j++) {
2865             if (fprintf(fp, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
2866                writeFileFailed = TRUE;
2867             }
2868          }
2869          if (fprintf(fp, "\", \"%s\",\n", color_str[i]) == EOF) {
2870             writeFileFailed = TRUE;
2871          }
2872       }
2873       if (fprintf(fp, "   \"") == EOF) writeFileFailed = TRUE;
2874       for (j = 0; j < chars_per_pixel; j++) {
2875          if (fprintf(fp, "%c", color_char[i*chars_per_pixel+j]) == EOF) {
2876             writeFileFailed = TRUE;
2877          }
2878       }
2879       if (fprintf(fp, "\", \"%s\"\n};\n", color_str[i]) == EOF) {
2880          writeFileFailed = TRUE;
2881       }
2882    }
2883 
2884    if (xpmInXGrabSCFormat) {
2885       fprintf(fp, "static char * %s_pixels[] = {\n", name);
2886    } else {
2887       fprintf(fp, "static char *%s_pixels[] = {\n", name);
2888    }
2889    line_len = chars_per_pixel * image_w;
2890    xpm_data_ptr = xpm_data;
2891    for (i=0; i < image_h; i++) {
2892       char saved_ch=xpm_data_ptr[line_len];
2893 
2894       xpm_data_ptr[line_len] = '\0';
2895       fprintf(fp, "\"%s\"", xpm_data_ptr);
2896       xpm_data_ptr[line_len] = saved_ch;
2897       xpm_data_ptr += line_len;
2898 
2899       if (i == image_h-1) {
2900          if (xpmInXGrabSCFormat) {
2901             if (fprintf(fp, ",\n} ;\n") == EOF) writeFileFailed = TRUE;
2902          } else {
2903             if (fprintf(fp, "\n};\n") == EOF) writeFileFailed = TRUE;
2904          }
2905       } else if (fprintf(fp, ",\n") == EOF) {
2906          writeFileFailed = TRUE;
2907       }
2908    }
2909    fclose(fp);
2910 
2911    if (!watch_cursor) {
2912       SetDefaultCursor(mainWindow);
2913       ShowCursor();
2914    }
2915    return TRUE;
2916 }
2917 
2918 static
ConvertXpmToGif(xpm_fname,gif_fname,src_is_ppm,where_to_print)2919 int ConvertXpmToGif(xpm_fname, gif_fname, src_is_ppm, where_to_print)
2920    char *xpm_fname, *gif_fname;
2921    int src_is_ppm, where_to_print;
2922 {
2923    char cmd[MAXSTRING<<1], netpbm_msg[MAXSTRING<<1], buf[1024];
2924    FILE *gif_fp=fopen(gif_fname,"w"), *pfp=NULL;
2925    int bytes_read=0, watch_cursor=watchCursorOnMainWindow;
2926 
2927    if (gif_fp == NULL) {
2928       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
2929             gif_fname);
2930       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2931       return FALSE;
2932    }
2933    switch (where_to_print) {
2934    case GIF_FILE:
2935    case HTML_FILE:
2936       *netpbm_msg = '\0';
2937       if (src_is_ppm) {
2938          sprintf(cmd, ppmToGifCmd, xpm_fname);
2939          if (strncmp(cmd, "ppm", 3) == 0) {
2940             sprintf(netpbm_msg, TgLoadString(STID_NETPBM_PROGS_VISIT_HOME_PAGE),
2941                   TOOL_NAME, homePageURL);
2942          }
2943       } else {
2944          sprintf(cmd, xpmToGifCmd, xpm_fname);
2945          if (strncmp(cmd, "xpmtop", 6) == 0) {
2946             sprintf(netpbm_msg, TgLoadString(STID_NETPBM_PROGS_VISIT_HOME_PAGE),
2947                   TOOL_NAME, homePageURL);
2948          }
2949       }
2950       if (!FindProgramInPath(cmd, netpbm_msg, FALSE)) {
2951          fclose(gif_fp);
2952          unlink(gif_fname);
2953          return FALSE;
2954       }
2955       break;
2956    case PNG_FILE:
2957       *netpbm_msg = '\0';
2958       if (src_is_ppm) {
2959          if (pngExportHasTransparentColor) {
2960             sprintf(cmd, ppmToPngWithTransCmd, pngExportTransparentColor,
2961                   xpm_fname);
2962             if (strncmp(cmd, "pnmtop", 6) == 0) {
2963                sprintf(netpbm_msg,
2964                      TgLoadString(STID_NETPBM_PNMTOPNG_VST_HOME_PAGE),
2965                      TOOL_NAME, homePageURL);
2966             }
2967          } else {
2968             sprintf(cmd, ppmToPngCmd, xpm_fname);
2969             if (strncmp(cmd, "pnmtop", 6) == 0) {
2970                sprintf(netpbm_msg,
2971                      TgLoadString(STID_NETPBM_PNMTOPNG_VST_HOME_PAGE),
2972                      TOOL_NAME, homePageURL);
2973             }
2974          }
2975       } else {
2976          sprintf(cmd, xpmToPngCmd, xpm_fname);
2977          if (strncmp(cmd, "xpmtop", 6) == 0) {
2978             sprintf(netpbm_msg,
2979                   TgLoadString(STID_NETPBM_PNMTOPNG_VST_HOME_PAGE), TOOL_NAME,
2980                   homePageURL);
2981          }
2982       }
2983       if (!FindProgramInPath(cmd, netpbm_msg, FALSE)) {
2984          fclose(gif_fp);
2985          unlink(gif_fname);
2986          return FALSE;
2987       }
2988       break;
2989    case JPEG_FILE:
2990       *netpbm_msg = '\0';
2991       if (src_is_ppm) {
2992          sprintf(cmd, ppmToJpegCmd, xpm_fname);
2993          if (strncmp(cmd, "cjpeg", 5) == 0) {
2994             sprintf(netpbm_msg, TgLoadString(STID_NETPBM_JPEG_VST_HOME_PAGE),
2995                   TOOL_NAME, homePageURL);
2996          }
2997       } else {
2998          sprintf(cmd, xpmToJpegCmd, xpm_fname);
2999          if (strncmp(cmd, "xpmtop", 6) == 0) {
3000             sprintf(netpbm_msg, TgLoadString(STID_NETPBM_JPEG_VST_HOME_PAGE),
3001                   TOOL_NAME, homePageURL);
3002          }
3003       }
3004       if (!FindProgramInPath(cmd, netpbm_msg, FALSE)) {
3005          fclose(gif_fp);
3006          unlink(gif_fname);
3007          return FALSE;
3008       }
3009       break;
3010    case XBM_FILE:
3011       sprintf(cmd, ppm6ToXpm3Cmd, xpm_fname);
3012       *netpbm_msg = '\0';
3013       if (strncmp(cmd, "ppmtox", 6) == 0) {
3014          sprintf(netpbm_msg, TgLoadString(STID_NETPBM_JPEG_VST_HOME_PAGE),
3015                TOOL_NAME, homePageURL);
3016       }
3017       if (!FindProgramInPath(cmd, netpbm_msg, FALSE)) {
3018          fclose(gif_fp);
3019          unlink(gif_fname);
3020          return FALSE;
3021       }
3022       break;
3023    }
3024    sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM), cmd);
3025    Msg(gszMsgBox);
3026    SetStringStatus(gszMsgBox);
3027    XSync(mainDisplay, False);
3028    if ((pfp=(FILE*)popen(cmd, "r")) == NULL) {
3029       fclose(gif_fp);
3030       unlink(gif_fname);
3031       sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_EXECUTE_CMD), cmd);
3032       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3033       return FALSE;
3034    }
3035    if (!watch_cursor) {
3036       SetWatchCursor(drawWindow);
3037       SetWatchCursor(mainWindow);
3038    }
3039    while ((bytes_read=fread(buf, sizeof(char), sizeof(buf), pfp)) > 0) {
3040       if ((int)fwrite(buf, sizeof(char), bytes_read, gif_fp) <= 0) {
3041          writeFileFailed = TRUE;
3042          break;
3043       }
3044    }
3045    pclose(pfp);
3046    if (!watch_cursor) {
3047       SetDefaultCursor(mainWindow);
3048       ShowCursor();
3049    }
3050    SetStringStatus(TgLoadCachedString(CSTID_DOTS_DONE));
3051    fclose(gif_fp);
3052    if (writeFileFailed) {
3053       return FailToWriteFileMessage(gif_fname);
3054    }
3055    if (whereToPrint == XBM_FILE && xpmOutputVersion == 1) {
3056       return Xpm3ToXpm1(gif_fname);
3057    }
3058    return TRUE;
3059 }
3060 
3061 #define TGV_FILE_NAME         0
3062 #define TGV_CUR_NUM           1
3063 #define TGV_FIRST_NUM         2
3064 #define TGV_LAST_NUM          3
3065 #define TGV_PREV_NUM          4
3066 #define TGV_PREV_NUM_NO_WRAP  5
3067 #define TGV_NEXT_NUM          6
3068 #define TGV_NEXT_NUM_NO_WRAP  7
3069 #define TGV_TITLE             8
3070 #define TGV_MAP_WIDTH         9
3071 #define TGV_MAP_HEIGHT       10
3072 #define TGV_MAP_OBJS         11
3073 
3074 struct tagTgVars {
3075    char *var_name;
3076    int var_type;
3077 } gszTgVars[] = {
3078    { "&tgvfilename", TGV_FILE_NAME },
3079    { "&tgvcurnum", TGV_CUR_NUM },
3080    { "&tgvfirstnum", TGV_FIRST_NUM },
3081    { "&tgvlastnum", TGV_LAST_NUM },
3082    { "&tgvprevnum", TGV_PREV_NUM },
3083    { "&tgvprevnumnowrap", TGV_PREV_NUM_NO_WRAP },
3084    { "&tgvnextnum", TGV_NEXT_NUM },
3085    { "&tgvnextnumnowrap", TGV_NEXT_NUM_NO_WRAP },
3086    { "&tgvtitle", TGV_TITLE },
3087    { "&tgvmapwidth", TGV_MAP_WIDTH },
3088    { "&tgvmapheight", TGV_MAP_HEIGHT },
3089    { "&tgvmapobjs", TGV_MAP_OBJS },
3090    { NULL, INVALID }
3091 };
3092 
3093 static
FindTgVarType(buf)3094 int FindTgVarType(buf)
3095    char *buf;
3096 {
3097    struct tagTgVars *ptv=NULL;
3098 
3099    for (ptv=gszTgVars; ptv->var_name != NULL; ptv++) {
3100       if (UtilStrICmp(buf, ptv->var_name) == 0) {
3101          return ptv->var_type;
3102       }
3103    }
3104    return INVALID;
3105 }
3106 
3107 static
GenerateTemplateHtmlVar(map_fp,var_type,gif_fname,map_fname,fname,LtX,LtY,RbX,RbY)3108 void GenerateTemplateHtmlVar(map_fp, var_type, gif_fname, map_fname, fname,
3109       LtX, LtY, RbX, RbY)
3110    FILE *map_fp;
3111    char *gif_fname, *map_fname, *fname;
3112    int var_type, LtX, LtY, RbX, RbY;
3113 {
3114    struct ObjRec *obj_ptr=NULL;
3115    struct AttrRec *attr_ptr=NULL;
3116 
3117    switch (var_type) {
3118    case TGV_FILE_NAME: fprintf(map_fp, "%s", fname); break;
3119    case TGV_CUR_NUM: fprintf(map_fp, "%1d", curPageNum); break;
3120    case TGV_FIRST_NUM: fprintf(map_fp, "1"); break;
3121    case TGV_LAST_NUM: fprintf(map_fp, "%1d", lastPageNum); break;
3122    case TGV_PREV_NUM:
3123       if (curPageNum == 1) {
3124          fprintf(map_fp, "%1d", lastPageNum);
3125       } else {
3126          fprintf(map_fp, "%1d", curPageNum-1);
3127       }
3128       break;
3129    case TGV_PREV_NUM_NO_WRAP:
3130       if (curPageNum == 1) {
3131          fprintf(map_fp, "1");
3132       } else {
3133          fprintf(map_fp, "%1d", curPageNum-1);
3134       }
3135       break;
3136    case TGV_NEXT_NUM:
3137       if (curPageNum == lastPageNum) {
3138          fprintf(map_fp, "1");
3139       } else {
3140          fprintf(map_fp, "%1d", curPageNum+1);
3141       }
3142       break;
3143    case TGV_NEXT_NUM_NO_WRAP:
3144       if (curPageNum == lastPageNum) {
3145          fprintf(map_fp, "%1d", lastPageNum);
3146       } else {
3147          fprintf(map_fp, "%1d", curPageNum+1);
3148       }
3149       break;
3150    case TGV_TITLE:
3151       if (curPage->name != NULL && *curPage->name != '\0') {
3152          fprintf(map_fp, "%s", curPage->name);
3153       } else if ((attr_ptr=FindFileAttrWithName("title=")) != NULL) {
3154          fprintf(map_fp, "%s", attr_ptr->attr_value.s);
3155       } else {
3156          fprintf(map_fp, TgLoadCachedString(CSTID_PARANED_UNKNOWN));
3157       }
3158       break;
3159    case TGV_MAP_WIDTH: fprintf(map_fp, "%1d", RbX-LtX); break;
3160    case TGV_MAP_HEIGHT: fprintf(map_fp, "%1d", RbY-LtY); break;
3161    case TGV_MAP_OBJS:
3162       for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
3163          if (GenerateObjImageMap(map_fp, obj_ptr, LtX, LtY)) {
3164          }
3165       }
3166       break;
3167    }
3168 }
3169 
3170 static
GenerateTemplateHtmlFile(map_fp,tmpl_fp,gif_fname,map_fname,LtX,LtY,RbX,RbY)3171 void GenerateTemplateHtmlFile(map_fp, tmpl_fp, gif_fname, map_fname,
3172       LtX, LtY, RbX, RbY)
3173    FILE *map_fp, *tmpl_fp;
3174    char *gif_fname, *map_fname;
3175    int LtX, LtY, RbX, RbY;
3176 {
3177    char *buf=NULL, *fname=NULL, *c_ptr=NULL;
3178    int line_num=0;
3179 
3180    if ((c_ptr=UtilStrRChr(curFileName, DIR_SEP)) == NULL) {
3181       fname = UtilStrDup(curFileName);
3182    } else {
3183       fname = UtilStrDup(++c_ptr);
3184    }
3185    if (fname == NULL) FailAllocMessage();
3186    if ((c_ptr=strchr(fname, '#')) != NULL) *c_ptr = '\0';
3187    GetRealBaseName(fname);
3188    if ((c_ptr=UtilStrRChr(fname, '.')) != NULL) *c_ptr = '\0';
3189 
3190    while ((buf=UtilGetALine(tmpl_fp)) != NULL) {
3191       char *psz_start=buf, *psz=NULL, *psz1=NULL;
3192 
3193       line_num++;
3194       if (*psz_start == '\0') {
3195          fprintf(map_fp, "%s\n", psz_start);
3196          UtilFree(buf);
3197          continue;
3198       }
3199       while ((psz=strstr(psz_start,"&tgv")) != NULL &&
3200             (psz1=strchr(psz,';')) != NULL) {
3201          int var_type=INVALID;
3202 
3203          *psz1 = '\0';
3204          if ((var_type=FindTgVarType(psz)) != INVALID) {
3205             *psz = '\0';
3206             fprintf(map_fp, "%s", psz_start);
3207             *psz = '&';
3208             psz_start = &psz1[1];
3209             GenerateTemplateHtmlVar(map_fp, var_type, gif_fname, map_fname,
3210                   fname, LtX, LtY, RbX, RbY);
3211          } else {
3212             fprintf(map_fp, "%s", psz_start);
3213             psz_start = psz1;
3214          }
3215          *psz1 = ';';
3216       }
3217       if (psz_start != NULL) {
3218          fprintf(map_fp, "%s\n", psz_start);
3219       } else {
3220          fprintf(map_fp, "\n");
3221       }
3222       UtilFree(buf);
3223    }
3224    UtilFree(fname);
3225 }
3226 
3227 static
GenerateImageMap(XpmFileName,src_is_ppm,LtX,LtY,RbX,RbY,nPageNumInFileName)3228 void GenerateImageMap(XpmFileName, src_is_ppm, LtX, LtY, RbX, RbY,
3229       nPageNumInFileName)
3230    char *XpmFileName;
3231    int src_is_ppm, LtX, LtY, RbX, RbY, nPageNumInFileName;
3232 {
3233    char map_fname[MAXPATHLENGTH+1], gif_fname[MAXPATHLENGTH+1];
3234    char tmpl_fname[MAXPATHLENGTH+1];
3235    struct ObjRec *obj_ptr=NULL;
3236    FILE *map_fp=NULL, *tmpl_fp=NULL;
3237    int xpm_ext_len, len, something_generated=FALSE, short_name=FALSE;
3238    struct AttrRec *attr_ptr=NULL;
3239    char *psz=UtilStrRChr(XpmFileName,DIR_SEP), *rest=NULL;
3240 
3241    *map_fname = *gif_fname = *tmpl_fname = '\0';
3242    len = strlen(XpmFileName);
3243    if (psz == NULL) {
3244       psz = UtilStrRChr(XpmFileName, '.');
3245       if (psz == NULL) {
3246          sprintf(gszMsgBox, TgLoadString(STID_FNAME_FORMAT_ERROR_IN_FUNC),
3247                "GenerateImageMap()");
3248          FatalUnexpectedError(gszMsgBox, NULL);
3249          return;
3250       }
3251       xpm_ext_len = strlen(psz);
3252    } else {
3253       char *psz1=NULL;
3254 
3255       *psz = '\0';
3256       psz1 = UtilStrRChr(&psz[1], '.');
3257       if (psz1 == NULL) {
3258          *psz = DIR_SEP;
3259          sprintf(gszMsgBox, TgLoadString(STID_FNAME_FORMAT_ERROR_IN_FUNC),
3260                "GenerateImageMap()");
3261          FatalUnexpectedError(gszMsgBox, NULL);
3262          return;
3263       }
3264       xpm_ext_len = strlen(psz1);
3265       *psz = DIR_SEP;
3266    }
3267    if (XpmFileName[len-xpm_ext_len] != '.') {
3268       sprintf(gszMsgBox, TgLoadString(STID_FNAME_FORMAT_ERROR_IN_FUNC),
3269             "GenerateImageMap()");
3270       FatalUnexpectedError(gszMsgBox, NULL);
3271       return;
3272    }
3273    XpmFileName[len-xpm_ext_len] = '\0';
3274    switch (whereToPrint) {
3275    case GIF_FILE:
3276       sprintf(map_fname, "%s%s%s", XpmFileName,
3277             *imageMapFileExtension == '\0' ? "" : ".", imageMapFileExtension);
3278       sprintf(gif_fname, "%s%s%s", XpmFileName,
3279             *gifFileExtension == '\0' ? "" : ".", gifFileExtension);
3280       break;
3281    case HTML_FILE:
3282       if (*gszHhtmlExportTemplate != '\0') {
3283          if (*gszHhtmlExportTemplate == DIR_SEP) {
3284             strcpy(tmpl_fname, gszHhtmlExportTemplate);
3285          } else {
3286             char *psz=UtilStrRChr(XpmFileName, DIR_SEP);
3287 
3288             if (psz == NULL) {
3289                strcpy(tmpl_fname, gszHhtmlExportTemplate);
3290             } else {
3291                *psz = '\0';
3292                sprintf(tmpl_fname, "%s%c%s", XpmFileName, DIR_SEP,
3293                      gszHhtmlExportTemplate);
3294                *psz = DIR_SEP;
3295             }
3296          }
3297       }
3298       sprintf(map_fname, "%s%s%s", XpmFileName,
3299             *htmlFileExtension == '\0' ? "" : ".", htmlFileExtension);
3300       sprintf(gif_fname, "%s%s%s", XpmFileName,
3301             *gifFileExtension == '\0' ? "" : ".", gifFileExtension);
3302       break;
3303    case PNG_FILE:
3304       *map_fname = '\0';
3305       sprintf(gif_fname, "%s%s%s", XpmFileName,
3306             *pngFileExtension == '\0' ? "" : ".", pngFileExtension);
3307       break;
3308    case JPEG_FILE:
3309       *map_fname = '\0';
3310       sprintf(gif_fname, "%s%s%s", XpmFileName,
3311             *jpegFileExtension == '\0' ? "" : ".", jpegFileExtension);
3312       break;
3313    case XBM_FILE:
3314       *map_fname = '\0';
3315       sprintf(gif_fname, "%s.xpm", XpmFileName);
3316       break;
3317    }
3318    XpmFileName[len-xpm_ext_len] = '.';
3319 
3320    if ((short_name=IsPrefix(bootDir, gif_fname, &rest))) ++rest;
3321    sprintf(gszMsgBox, TgLoadString(STID_CONVERTING_INTO_NAMED_FILE), rest);
3322    if (PRTGIF && !cmdLineStdOut) {
3323       if (!cmdLineQuiet) {
3324          fprintf(stderr, "%s\n", gszMsgBox);
3325       }
3326    } else {
3327       Msg(gszMsgBox);
3328    }
3329    if (*tmpl_fname != '\0' && whereToPrint == HTML_FILE &&
3330          ((tmpl_fp=fopen(tmpl_fname,"r")) == NULL)) {
3331       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_HTML_TMPL_READ),
3332             tmpl_fname);
3333       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3334       return;
3335    }
3336    if (!ConvertXpmToGif(XpmFileName, gif_fname, src_is_ppm, whereToPrint)) {
3337       if (tmpl_fp != NULL) fclose(tmpl_fp);
3338       return;
3339    }
3340    switch (whereToPrint) {
3341    case GIF_FILE:
3342       if ((attr_ptr=FindFileAttrWithName("href=")) != NULL) {
3343          map_fp = OpenMapFile(map_fname);
3344          if (map_fp != NULL) {
3345             Msg(TgLoadCachedString(CSTID_GENERATING_IMAGEMAP_FILE_DOTS));
3346             fprintf(map_fp, "default %s\n", attr_ptr->attr_value.s);
3347             for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
3348                if (GenerateObjImageMap(map_fp, obj_ptr, LtX, LtY)) {
3349                   something_generated = TRUE;
3350                }
3351             }
3352             fclose(map_fp);
3353             Msg("");
3354             sprintf(gszMsgBox, TgLoadString(STID_NAMED_IMAGEMAP_FILE_GEN),
3355                   map_fname);
3356             Msg(gszMsgBox);
3357          }
3358       } else if (generateImageMap) {
3359          if (nPageNumInFileName) {
3360             /* surpress the error message if we are print one file per page */
3361          } else if (something_generated) {
3362             sprintf(gszMsgBox, TgLoadString(STID_CANT_FND_FATTR_IMGMAP_NOT_GEN),
3363                   "href=");
3364             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3365          } else {
3366             sprintf(gszMsgBox, TgLoadString(STID_CANT_FND_FATTR_NO_IMGMAP_GIF),
3367                   "href=");
3368             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3369          }
3370       }
3371       break;
3372    case HTML_FILE:
3373       map_fp = OpenMapFile(map_fname);
3374       if (map_fp != NULL) {
3375          int saved_image_map_file_format=imageMapFileFormat;
3376 
3377          if (tmpl_fp == NULL) {
3378             Msg(TgLoadCachedString(CSTID_GENERATING_HTML_FILE_DOTS));
3379             GenerateHtmlHeader(map_fp);
3380             GenerateUseMapHeader(map_fp, gif_fname, map_fname);
3381             imageMapFileFormat = IMF_FORMAT_SPYG;
3382             for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
3383                if (GenerateObjImageMap(map_fp, obj_ptr, LtX, LtY)) {
3384                   something_generated = TRUE;
3385                }
3386             }
3387             GenerateUseMapTrailer(map_fp, RbX-LtX, RbY-LtY);
3388             GenerateHtmlTrailer(map_fp);
3389          } else {
3390             sprintf(gszMsgBox,
3391                   TgLoadCachedString(CSTID_GEN_TEMPLATE_HTML_FILE_DOTS),
3392                   tmpl_fname);
3393             Msg(gszMsgBox);
3394             imageMapFileFormat = IMF_FORMAT_SPYG;
3395             GenerateTemplateHtmlFile(map_fp, tmpl_fp, gif_fname, map_fname,
3396                   LtX, LtY, RbX, RbY);
3397             fclose(tmpl_fp);
3398          }
3399          Msg("");
3400          fclose(map_fp);
3401          imageMapFileFormat = saved_image_map_file_format;
3402          sprintf(gszMsgBox, TgLoadString(STID_NAMED_HTML_FILE_GEN),
3403                map_fname);
3404          Msg(gszMsgBox);
3405       }
3406       break;
3407 
3408    case PNG_FILE: break;
3409    case JPEG_FILE: break;
3410    case PPM_FILE: break;
3411    case XBM_FILE: break;
3412    }
3413 }
3414 
3415 #ifdef NOT_DEFINED
3416 #ifdef _TGIF_DBG /* debug, do not translate */
3417 static
DebugXPmColors()3418 void DebugXPmColors()
3419 {
3420    int i=0;
3421 
3422    fprintf(stderr, "\nnumColorsToDump = %1d\n", numColorsToDump);
3423    fprintf(stderr, "maxColors = %1d\n", maxColors);
3424    fprintf(stderr, "\nThe following indices ranges from 0 to maxColors-1:\n");
3425    for (i=0; i < maxColors; i++) {
3426       if (mainVisual->class == TrueColor) {
3427          fprintf(stderr, "%s[%3d]=%3d, %s[%3d]=0x%06lx\n",
3428                "colorIndexToDumpIndex", i, colorIndexToDumpIndex[i],
3429                "colorPixels", i, (long)colorPixels[i]);
3430       } else {
3431          fprintf(stderr, "%s[%3d]=%3d, %s[%3d]=%3d\n",
3432                "colorIndexToDumpIndex", i, colorIndexToDumpIndex[i],
3433                "colorPixels", i, colorPixels[i]);
3434       }
3435    }
3436    fprintf(stderr, "\n%s 0 to numColorsToDump-1:\n",
3437          "The following indices ranges from");
3438    for (i=0; i < numColorsToDump; i++) {
3439       int j=0;
3440 
3441       if (mainVisual->class == TrueColor) {
3442          fprintf(stderr, "%s[%3d]=0x%06lx, %s[%3d]=",
3443                "pixelValue", i, (long)pixelValue[i], "colorChar", i);
3444       } else {
3445          fprintf(stderr, "%s[%3d]=%3d, %s[%3d]=",
3446                "pixelValue", i, pixelValue[i], "colorChar", i);
3447       }
3448       for (j = 0; j < charsPerPixel; j++) {
3449          fprintf(stderr, "%c", colorChar[i*charsPerPixel+j]);
3450       }
3451       fprintf(stderr, ", %s[%3d]=%s\n", "colorStr", i, colorStr[i]);
3452    }
3453 }
3454 #endif /* _TGIF_DBG */
3455 
3456 #ifdef _TGIF_DBG /* debug, do not translate */
3457 static
DebugXPmColorsAndExportImage(image,w,h,left,top,right,bottom)3458 void DebugXPmColorsAndExportImage(image, w, h, left, top, right, bottom)
3459    XImage *image;
3460    int w, h, left, top, right, bottom;
3461 {
3462    int i=0;
3463 
3464    DebugXPmColors();
3465 
3466    fprintf(stderr, "\nHere is the image:\n");
3467    fprintf(stderr, "    (%s\n    %s\n    %s)\n",
3468          "recall that if colorIndexToDumpIndex[color_index] = index",
3469          "then pixelValue[index] == pixel, where pixel is a value seen below",
3470          "and color_index indexes colorPixels and colorMenuItems");
3471    for (i=top; i < h-bottom; i++) {
3472       int j=0;
3473 
3474       for (j=left; j < w-right; j++) {
3475          int data=XGetPixel(image,j-left,i-top);
3476 
3477          if (j+1 == w-right) {
3478             if (mainVisual->class == TrueColor) {
3479                fprintf(stderr, "%06lx\n", (long)data);
3480             } else {
3481                fprintf(stderr, "%3d\n", data);
3482             }
3483          } else {
3484             if (mainVisual->class == TrueColor) {
3485                fprintf(stderr, "%06lx ", (long)data);
3486             } else {
3487                fprintf(stderr, "%3d ", data);
3488             }
3489          }
3490       }
3491    }
3492 }
3493 #endif /* _TGIF_DBG */
3494 #endif /* NOT_DEFINED */
3495 
3496 static
AdjustForRealBaseName(fname,gzipped,no_name)3497 void AdjustForRealBaseName(fname, gzipped, no_name)
3498    char *fname;
3499    int gzipped, no_name;
3500 {
3501    char *psz=NULL, *psz1=NULL;
3502 
3503    if (no_name) return;
3504    if ((psz1=UtilStrRChr(fname, '.')) == NULL) return;
3505    *psz1 = '\0';
3506    if (!gzipped) return;
3507    if ((psz=UtilStrRChr(fname, '.')) == NULL) {
3508       *psz1 = '.';
3509       return;
3510    }
3511    *psz = '\0';
3512 }
3513 
GetRealBaseName(fname)3514 void GetRealBaseName(fname)
3515    char *fname;
3516 {
3517    int gzipped=FALSE, no_name=FALSE;
3518 
3519    if (FileNameHasExtension(fname, OBJ_FILE_TYPE, &gzipped, &no_name)) {
3520       AdjustForRealBaseName(fname, gzipped, no_name);
3521       return;
3522    }
3523    gzipped = no_name = FALSE;
3524    if (FileNameHasExtension(fname, SYM_FILE_TYPE, &gzipped, &no_name)) {
3525       AdjustForRealBaseName(fname, gzipped, no_name);
3526       return;
3527    }
3528    gzipped = no_name = FALSE;
3529    if (FileNameHasExtension(fname, PIN_FILE_TYPE, &gzipped, &no_name)) {
3530       AdjustForRealBaseName(fname, gzipped, no_name);
3531       return;
3532    }
3533 }
3534 
3535 static
RotateImageForLandscape(src_image,p_w,p_h,p_left,p_top,p_right,p_bottom)3536 XImage *RotateImageForLandscape(src_image, p_w, p_h, p_left, p_top, p_right,
3537       p_bottom)
3538    XImage *src_image;
3539    int *p_w, *p_h, *p_left, *p_top, *p_right, *p_bottom;
3540 {
3541    int x=0, y=0;
3542    int new_w=(*p_h), new_h=(*p_w), new_left=(*p_top), new_top=(*p_right);
3543    int new_right=(*p_bottom), new_bottom=(*p_left);
3544    Pixmap dest_pixmap=None;
3545    XImage *dest_image=NULL;
3546 
3547    dest_pixmap = XCreatePixmap(mainDisplay, mainWindow, new_w, new_h,
3548          mainDepth);
3549    dest_image = (dest_pixmap==None ? NULL : XGetImage(mainDisplay, dest_pixmap,
3550          0, 0, new_w, new_h, AllPlanes, ZPixmap));
3551    if (dest_pixmap == None || dest_image == NULL) {
3552       FailAllocPixmapMessage(new_w, new_h);
3553       if (dest_pixmap != None) XFreePixmap(mainDisplay, dest_pixmap);
3554       if (dest_image != NULL) XDestroyImage(dest_image);
3555       return NULL;
3556    }
3557    for (y=0; y < new_w; y++) {
3558       for (x=0; x < new_h; x++) {
3559          XPutPixel(dest_image, y, (new_h-1)-x, XGetPixel(src_image, x, y));
3560       }
3561    }
3562    *p_w = new_w;
3563    *p_h = new_h;
3564    *p_left = new_left;
3565    *p_top = new_top;
3566    *p_right = new_right;
3567    *p_bottom = new_bottom;
3568 
3569    XFreePixmap(mainDisplay, dest_pixmap);
3570 
3571    return dest_image;
3572 }
3573 
3574 static int dumpPpmPreferred=FALSE;
3575 
3576 static
DumpXpmHeader(fp,w,h,name,left,top,right,bottom)3577 void DumpXpmHeader(fp, w, h, name, left, top, right, bottom)
3578    FILE *fp;
3579    int w, h, left, top, right, bottom;
3580    char *name;
3581 {
3582    if (whereToPrint == PPM_FILE ||
3583          (whereToPrint != XBM_FILE && dumpPpmPreferred)) {
3584       fprintf(fp, "P6\n%1d %1d\n255\n", w-left-right, h-top-bottom);
3585    } else if (xpmOutputVersion == 1) {
3586       DumpCommentInBitmapExport(fp);
3587       /* do not translate -- program constants */
3588       fprintf(fp, "#define %s_format 1\n", name);
3589       fprintf(fp, "#define %s_width %1d\n", name, w-left-right);
3590       fprintf(fp, "#define %s_height %1d\n", name, h-top-bottom);
3591       fprintf(fp, "#define %s_ncolors %1d\n", name, numColorsToDump);
3592       fprintf(fp, "#define %s_chars_per_pixel %1d\n", name, charsPerPixel);
3593       if (xpmInXGrabSCFormat) {
3594          fprintf(fp, "static char * %s_colors[] = {\n", name);
3595       } else {
3596          fprintf(fp, "static char *%s_colors[] = {\n", name);
3597       }
3598       DumpXPmColors(fp);
3599       if (xpmInXGrabSCFormat) {
3600          fprintf(fp, "static char * %s_pixels[] = {\n", name);
3601       } else {
3602          fprintf(fp, "static char *%s_pixels[] = {\n", name);
3603       }
3604    } else {
3605       /* xpmOutputVersion is 3 */
3606       fprintf(fp, "/* XPM */\n");
3607       DumpCommentInBitmapExport(fp);
3608       fprintf(fp, "static char * %s[] = {\n", name);
3609       fprintf(fp, "\"%1d %1d %1d %1d\",\n",
3610             w-left-right, h-top-bottom, numColorsToDump, charsPerPixel);
3611       DumpXPmColors(fp);
3612    }
3613 }
3614 
3615 static
DumpXbmHeader(fp,w,h,name,left,top,right,bottom)3616 void DumpXbmHeader(fp, w, h, name, left, top, right, bottom)
3617    FILE *fp;
3618    int w, h, left, top, right, bottom;
3619    char *name;
3620 {
3621    if (whereToPrint == PPM_FILE) {
3622       fprintf(fp, "P4\n%1d %1d\n", w-left-right, h-top-bottom);
3623    } else {
3624       DumpCommentInBitmapExport(fp);
3625       /* do not translate -- program constants */
3626       fprintf(fp, "#define %s_width %1d\n", name, w-left-right);
3627       fprintf(fp, "#define %s_height %1d\n", name, h-top-bottom);
3628       fprintf(fp, "#define %s_x_hot 0\n", name);
3629       fprintf(fp, "#define %s_y_hot 0\n", name);
3630       fprintf(fp, "static %schar %s_bits[] = {\n   ",
3631             (unsignedInXBmExport ? "unsigned " : ""), name);
3632    }
3633 }
3634 
SetAColorByteInfo(pcb,pXColor)3635 void SetAColorByteInfo(pcb, pXColor)
3636    ColorBytes *pcb;
3637    XColor *pXColor;
3638 {
3639    double red=0, green=0, blue=0;
3640    int r=0, g=0, b=0;
3641 
3642    red = ((double)255)*((double)(pXColor->red))/((double)maxRGB);
3643    green = ((double)255)*((double)(pXColor->green))/((double)maxRGB);
3644    blue = ((double)255)*((double)(pXColor->blue))/((double)maxRGB);
3645 
3646    r = round(red);
3647    g = round(green);
3648    b = round(blue);
3649 
3650    if (r > 255) r = 255;
3651    if (g > 255) g = 255;
3652    if (b > 255) b = 255;
3653 
3654    if (r < 0) r = 0;
3655    if (g < 0) g = 0;
3656    if (b < 0) b = 0;
3657 
3658    pcb->r = (unsigned char)(r & 0x0ff);
3659    pcb->g = (unsigned char)(g & 0x0ff);
3660    pcb->b = (unsigned char)(b & 0x0ff);
3661 
3662    pcb->valid = TRUE;
3663 }
3664 
3665 static
SetColorBytes(pcb,index,table_size)3666 void SetColorBytes(pcb, index, table_size)
3667    ColorBytes *pcb;
3668    int index, table_size;
3669 {
3670 #ifdef _TGIF_DBG /* debug, do not translate */
3671    TgAssert(index >= 0 && index < table_size,
3672          "index out of range in SetColorBytes()", NULL);
3673 #endif /* _TGIF_DBG */
3674    if (pcb[index].valid) return;
3675 
3676    SetAColorByteInfo(&pcb[index], &tgifColors[index]);
3677 }
3678 
3679 static
DumpPpmBody(fp,image,bitmap_image,w,h,left,top,right,bottom,nInImageProc,bg_pixel)3680 int DumpPpmBody(fp, image, bitmap_image, w, h, left, top, right,
3681       bottom, nInImageProc, bg_pixel)
3682    FILE *fp;
3683    XImage *image, *bitmap_image;
3684    int w, h, left, top, right, bottom, nInImageProc, bg_pixel;
3685 {
3686    XColor *saved_tgif_colors=tgifColors;
3687    ColorBytes *pcb=(ColorBytes*)malloc((maxColors+3)*sizeof(ColorBytes));
3688    ColorBytes my_bg_cb;
3689    int i=0, target_percent=5;
3690 
3691    if (pcb == NULL) FailAllocMessage();
3692    memset(pcb, 0, (maxColors+3)*sizeof(ColorBytes));
3693    memset(&my_bg_cb, 0, sizeof(ColorBytes));
3694    if (printUsingRequestedColor) tgifColors = tgifRequestedColors;
3695 
3696    SetAColorByteInfo(&my_bg_cb, &myBgColor);
3697 
3698    for (i=top; i < h-bottom; i++) {
3699       int j=0, percent=((i-top)*10000/(h-top-bottom))/100;
3700 
3701       if (percent >= target_percent) {
3702          sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
3703                percent);
3704          SetStringStatus(gszMsgBox);
3705          XSync(mainDisplay, False);
3706          while (target_percent <= percent) target_percent += 5;
3707       }
3708       for (j=left; j < w-right; j++) {
3709          int transparent=FALSE, data=0;
3710 
3711          if (nInImageProc && bitmap_image != NULL) {
3712             if (XGetPixel(bitmap_image,j-left,i-top) != 0) {
3713                data = XGetPixel(image,j-left,i-top);
3714             } else {
3715                transparent = TRUE;
3716             }
3717          } else {
3718             data = XGetPixel(image,j-left,i-top);
3719          }
3720          if (!nInImageProc && data == bg_pixel) {
3721             if (fprintf(fp, "%c%c%c",
3722                   my_bg_cb.r, my_bg_cb.g, my_bg_cb.b) == EOF) {
3723                writeFileFailed = TRUE;
3724             }
3725          } else {
3726             int index=INVALID, color_index=BAD;
3727 
3728             if (transparent) {
3729                index = transparentIndex;
3730             } else {
3731                index = XPmLookUp(data, INVALID, NULL, &color_index);
3732             }
3733             if (index == INVALID || color_index == BAD ||
3734                   color_index == INVALID) {
3735                sprintf(gszMsgBox,
3736                      TgLoadString(transparent ?
3737                      STID_UNRECOG_GIVEN_TRPIX_VAL_PRINT :
3738                      STID_UNRECOG_GIVEN_PIXEL_VAL_PRINT),
3739                      j-left, i-top, data, (long)data);
3740                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3741 
3742                if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
3743                free(pcb);
3744                return FALSE;
3745             }
3746             SetColorBytes(pcb, color_index, (maxColors+3));
3747             if (fprintf(fp, "%c%c%c", pcb[color_index].r, pcb[color_index].g,
3748                   pcb[color_index].b) == EOF) {
3749                writeFileFailed = TRUE;
3750             }
3751          }
3752       }
3753    }
3754    if (printUsingRequestedColor) tgifColors = saved_tgif_colors;
3755    free(pcb);
3756 
3757    return TRUE;
3758 }
3759 
3760 static
DumpXpmBody(fp,image,bitmap_image,w,h,left,top,right,bottom,nInImageProc,bg_pixel)3761 int DumpXpmBody(fp, image, bitmap_image, w, h, left, top, right,
3762       bottom, nInImageProc, bg_pixel)
3763    FILE *fp;
3764    XImage *image, *bitmap_image;
3765    int w, h, left, top, right, bottom, nInImageProc, bg_pixel;
3766 {
3767    int i=0, target_percent=5;
3768 
3769    if (whereToPrint == PPM_FILE ||
3770          (whereToPrint != XBM_FILE && dumpPpmPreferred)) {
3771       return DumpPpmBody(fp, image, bitmap_image, w, h, left, top, right,
3772             bottom, nInImageProc, bg_pixel);
3773    }
3774    for (i=top; i < h-bottom; i++) {
3775       int j=0, percent=((i-top)*10000/(h-top-bottom))/100;
3776 
3777       if (percent >= target_percent) {
3778          sprintf(gszMsgBox, TgLoadCachedString(CSTID_PROGRESS_PERCENT),
3779                percent);
3780          SetStringStatus(gszMsgBox);
3781          XSync(mainDisplay, False);
3782          while (target_percent <= percent) target_percent += 5;
3783       }
3784       if (fprintf(fp, "\"") == EOF) writeFileFailed = TRUE;
3785       for (j=left; j < w-right; j++) {
3786          int transparent=FALSE, data=0;
3787 
3788          if (nInImageProc && bitmap_image != NULL) {
3789             if (XGetPixel(bitmap_image,j-left,i-top) != 0) {
3790                data = XGetPixel(image,j-left,i-top);
3791             } else {
3792                transparent = TRUE;
3793             }
3794          } else {
3795             data = XGetPixel(image,j-left,i-top);
3796          }
3797          if (!nInImageProc && data == bg_pixel) {
3798             switch (charsPerPixel) {
3799             case 1:
3800                if (fprintf(fp, "`") == EOF) writeFileFailed = TRUE;
3801                break;
3802             case 2:
3803                if (fprintf(fp, "``") == EOF) writeFileFailed = TRUE;
3804                break;
3805             }
3806          } else {
3807             int k=0, index=0;
3808 
3809             if (transparent) {
3810                index = transparentIndex;
3811             } else {
3812                index = XPmLookUp(data, INVALID, NULL, NULL);
3813             }
3814             if (index == INVALID) {
3815                sprintf(gszMsgBox,
3816                      TgLoadString(transparent ?
3817                      STID_UNRECOG_GIVEN_TRPIX_VAL_PRINT :
3818                      STID_UNRECOG_GIVEN_PIXEL_VAL_PRINT),
3819                      j-left, i-top, data, (long)data);
3820                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3821 
3822                return FALSE;
3823             }
3824             for (k=0; k < charsPerPixel; k++) {
3825                if (fprintf(fp, "%c", colorChar[index*charsPerPixel+k]) == EOF) {
3826                   writeFileFailed = TRUE;
3827                }
3828             }
3829          }
3830       }
3831       if (i == h-bottom-1) {
3832          if (xpmInXGrabSCFormat) {
3833             if (fprintf(fp, "\",\n} ;\n") == EOF) {
3834                writeFileFailed = TRUE;
3835             }
3836          } else {
3837             if (fprintf(fp, "\"\n};\n") == EOF) {
3838                writeFileFailed = TRUE;
3839             }
3840          }
3841       } else if (fprintf(fp, "\",\n") == EOF) {
3842          writeFileFailed = TRUE;
3843       }
3844    }
3845    return TRUE;
3846 }
3847 
3848 #define FS_SCALE 0x400
3849 #define HALF_FS_SCALE 0x200
3850 
3851 static
DumpXbmHalfToneBody(fp,image,w,h,left,top,right,bottom,bg_pixel)3852 void DumpXbmHalfToneBody(fp, image, w, h, left, top, right, bottom, bg_pixel)
3853    FILE *fp;
3854    XImage *image;
3855    int w, h, left, top, right, bottom, bg_pixel;
3856 {
3857    int i=0, j=0, k=0, bit_count=0, data=0, pixel=0, byte_count=0;
3858    TrueColorInfo tci;
3859    ProgressInfo pi;
3860 
3861    /*--------------------------------------------------*/
3862    /* the halftoning code is adapted from 'pgmopbm.c', */
3863    /*       which is part of the pbmplus package.      */
3864    /*                                                  */
3865    /*       Copyright (C) 1989 by Jef Poskanzer        */
3866    /*--------------------------------------------------*/
3867    long *thiserr, *nexterr, *tmperr, threshval, sum;
3868    int fs_forward=TRUE, col, limitcol, found_index, *bits;
3869    float gray;
3870 
3871    sprintf(gszMsgBox,
3872          TgLoadCachedString(CSTID_FS_HALFTONE_BMP_THRESH_DOTS),
3873          bitmapThresholdStr);
3874    Msg(gszMsgBox);
3875 
3876    srand(0);
3877    thiserr = (long*)malloc((w-left-right+2)*sizeof(long));
3878    nexterr = (long*)malloc((w-left-right+2)*sizeof(long));
3879    bits = (int*)malloc((w-left-right+2)*sizeof(int));
3880    if (thiserr==NULL || nexterr==NULL || bits==NULL) FailAllocMessage();
3881    for (j = 0; j < w-left-right+2; j++) {
3882       thiserr[j] = (rand() % FS_SCALE - HALF_FS_SCALE) >> 2;
3883    }
3884    threshval = (long)(bitmapThreshold * (float)FS_SCALE);
3885    if (fullTrueColorMode) {
3886       if (!InitTrueColorInfo(image, &tci, w)) {
3887          return;
3888       }
3889    }
3890    byte_count = 0;
3891    BeginProgress(&pi, h-top-bottom);
3892    for (i=top; i < h-bottom; i++) {
3893       UpdateProgress(&pi, i-top);
3894 
3895       for (col = 0; col < w-left-right+2; col++) {
3896          nexterr[col] = bits[col] = 0;
3897       }
3898       bit_count = 0;
3899       col = (fs_forward) ? 0 : w-left-right-1;
3900       limitcol = (fs_forward) ? w-left-right : -1;
3901       do {
3902          found_index = INVALID;
3903          pixel = XGetPixel(image, col, i);
3904 
3905          if (fullTrueColorMode) {
3906             uint32_t pix=(uint32_t)(unsigned int)pixel;
3907             unsigned int r=0, g=0, b=0;
3908             double dr=(double)0, dg=(double)0, db=(double)0;
3909 
3910             r = (pix & tci.r_mask) >> tci.r_shift;
3911             g = (pix & tci.g_mask) >> tci.g_shift;
3912             b = (pix & tci.b_mask) >> tci.b_shift;
3913             dr = ((double)r) / tci.dr_maxval;
3914             dg = ((double)g) / tci.dg_maxval;
3915             db = ((double)b) / tci.db_maxval;
3916             gray = (float)(0.299*dr + 0.587*dg + 0.114*db);
3917          } else {
3918             for (k = 0; k < maxColors; k++) {
3919                if (colorPixels[k] == pixel) {
3920                   found_index = k;
3921                   break;
3922                }
3923             }
3924             if (found_index == INVALID) {
3925                if (pixel == bg_pixel) {
3926                   gray = (float)1.0;
3927                } else {
3928                   sprintf(gszMsgBox,
3929                         TgLoadString(STID_UNRECOG_GIVEN_PIXEL_VAL_1_USE),
3930                         pixel, (long)pixel);
3931                   Msg(gszMsgBox);
3932                   gray = (float)0.0;
3933                }
3934             } else {
3935                gray = 0.299*((float)tgifColors[found_index].red/maxRGB) +
3936                      0.587*((float)tgifColors[found_index].green/maxRGB) +
3937                      0.114*((float)tgifColors[found_index].blue/maxRGB);
3938             }
3939          }
3940          sum = ((long)(gray * FS_SCALE)) + thiserr[col+1];
3941          if (sum >= threshval) {
3942             sum = sum-threshval-HALF_FS_SCALE;
3943          } else {
3944             bits[col] = 1; /* black bit */
3945          }
3946          if (fs_forward) {
3947             thiserr[col+2] += (sum*7)>>4;
3948             nexterr[col  ] += (sum*3)>>4;
3949             nexterr[col+1] += (sum*5)>>4;
3950             nexterr[col+2] += (sum  )>>4;
3951             col++;
3952          } else {
3953             thiserr[col  ] += (sum*7)>>4;
3954             nexterr[col+2] += (sum*3)>>4;
3955             nexterr[col+1] += (sum*5)>>4;
3956             nexterr[col  ] += (sum  )>>4;
3957             col--;
3958          }
3959       } while (col != limitcol);
3960 
3961       tmperr = thiserr;
3962       thiserr = nexterr;
3963       nexterr = tmperr;
3964       fs_forward = !fs_forward;
3965 
3966       bit_count = 0;
3967       data = 0;
3968 
3969       for (j = left; j < w-right; j++) {
3970          if (bits[j]) {
3971             if (whereToPrint == XBM_FILE ||
3972                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
3973                data |= (1<<bit_count);
3974             } else {
3975                data |= (1<<(7-bit_count));
3976             }
3977          }
3978          if (++bit_count == 8) {
3979             if (byte_count++ == 12) {
3980                byte_count = 1;
3981                if (whereToPrint == XBM_FILE ||
3982                      (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
3983                   if (fprintf(fp, "\n   ") == EOF) writeFileFailed = TRUE;
3984                }
3985             }
3986             if (whereToPrint == XBM_FILE ||
3987                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
3988                if (fprintf(fp, "0x%c", hexValue[(data>>4) & 0xf]) == EOF) {
3989                   writeFileFailed = TRUE;
3990                }
3991                if (i == h-bottom-1 && j == w-right-1) {
3992                   if (fprintf(fp, "%c};\n", hexValue[data & 0xf]) == EOF) {
3993                      writeFileFailed = TRUE;
3994                   }
3995                } else {
3996                   if (fprintf(fp, "%c, ", hexValue[data & 0xf]) == EOF) {
3997                      writeFileFailed = TRUE;
3998                   }
3999                }
4000             } else {
4001                if (fprintf(fp, "%c", (unsigned char)(data & 0x0ff)) == EOF) {
4002                   writeFileFailed = TRUE;
4003                }
4004             }
4005             bit_count = 0;
4006             data = 0;
4007          }
4008       }
4009       if (((w-left-right) % 8) != 0) {
4010          if (byte_count++ == 12) {
4011             byte_count = 1;
4012             if (whereToPrint == XBM_FILE ||
4013                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4014                if (fprintf(fp, "\n   ") == EOF) writeFileFailed = TRUE;
4015             }
4016          }
4017          if (whereToPrint == XBM_FILE ||
4018                (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4019             for (j=((w-left-right)%8); j < 8; j++) data |= (1<<j);
4020 
4021             if (fprintf(fp, "0x%c", hexValue[(data>>4) & 0xf]) == EOF) {
4022                writeFileFailed = TRUE;
4023             }
4024             if (i == h-bottom-1) {
4025                if (fprintf(fp, "%c};\n", hexValue[data & 0xf]) == EOF) {
4026                   writeFileFailed = TRUE;
4027                }
4028             } else {
4029                if (fprintf(fp, "%c, ", hexValue[data & 0xf]) == EOF) {
4030                   writeFileFailed = TRUE;
4031                }
4032             }
4033          } else {
4034             if (fprintf(fp, "%c", (unsigned char)(data & 0x0ff)) == EOF) {
4035                writeFileFailed = TRUE;
4036             }
4037          }
4038       }
4039    }
4040 }
4041 
4042 static
DumpXbmNoneHalfToneBody(fp,image,w,h,left,top,right,bottom,bg_pixel)4043 void DumpXbmNoneHalfToneBody(fp, image, w, h, left, top, right, bottom,
4044       bg_pixel)
4045    FILE *fp;
4046    XImage *image;
4047    int w, h, left, top, right, bottom, bg_pixel;
4048 {
4049    int i=0, j=0, k=0, bit_count=0, data=0, pixel=0, byte_count=0;
4050    TrueColorInfo tci;
4051    ProgressInfo pi;
4052 
4053    if (thresholdBitmap) {
4054       sprintf(gszMsgBox,
4055             TgLoadCachedString(CSTID_THRESHOLD_BMP_THRESH_DOTS),
4056             bitmapThresholdStr);
4057       Msg(gszMsgBox);
4058    }
4059    if (fullTrueColorMode) {
4060       if (!InitTrueColorInfo(image, &tci, w)) {
4061          return;
4062       }
4063    }
4064    byte_count = 0;
4065    BeginProgress(&pi, h-top-bottom);
4066    for (i=top; i < h-bottom; i++) {
4067       UpdateProgress(&pi, i-top);
4068 
4069       bit_count = 0;
4070       data = 0;
4071 
4072       for (j = left; j < w-right; j++) {
4073          if (thresholdBitmap) {
4074             pixel = XGetPixel(image, j, i);
4075 
4076             if (fullTrueColorMode) {
4077                uint32_t pix=(uint32_t)(unsigned int)pixel;
4078                unsigned int r=0, g=0, b=0;
4079                double dr=(double)0, dg=(double)0, db=(double)0;
4080                double dgray=(double)0;
4081 
4082                r = (pix & tci.r_mask) >> tci.r_shift;
4083                g = (pix & tci.g_mask) >> tci.g_shift;
4084                b = (pix & tci.b_mask) >> tci.b_shift;
4085                dr = ((double)r) / tci.dr_maxval;
4086                dg = ((double)g) / tci.dg_maxval;
4087                db = ((double)b) / tci.db_maxval;
4088                dgray = 0.299*dr + 0.587*dg + 0.114*db;
4089                if (dgray < (double)bitmapThreshold) {
4090                   if (whereToPrint == XBM_FILE ||
4091                         (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4092                      data |= (1<<bit_count);
4093                   } else {
4094                      data |= (1<<(7-bit_count));
4095                   }
4096                }
4097             } else {
4098                int found_index=INVALID;
4099                float gray=(float)0;
4100 
4101                for (k = 0; k < maxColors; k++) {
4102                   if (colorPixels[k] == pixel) {
4103                      found_index = k;
4104                      break;
4105                   }
4106                }
4107                if (found_index == INVALID) {
4108                   if (pixel != bg_pixel) {
4109                      sprintf(gszMsgBox,
4110                            TgLoadString(STID_UNRECOG_GIVEN_PIXEL_VAL_1_USE),
4111                            pixel, (long)pixel);
4112                      Msg(gszMsgBox);
4113                      if (whereToPrint == XBM_FILE ||
4114                            (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4115                         data |= (1<<bit_count);
4116                      } else {
4117                         data |= (1<<(7-bit_count));
4118                      }
4119                      }
4120                } else {
4121                   gray = 0.299*((float)tgifColors[found_index].red/maxRGB) +
4122                         0.587*((float)tgifColors[found_index].green/maxRGB) +
4123                         0.114*((float)tgifColors[found_index].blue/maxRGB);
4124                   if (gray < bitmapThreshold) {
4125                      if (whereToPrint == XBM_FILE ||
4126                            (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4127                         data |= (1<<bit_count);
4128                      } else {
4129                         data |= (1<<(7-bit_count));
4130                      }
4131                   }
4132                }
4133             }
4134          } else if (XGetPixel(image,j,i) != bg_pixel) {
4135             if (whereToPrint == XBM_FILE ||
4136                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4137                data |= (1<<bit_count);
4138             } else {
4139                data |= (1<<(7-bit_count));
4140             }
4141          }
4142          if (++bit_count == 8) {
4143             if (byte_count++ == 12) {
4144                byte_count = 1;
4145                if (whereToPrint == XBM_FILE ||
4146                      (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4147                   if (fprintf(fp, "\n   ") == EOF) writeFileFailed = TRUE;
4148                }
4149             }
4150             if (whereToPrint == XBM_FILE ||
4151                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4152                if (fprintf(fp, "0x%c", hexValue[(data>>4) & 0xf]) == EOF) {
4153                   writeFileFailed = TRUE;
4154                }
4155                if (i == h-bottom-1 && j == w-right-1) {
4156                   if (fprintf(fp, "%c};\n", hexValue[data & 0xf]) == EOF) {
4157                      writeFileFailed = TRUE;
4158                   }
4159                } else {
4160                   if (fprintf(fp, "%c, ", hexValue[data & 0xf]) == EOF) {
4161                      writeFileFailed = TRUE;
4162                   }
4163                }
4164             } else {
4165                if (fprintf(fp, "%c", (unsigned char)(data & 0x0ff)) == EOF) {
4166                   writeFileFailed = TRUE;
4167                }
4168             }
4169             bit_count = 0;
4170             data = 0;
4171          }
4172       }
4173       if (((w-left-right) % 8) != 0) {
4174          if (byte_count++ == 12) {
4175             byte_count = 1;
4176             if (whereToPrint == XBM_FILE ||
4177                   (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4178                if (fprintf(fp, "\n   ") == EOF) writeFileFailed = TRUE;
4179             }
4180          }
4181          if (whereToPrint == XBM_FILE ||
4182                (whereToPrint == EPSI_FILE && generateTiffEPSI)) {
4183             for (j=((w-left-right)%8); j < 8; j++) data |= (1<<j);
4184 
4185             if (fprintf(fp, "0x%c", hexValue[(data>>4) & 0xf]) == EOF) {
4186                writeFileFailed = TRUE;
4187             }
4188             if (i == h-bottom-1) {
4189                if (fprintf(fp, "%c};\n", hexValue[data & 0xf]) == EOF) {
4190                   writeFileFailed = TRUE;
4191                }
4192             } else {
4193                if (fprintf(fp, "%c, ", hexValue[data & 0xf]) == EOF) {
4194                   writeFileFailed = TRUE;
4195                }
4196             }
4197          } else {
4198             if (fprintf(fp, "%c", (unsigned char)(data & 0x0ff)) == EOF) {
4199                writeFileFailed = TRUE;
4200             }
4201          }
4202       }
4203    }
4204 }
4205 
4206 static
DumpXbmBody(fp,image,w,h,left,top,right,bottom,bg_pixel)4207 void DumpXbmBody(fp, image, w, h, left, top, right, bottom, bg_pixel)
4208    FILE *fp;
4209    XImage *image;
4210    int w, h, left, top, right, bottom, bg_pixel;
4211 {
4212    if (halfToneBitmap) {
4213       DumpXbmHalfToneBody(fp, image, w, h, left, top, right, bottom, bg_pixel);
4214    } else {
4215       DumpXbmNoneHalfToneBody(fp, image, w, h, left, top, right, bottom,
4216             bg_pixel);
4217    }
4218 }
4219 
4220 static
GetPixelTrims(w,h,pnLeft,pnTop,pnRight,pnBottom)4221 void GetPixelTrims(w, h, pnLeft, pnTop, pnRight, pnBottom)
4222    int w, h, *pnLeft, *pnTop, *pnRight, *pnBottom;
4223 {
4224    *pnLeft = leftExportPixelTrim;
4225    *pnTop = topExportPixelTrim;
4226    *pnRight = rightExportPixelTrim;
4227    *pnBottom = bottomExportPixelTrim;
4228    if (leftExportPixelTrim+rightExportPixelTrim >= w ||
4229          topExportPixelTrim+bottomExportPixelTrim >= h) {
4230       SetExportPixelTrim(TRUE);
4231       if (leftExportPixelTrim+rightExportPixelTrim >= w ||
4232             topExportPixelTrim+bottomExportPixelTrim >= h) {
4233          sprintf(gszMsgBox, TgLoadString(STID_LARGE_EXP_PXL_TRM_WH_0_USED),
4234                leftExportPixelTrim, topExportPixelTrim, rightExportPixelTrim,
4235                bottomExportPixelTrim, w, h);
4236          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4237          *pnLeft = *pnTop = *pnRight = *pnBottom = 0;
4238       } else {
4239          *pnLeft = leftExportPixelTrim;
4240          *pnTop = topExportPixelTrim;
4241          *pnRight = rightExportPixelTrim;
4242          *pnBottom = bottomExportPixelTrim;
4243       }
4244    }
4245 }
4246 
4247 static
BuildXPmColorsFromImage(image,w,h)4248 void BuildXPmColorsFromImage(image, w, h)
4249    XImage *image;
4250    int w, h;
4251 {
4252    int i=0, saved_max_colors=maxColors;
4253 
4254    FreeCachedStrings();
4255 
4256    maxColors = MAXXPMEXPORTCOLORS;
4257 
4258    pixelValue = (int*)malloc((maxColors+3)*sizeof(int));
4259    if (pixelValue == NULL) FailAllocMessage();
4260    colorIndexToDumpIndex = (int*)malloc((maxColors+3)*sizeof(int));
4261    dumpIndexToColorIndex = (int*)malloc((maxColors+3)*sizeof(int));
4262    if (colorIndexToDumpIndex == NULL || dumpIndexToColorIndex == NULL) {
4263       FailAllocMessage();
4264    }
4265    if (maxColors > 20) {
4266       charsPerPixel = 2;
4267       colorChar = (char*)malloc(((maxColors<<1)+6)*sizeof(char));
4268    } else {
4269       charsPerPixel = 1;
4270       colorChar = (char*)malloc((maxColors+3)*sizeof(char));
4271    }
4272    if (colorChar == NULL) FailAllocMessage();
4273    colorStr = (char**)malloc((maxColors+3)*sizeof(char*));
4274    if (colorStr == NULL) FailAllocMessage();
4275    memset(colorStr, 0, (maxColors+3)*sizeof(char*));
4276 
4277    for (i = 0; i < maxColors+3; i++) {
4278       colorIndexToDumpIndex[i] = dumpIndexToColorIndex[i] = INVALID;
4279    }
4280    pixelValue[0] = GetDrawingBgPixel(INVALID, INVALID);
4281    if (myFileBgColorStr == NULL) {
4282       colorStr[0] = (char*)malloc((strlen(myBgColorStr)+1)*sizeof(char));
4283       if (colorStr[0] == NULL) FailAllocMessage();
4284       strcpy(colorStr[0], myBgColorStr);
4285    } else {
4286       colorStr[0] = (char*)malloc((strlen(myFileBgColorStr)+1)*sizeof(char));
4287       if (colorStr[0] == NULL) FailAllocMessage();
4288       strcpy(colorStr[0], myFileBgColorStr);
4289    }
4290    numColorsToDump = 1;
4291 
4292    if (InitTmpBuckets()) {
4293       SetStringStatus(TgLoadCachedString(CSTID_BLD_COLOR_TBL_FROM_PIXEL_DOTS));
4294       for (i=0; i < h; i++) {
4295          int j=0;
4296 
4297          for (j=0; j < w; j++) {
4298             int pixel=XGetPixel(image,j,i);
4299 
4300             UpdateColorsLookupTableForPixel(pixel, TRUE);
4301          }
4302       }
4303       CleanUpTmpBuckets();
4304    }
4305    colorChar[0] = '`';
4306    if (charsPerPixel > 1) colorChar[1] = '`';
4307    if (numColorsToDump >= 256) {
4308       for (i=1; i < numColorsToDump; i++) {
4309          if (charsPerPixel == 1) {
4310             colorChar[i] = (char)(((int)('a'))+i-1);
4311          } else {
4312             int left=(int)(i/80), right=(i%80);
4313 
4314             if (left >= 31) {
4315                colorChar[i*2] = (char)(((int)('/'))+left-31);
4316             } else {
4317                colorChar[i*2] = (char)(((int)('`'))+left);
4318             }
4319             if (right >= 31) {
4320                colorChar[i*2+1] = (char)(((int)('/'))+right-31);
4321             } else {
4322                colorChar[i*2+1] = (char)(((int)('`'))+right);
4323             }
4324          }
4325       }
4326    } else {
4327       for (i=1; i < numColorsToDump; i++) {
4328          if (charsPerPixel == 1) {
4329             colorChar[i] = (char)(((int)('a'))+i-1);
4330          } else {
4331             colorChar[i*2] = (char)(((int)('a'))+(int)(i/10));
4332             colorChar[i*2+1] = (char)(((int)('0'))+(i%10));
4333          }
4334       }
4335    }
4336    maxColors = saved_max_colors;
4337 }
4338 
4339 static
DumpXImageToXpmFile(image,w,h,fname)4340 int DumpXImageToXpmFile(image, w, h, fname)
4341    XImage *image;
4342    int w, h;
4343    char *fname;
4344 {
4345    FILE *fp=fopen(fname, "w");
4346    int bg_pixel=GetDrawingBgPixel(INVALID, INVALID);
4347    int saved_xpm_output_version=xpmOutputVersion;
4348 
4349    BuildXPmColorsFromImage(image, w, h);
4350 
4351    if (numColorsToDump >= MAXXPMEXPORTCOLORS) {
4352       sprintf(gszMsgBox, TgLoadString(STID_TOO_MANY_COLORS_LIMIT_IS),
4353             numColorsToDump, MAXXPMEXPORTCOLORS);
4354       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4355       return FALSE;
4356    }
4357    if (fp == NULL) {
4358       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
4359             fname);
4360       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4361       return FALSE;
4362    }
4363    if (useXPmVersion1ForImageMap) {
4364       xpmOutputVersion = 1;
4365    }
4366    writeFileFailed = FALSE;
4367 
4368    DumpXpmHeader(fp, w, h, TOOL_NAME, 0, 0, 0, 0);
4369 
4370 #ifdef NOT_DEFINED
4371 #ifdef _TGIF_DBG
4372    DebugXPmColorsAndExportImage(image, w, h, 0, 0, 0, 0);
4373 #endif /* _TGIF_DBG */
4374 #endif /* NOT_DEFINED */
4375    if (!BuildXPmBuckets(numColorsToDump, pixelValue, dumpIndexToColorIndex,
4376          INVALID, NULL, NULL)) {
4377       fclose(fp);
4378       xpmOutputVersion = saved_xpm_output_version;
4379       return FALSE;
4380    }
4381    if (!DumpXpmBody(fp, image, NULL, w, h, 0, 0, 0, 0, FALSE, bg_pixel)) {
4382       if (!(PRTGIF && cmdLineStdOut &&
4383             !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4384             !preDumpSetup)) {
4385          fclose(fp);
4386       }
4387       xpmOutputVersion = saved_xpm_output_version;
4388       return FALSE;
4389    }
4390    fclose(fp);
4391    xpmOutputVersion = saved_xpm_output_version;
4392    if (writeFileFailed) {
4393       return FailAllocPixmapMessage(w, h);
4394    }
4395    return TRUE;
4396 }
4397 
DumpXImageToPpmFile(image,w,h,fname,deflate)4398 int DumpXImageToPpmFile(image, w, h, fname, deflate)
4399    XImage *image;
4400    int w, h, deflate;
4401    char *fname;
4402 {
4403    int row=0, col=0;
4404    TrueColorInfo tci;
4405    double dmaxval=(double)255;
4406    unsigned int bytes_per_pixel=image->bits_per_pixel/8;
4407    unsigned char *image_ptr=(unsigned char *)(image->data);
4408    char deflated_fname[MAXPATHLENGTH];
4409    FILE *fp=NULL;
4410    ProgressInfo pi;
4411 
4412    *deflated_fname = '\0';
4413    if (!InitTrueColorInfo(image, &tci, w)) {
4414       return FALSE;
4415    }
4416    fp = fopen(fname, "w");
4417    if (fp == NULL) {
4418       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
4419             fname);
4420       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4421       return FALSE;
4422    }
4423    writeFileFailed = FALSE;
4424    if (fprintf(fp, "P6\n%1d %1d\n255\n", w, h) == EOF) writeFileFailed = TRUE;
4425 
4426    BeginProgress(&pi, h);
4427    for (row=0; row < h; row++) {
4428       UpdateProgress(&pi, row);
4429       for (col=0; col < w; col++, image_ptr+=bytes_per_pixel) {
4430          uint32_t pixel=0;
4431          unsigned int r=0, g=0, b=0;
4432          double dr=(double)0, dg=(double)0, db=(double)0;
4433          unsigned char buf[3];
4434 
4435          memcpy(&pixel, image_ptr, bytes_per_pixel);
4436          r = (pixel & tci.r_mask) >> tci.r_shift;
4437          g = (pixel & tci.g_mask) >> tci.g_shift;
4438          b = (pixel & tci.b_mask) >> tci.b_shift;
4439          dr = ((double)r) * dmaxval / tci.dr_maxval;
4440          dg = ((double)g) * dmaxval / tci.dg_maxval;
4441          db = ((double)b) * dmaxval / tci.db_maxval;
4442          r = round(dr);
4443          g = round(dg);
4444          b = round(db);
4445          buf[0] = (unsigned char)(r&0xff);
4446          buf[1] = (unsigned char)(g&0xff);
4447          buf[2] = (unsigned char)(b&0xff);
4448 
4449          if ((int)fwrite(buf, sizeof(char), 3, fp) <= 0) writeFileFailed = TRUE;
4450       }
4451    }
4452    EndProgress(&pi);
4453    fclose(fp);
4454    if (writeFileFailed) {
4455       return FailToWriteFileMessage(fname);
4456    }
4457    if (deflate) {
4458       snprintf(deflated_fname, sizeof(deflated_fname), "%s.ppm.z", fname);
4459       if (!DeflateFile(fname, deflated_fname)) {
4460          unlink(fname);
4461          return FALSE;
4462       }
4463       unlink(fname);
4464    }
4465    return TRUE;
4466 }
4467 
4468 static
DumpXImageToPpm6(fp,image,bitmap_image,w,h,left,top,right,bottom)4469 int DumpXImageToPpm6(fp, image, bitmap_image, w, h, left, top, right, bottom)
4470    FILE *fp;
4471    XImage *image, *bitmap_image;
4472    int w, h, left, top, right, bottom;
4473 {
4474    int i=0;
4475    TrueColorInfo tci;
4476    double dmaxval=(double)255;
4477    unsigned int bytes_per_pixel=image->bits_per_pixel/8;
4478    unsigned char *image_ptr=(unsigned char *)(image->data);
4479    ProgressInfo pi;
4480 
4481    if (!InitTrueColorInfo(image, &tci, w)) {
4482       return FALSE;
4483    }
4484    if (fprintf(fp, "P6\n%1d %1d\n255\n", w, h) == EOF) writeFileFailed = TRUE;
4485 
4486    image_ptr += (bytes_per_pixel*top*w);
4487    BeginProgress(&pi, h-top-bottom);
4488    for (i=top; i < h-bottom; i++, image_ptr+=bytes_per_pixel*right) {
4489       int j=0;
4490 
4491       UpdateProgress(&pi, i-top);
4492       for (j=left, image_ptr+=(bytes_per_pixel*left); j < w-right; j++,
4493             image_ptr+=bytes_per_pixel) {
4494          uint32_t pixel=0;
4495          unsigned int r=0, g=0, b=0;
4496          double dr=(double)0, dg=(double)0, db=(double)0;
4497          unsigned char buf[3];
4498 
4499          memcpy(&pixel, image_ptr, bytes_per_pixel);
4500          r = (pixel & tci.r_mask) >> tci.r_shift;
4501          g = (pixel & tci.g_mask) >> tci.g_shift;
4502          b = (pixel & tci.b_mask) >> tci.b_shift;
4503          dr = ((double)r) * dmaxval / tci.dr_maxval;
4504          dg = ((double)g) * dmaxval / tci.dg_maxval;
4505          db = ((double)b) * dmaxval / tci.db_maxval;
4506          r = round(dr);
4507          g = round(dg);
4508          b = round(db);
4509          buf[0] = (unsigned char)(r&0xff);
4510          buf[1] = (unsigned char)(g&0xff);
4511          buf[2] = (unsigned char)(b&0xff);
4512 
4513          if ((int)fwrite(buf, sizeof(char), 3, fp) <= 0) writeFileFailed = TRUE;
4514       }
4515    }
4516    EndProgress(&pi);
4517 
4518    return TRUE;
4519 }
4520 
DumpXBitmapFile(nInImageProc,nDumpPpmPreferred,nPageNumInFileName)4521 void DumpXBitmapFile(nInImageProc, nDumpPpmPreferred, nPageNumInFileName)
4522    int nInImageProc, nDumpPpmPreferred, nPageNumInFileName;
4523 {  /* called when printing in the xbm or xpm format */
4524    int ltx=0, lty=0, w=0, h=0, short_name=FALSE;
4525    int left=0, top=0, right=0, bottom=0;
4526    int bg_pixel=GetDrawingBgPixel(INVALID, INVALID);
4527    char xbm_file_name[MAXPATHLENGTH<<1], *rest=NULL, name[MAXPATHLENGTH+1];
4528    FILE *fp=NULL;
4529    Pixmap pixmap=None;
4530    XImage *image=NULL, *bitmap_image=NULL;
4531 
4532    dumpPpmPreferred = nDumpPpmPreferred;
4533 
4534    if (nInImageProc) {
4535       *gszImageProcXPmFile = '\0';
4536       if (MkTempFile(xbm_file_name, sizeof(xbm_file_name), tmpDir,
4537             TOOL_NAME) == NULL) {
4538          return;
4539       }
4540       strcpy(name, "unnamed");
4541       if ((short_name=IsPrefix(bootDir, xbm_file_name, &rest))) ++rest;
4542    } else {
4543       strcpy(name, curFileName);
4544       GetRealBaseName(name);
4545       sprintf(xbm_file_name, "%s%c%s", curDir, DIR_SEP, name);
4546       if (PRTGIF) {
4547          char *tmp_name=(char*)name;
4548 
4549          if (whereToPrint == PPM_FILE || dumpPpmPreferred) {
4550             SetOutputFileName(xbm_file_name,
4551                   colorDump?"ppm":"pbm", NULL, &tmp_name);
4552          } else {
4553             SetOutputFileName(xbm_file_name,
4554                   colorDump?XPM_FILE_EXT:XBM_FILE_EXT, NULL, &tmp_name);
4555          }
4556       } else {
4557          if (whereToPrint == PPM_FILE || dumpPpmPreferred) {
4558             SetOutputFileName(xbm_file_name,
4559                   colorDump?"ppm":"pbm", &short_name, &rest);
4560          } else {
4561             SetOutputFileName(xbm_file_name,
4562                   colorDump?XPM_FILE_EXT:XBM_FILE_EXT, &short_name, &rest);
4563          }
4564       }
4565    }
4566    if (PRTGIF && cmdLineStdOut &&
4567          !(whereToPrint == EPSI_FILE && generateTiffEPSI) && !preDumpSetup) {
4568       fp = stdout;
4569    } else if ((fp=fopen(xbm_file_name, "w")) == NULL) {
4570       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FOR_WRITE_PRINT),
4571             (short_name ? rest : xbm_file_name));
4572       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4573       return;
4574    }
4575    if (colorDump) InitImageMap();
4576    Msg(TgLoadCachedString(CSTID_GENERATING_IMAGE));
4577 
4578    /* if we are print one page per file, don't redraw */
4579    if ((pixmap=DrawAllOnPixmap(&ltx, &lty, &w, &h, !nPageNumInFileName)) ==
4580          None) {
4581       if (!(PRTGIF && cmdLineStdOut &&
4582             !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4583             !preDumpSetup)) {
4584          fclose(fp);
4585          unlink(xbm_file_name);
4586       }
4587       return;
4588    }
4589 
4590    sprintf(gszMsgBox, TgLoadString(STID_PRINTING_INTO_NAMED_FILE),
4591          (short_name ? rest : xbm_file_name));
4592    Msg(gszMsgBox);
4593 
4594    GetPixelTrims(w, h, &left, &top, &right, &bottom);
4595 
4596    if ((image=XGetImage(mainDisplay, pixmap, left, top,
4597          w-left-right, h-top-bottom, AllPlanes, ZPixmap)) == NULL) {
4598       MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME, INFO_MB);
4599       if (!(PRTGIF && cmdLineStdOut &&
4600             !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4601             !preDumpSetup)) {
4602          fclose(fp);
4603          unlink(xbm_file_name);
4604       }
4605       XFreePixmap(mainDisplay, pixmap);
4606       return;
4607    }
4608    if (nInImageProc && topSel != NULL && topSel == botSel &&
4609          topSel->obj->type == OBJ_XPM) {
4610 /*    if ((bitmap_image=XGetImage(mainDisplay,
4611             topSel->obj->detail.xpm->bitmap, left, top,
4612             w-left-right, h-top-bottom, 1, ZPixmap)) == NULL) {
4613          Msg("Cannot generate image, print aborted!");
4614          if (!(PRTGIF && cmdLineStdOut &&
4615                !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4616                !preDumpSetup)) {
4617             fclose(fp);
4618             unlink(xbm_file_name);
4619          }
4620          XDestroyImage(image);
4621          XFreePixmap(mainDisplay, pixmap);
4622          return;
4623       } */
4624    }
4625    if (left != 0 || top != 0 || right != 0 || bottom != 0) {
4626       sprintf(gszMsgBox, TgLoadString(STID_APPLY_EXP_PXL_TRM_VALS),
4627             left, top, right, bottom);
4628       Msg(gszMsgBox);
4629    }
4630    if (whereToPrint == EPSI_FILE && generateTiffEPSI &&
4631          pageStyle == LANDSCAPE) {
4632       /* for landscape mode TiffEPSI, we need to rotate the image */
4633       XImage *rotated_image=RotateImageForLandscape(image, &w, &h, &left, &top,
4634             &right, &bottom);
4635 
4636       if (rotated_image == NULL) {
4637          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
4638                INFO_MB);
4639          if (!(PRTGIF && cmdLineStdOut &&
4640                !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4641                !preDumpSetup)) {
4642             fclose(fp);
4643             unlink(xbm_file_name);
4644          }
4645          if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4646          XDestroyImage(image);
4647          XFreePixmap(mainDisplay, pixmap);
4648          return;
4649       }
4650       XDestroyImage(image);
4651       image = rotated_image;
4652    }
4653    writeFileFailed = FALSE;
4654    if (colorDump && nInImageProc && gnConvolving) {
4655 #ifdef _TGIF_DBG /* debug, do not translate */
4656       fprintf(stderr,
4657             "Warning (unexpected): gnConvolving is TRUE in DumpXBitmapFile.\n");
4658 #endif /* _TGIF_DBG */
4659       if (!DoConvolution(fp, image, bitmap_image, w, h, NULL)) {
4660          if (!(PRTGIF && cmdLineStdOut &&
4661                !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4662                !preDumpSetup)) {
4663             fclose(fp);
4664             unlink(xbm_file_name);
4665          }
4666          if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4667          XDestroyImage(image);
4668          XFreePixmap(mainDisplay, pixmap);
4669          return;
4670       }
4671    } else if (colorDump) {
4672       if (dumpPpmPreferred) {
4673          /* don't do anything here, do it below */
4674       } else {
4675          int saved_xpm_output_version=xpmOutputVersion;
4676 
4677          if (whereToPrint==GIF_FILE || whereToPrint==HTML_FILE ||
4678                whereToPrint==PNG_FILE || whereToPrint==JPEG_FILE ||
4679                whereToPrint==PPM_FILE) {
4680             if (useXPmVersion1ForImageMap) {
4681                xpmOutputVersion = 1;
4682             }
4683          }
4684          BuildXPmColors(image, w, h, left, top, right, bottom, FALSE);
4685 
4686          if (numColorsToDump >= MAXXPMEXPORTCOLORS) {
4687             sprintf(gszMsgBox, TgLoadString(STID_TOO_MANY_COLORS_LIMIT_IS),
4688                   numColorsToDump, MAXXPMEXPORTCOLORS);
4689             if (PRTGIF) {
4690                fprintf(stderr, "%s\n", gszMsgBox);
4691             } else {
4692                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4693             }
4694             if (!(PRTGIF && cmdLineStdOut &&
4695                   !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4696                   !preDumpSetup)) {
4697                fclose(fp);
4698                unlink(xbm_file_name);
4699             }
4700             if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4701             XDestroyImage(image);
4702             XFreePixmap(mainDisplay, pixmap);
4703             return;
4704          }
4705          DumpXpmHeader(fp, w, h, name, left, top, right, bottom);
4706 
4707          xpmOutputVersion = saved_xpm_output_version;
4708       }
4709    } else {
4710       DumpXbmHeader(fp, w, h, name, left, top, right, bottom);
4711    }
4712    SaveStatusStrings();
4713    if (colorDump && nInImageProc && gnConvolving) {
4714    } else if (colorDump) {
4715       if (dumpPpmPreferred) {
4716          if (!DumpXImageToPpm6(fp, image, bitmap_image, w, h, left, top,
4717                right, bottom)) {
4718             if (!(PRTGIF && cmdLineStdOut &&
4719                   !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4720                   !preDumpSetup)) {
4721                fclose(fp);
4722             }
4723             if (!(PRTGIF && cmdLineStdOut &&
4724                   !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4725                   !preDumpSetup)) {
4726                unlink(xbm_file_name);
4727             }
4728             if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4729             XDestroyImage(image);
4730             XFreePixmap(mainDisplay, pixmap);
4731 
4732             return;
4733          }
4734       } else {
4735 #ifdef NOT_DEFINED
4736 #ifdef _TGIF_DBG
4737          DebugXPmColorsAndExportImage(image, w, h, left, top, right, bottom);
4738 #endif /* _TGIF_DBG */
4739 #endif /* NOT_DEFINED */
4740          if (!BuildXPmBuckets(numColorsToDump, pixelValue,
4741                dumpIndexToColorIndex, INVALID, NULL, NULL)) {
4742             if (!(PRTGIF && cmdLineStdOut && !(whereToPrint == EPSI_FILE &&
4743                   generateTiffEPSI) && !preDumpSetup)) {
4744                fclose(fp);
4745                unlink(xbm_file_name);
4746             }
4747             if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4748             XDestroyImage(image);
4749             XFreePixmap(mainDisplay, pixmap);
4750             return;
4751          }
4752          if (!DumpXpmBody(fp, image, bitmap_image, w, h, left, top, right,
4753                bottom, nInImageProc, bg_pixel)) {
4754             if (!(PRTGIF && cmdLineStdOut &&
4755                   !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4756                   !preDumpSetup)) {
4757                fclose(fp);
4758             }
4759             if (!(PRTGIF && cmdLineStdOut &&
4760                   !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4761                   !preDumpSetup)) {
4762                unlink(xbm_file_name);
4763             }
4764             if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4765             XDestroyImage(image);
4766             XFreePixmap(mainDisplay, pixmap);
4767 
4768             return;
4769          }
4770       }
4771    } else {
4772       DumpXbmBody(fp, image, w, h, left, top, right, bottom, bg_pixel);
4773    }
4774    RestoreStatusStrings();
4775    if (!(PRTGIF && cmdLineStdOut &&
4776          !(whereToPrint == EPSI_FILE && generateTiffEPSI) && !preDumpSetup)) {
4777       fclose(fp);
4778    }
4779    XDestroyImage(image);
4780    XFreePixmap(mainDisplay, pixmap);
4781 
4782    if (writeFileFailed) {
4783       writeFileFailed = FALSE;
4784       FailToWriteFileMessage(xbm_file_name);
4785    } else {
4786       if (whereToPrint == PPM_FILE || dumpPpmPreferred) {
4787          sprintf(gszMsgBox, TgLoadString(STID_FORMAT_FILE_WH_PRINTED_INTO),
4788                (colorDump ? "PPM" : "PBM"), w-left-right, h-top-bottom,
4789                (short_name ? rest : xbm_file_name));
4790       } else {
4791          sprintf(gszMsgBox, TgLoadString(STID_FORMAT_FILE_WH_PRINTED_INTO),
4792                (colorDump ? "XPM" : "XBM"), w-left-right, h-top-bottom,
4793                (short_name ? rest : xbm_file_name));
4794       }
4795       if (PRTGIF && !cmdLineStdOut) {
4796          if (!cmdLineQuiet) {
4797             fprintf(stderr, "%s\n", gszMsgBox);
4798          }
4799       } else {
4800          Msg(gszMsgBox);
4801       }
4802       if (colorDump && (whereToPrint==GIF_FILE || whereToPrint==HTML_FILE ||
4803             whereToPrint==PNG_FILE || whereToPrint==JPEG_FILE ||
4804             (dumpPpmPreferred && whereToPrint==XBM_FILE))) {
4805          int src_is_ppm=dumpPpmPreferred;
4806 
4807          SaveStatusStrings();
4808          GenerateImageMap(xbm_file_name, src_is_ppm, ltx+left, lty+top,
4809                ltx+w-right, lty+h-bottom, nPageNumInFileName);
4810          RestoreStatusStrings();
4811          if (!(PRTGIF && cmdLineStdOut &&
4812                !(whereToPrint == EPSI_FILE && generateTiffEPSI) &&
4813                !preDumpSetup)) {
4814             unlink(xbm_file_name);
4815          }
4816       }
4817    }
4818    if (nInImageProc) {
4819       strcpy(gszImageProcXPmFile, xbm_file_name);
4820       if (gnConvolving) {
4821          CleanUpConvolution();
4822       }
4823    }
4824    if (bitmap_image != NULL) XDestroyImage(bitmap_image);
4825 }
4826 
DumpXImageToFile(image,w,h,fname,ext)4827 int DumpXImageToFile(image, w, h, fname, ext)
4828    XImage *image;
4829    int w, h;
4830    char *fname, *ext;
4831 {
4832    if (fullTrueColorMode && HasZlibSupport()) {
4833       if (DumpXImageToPpmFile(image, w, h, fname, TRUE)) {
4834          if (ext != NULL) strcpy(ext, ".ppm.z");
4835          return TRUE;
4836       }
4837    }
4838    if (ext != NULL) strcpy(ext, ".xpm");
4839 
4840    return DumpXImageToXpmFile(image, w, h, fname);
4841 }
4842 
4843 static
FailedExportXPixmapDeckToGIF(count,gif_fp,gif_fname,tmp_fnames)4844 void FailedExportXPixmapDeckToGIF(count, gif_fp, gif_fname, tmp_fnames)
4845    int count;
4846    FILE *gif_fp;
4847    char *gif_fname, *tmp_fnames;
4848 {
4849    if (gif_fp != NULL) fclose(gif_fp);
4850    if (*gif_fname != '\0') unlink(gif_fname);
4851    if (tmp_fnames != NULL) {
4852       int i=0, index=0;
4853 
4854       for (i=0, index=0; i < count; i++, index += MAXPATHLENGTH) {
4855          char *psz=NULL;
4856 
4857          if (tmp_fnames[index] == '\0') {
4858             break;
4859          }
4860          unlink(&tmp_fnames[index]);
4861          if ((psz=UtilStrRChr(&tmp_fnames[index], '.')) != NULL) {
4862             *psz = '\0';
4863             unlink(&tmp_fnames[index]);
4864          }
4865       }
4866       free(tmp_fnames);
4867    }
4868 }
4869 
ExportXPixmapDeckToGIF()4870 void ExportXPixmapDeckToGIF()
4871 {
4872    struct ObjRec *obj_ptr=NULL, *xpm_obj=NULL;
4873    struct ObjRec *saved_top_obj=topObj, *saved_bot_obj=botObj;
4874    int i=0, first_one=TRUE, w=(-1), h=(-1), count=0, index=0, len=0, ok=TRUE;
4875    int short_name=FALSE, bytes_read=0, watch_cursor=watchCursorOnMainWindow;
4876    char *tmp_fnames=NULL, *cmd=NULL, *rest=NULL, gif_fname[MAXPATHLENGTH];
4877    char buf[1024];
4878    FILE *gif_fp=NULL, *pfp=NULL;
4879 
4880    if (!curDirIsLocal) {
4881       MsgBox(TgLoadString(STID_CANNOT_PRINT_REMOTE_FILE), TOOL_NAME, INFO_MB);
4882       return;
4883    } else if (!curFileDefined) {
4884       sprintf(gszMsgBox, TgLoadString(STID_NO_CUR_FILE_CANNOT_GEN_FORMAT),
4885             "GIF"),
4886       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4887       return;
4888    }
4889    if (topSel == NULL || topSel != botSel) {
4890       MsgBox(TgLoadString(STID_SEL_XPM_DECK_TO_EXPORT), TOOL_NAME, INFO_MB);
4891       return;
4892    }
4893    obj_ptr = topSel->obj;
4894    if (obj_ptr->type != OBJ_GROUP && obj_ptr->type != OBJ_SYM &&
4895          obj_ptr->type != OBJ_ICON) {
4896       MsgBox(TgLoadString(STID_SEL_XPM_DECK_TO_EXPORT), TOOL_NAME, INFO_MB);
4897       return;
4898    }
4899    for (xpm_obj=obj_ptr->detail.r->first; xpm_obj != NULL;
4900          xpm_obj=xpm_obj->next) {
4901       if (xpm_obj->type == OBJ_XPM) {
4902          if (first_one) {
4903             w = xpm_obj->obbox.rbx-xpm_obj->obbox.ltx;
4904             h = xpm_obj->obbox.rby-xpm_obj->obbox.lty;
4905             first_one = FALSE;
4906          } else {
4907             if (w != xpm_obj->obbox.rbx-xpm_obj->obbox.ltx ||
4908                   h != xpm_obj->obbox.rby-xpm_obj->obbox.lty) {
4909                sprintf(gszMsgBox,
4910                      TgLoadString(STID_MANY_SZ_FAIL_XPM_DESK_EXPORT), w, h);
4911                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4912                return;
4913             }
4914          }
4915          count++;
4916       }
4917    }
4918    tmp_fnames = (char*)malloc(count*MAXPATHLENGTH*sizeof(char));
4919    if (tmp_fnames == NULL) FailAllocMessage();
4920 
4921    curPage->top = curPage->bot = topObj = botObj = NULL;
4922 
4923    SaveStatusStrings();
4924    HighLightReverse();
4925    RemoveAllSel();
4926    PushPageInfo();
4927 
4928    InitImageMap();
4929 
4930    SetWatchCursor(drawWindow);
4931    SetWatchCursor(mainWindow);
4932 
4933    len = strlen(xpmDeckToGifAnimCmd)+5;
4934    for (xpm_obj=obj_ptr->detail.r->first; xpm_obj != NULL;
4935          xpm_obj=xpm_obj->next) {
4936       if (xpm_obj->type == OBJ_XPM) {
4937          int saved_colordump=colorDump, saved_wheretoprint=whereToPrint;
4938          int saved_xpm_output_version=xpmOutputVersion;
4939          int dump_ppm_preferred=FALSE;
4940 
4941          curPage->top = curPage->bot = topObj = botObj = DupObj(xpm_obj);
4942          topSel = botSel = SelectThisObject(topObj);
4943          UpdSelBBox();
4944 
4945          if (useXPmVersion1ForXPmDeck) {
4946             xpmOutputVersion = 1;
4947          }
4948          *gszImageProcXPmFile = '\0';
4949          gnConvolving = FALSE;
4950 
4951          colorDump = TRUE;
4952          whereToPrint = XBM_FILE;
4953          gnInImageProc = TRUE;
4954 
4955          dump_ppm_preferred = fullTrueColorMode &&
4956                (whereToPrint==XBM_FILE && xpmOutputVersion == 3);
4957          DumpXBitmapFile(gnInImageProc, dump_ppm_preferred, FALSE);
4958 
4959          RemoveAllSel();
4960          DelAllObj();
4961          gnInImageProc = FALSE;
4962          whereToPrint = saved_wheretoprint;
4963          colorDump = saved_colordump;
4964          xpmOutputVersion = saved_xpm_output_version;
4965          if (*gszImageProcXPmFile == '\0') {
4966             break;
4967          }
4968          sprintf(&tmp_fnames[index], "%s.gif", gszImageProcXPmFile);
4969          if (!ConvertXpmToGif(gszImageProcXPmFile, &tmp_fnames[index], FALSE,
4970                GIF_FILE)) {
4971             unlink(gszImageProcXPmFile);
4972             break;
4973          }
4974          len += strlen(&tmp_fnames[index])+1;
4975 
4976          index += MAXPATHLENGTH;
4977       }
4978    }
4979    SetDefaultCursor(mainWindow);
4980    ShowCursor();
4981 
4982    *gif_fname = '\0';
4983    SetOutputFileName(gif_fname, GetExportExt(GIF_FILE), &short_name, &rest);
4984    gif_fp = fopen(gif_fname,"w");
4985    if (gif_fp == NULL) {
4986       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
4987             ((short_name && *outputDir=='\0') ? rest : gif_fname));
4988       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4989       FailedExportXPixmapDeckToGIF(count, gif_fp, gif_fname, tmp_fnames);
4990       ok = FALSE;
4991    }
4992    if (ok) {
4993       cmd = (char*)malloc(len+1);
4994       strcpy(cmd, xpmDeckToGifAnimCmd);
4995       len = strlen(cmd);
4996       for (i=0, index=0; i < count; i++, index += MAXPATHLENGTH) {
4997          if (tmp_fnames[index] == '\0') {
4998             break;
4999          }
5000          sprintf(&cmd[len], " %s", &tmp_fnames[index]);
5001          len += strlen(&cmd[len]);
5002       }
5003       if (FindProgramInPath(cmd, NULL, FALSE)) {
5004          sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM),
5005                xpmDeckToGifAnimCmd);
5006          SetStringStatus(gszMsgBox);
5007          XSync(mainDisplay, False);
5008          if ((pfp=(FILE*)popen(cmd, "r")) == NULL) {
5009             sprintf(gszMsgBox, TgLoadString(STID_CANNOT_EXEC_FORMAT_NOT_GEN),
5010                   cmd, "GIF");
5011             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5012             FailedExportXPixmapDeckToGIF(count, gif_fp, gif_fname, tmp_fnames);
5013             ok = FALSE;
5014          } else {
5015             if (!watch_cursor) {
5016                SetWatchCursor(drawWindow);
5017                SetWatchCursor(mainWindow);
5018             }
5019             while ((bytes_read=fread(buf, sizeof(char), sizeof(buf), pfp)) >
5020                   0) {
5021                if ((int)fwrite(buf, sizeof(char), bytes_read, gif_fp) <= 0) {
5022                   writeFileFailed = TRUE;
5023                   break;
5024                }
5025             }
5026             pclose(pfp);
5027             if (!watch_cursor) {
5028                SetDefaultCursor(mainWindow);
5029                ShowCursor();
5030             }
5031             fclose(gif_fp);
5032             gif_fp = NULL;
5033             if (writeFileFailed) {
5034                FailToWriteFileMessage(
5035                      ((short_name && *outputDir=='\0') ? rest : gif_fname));
5036                FailedExportXPixmapDeckToGIF(count, gif_fp, gif_fname,
5037                      tmp_fnames);
5038                ok = FALSE;
5039             }
5040          }
5041       }
5042    }
5043    if (ok) {
5044       /*
5045        * GIF generated, set gif_fname to NULL so that the GIF file
5046        * doesn't get deleted FailedExportXPixmapDeckToGIF()
5047        */
5048       *gif_fname = '\0';
5049       FailedExportXPixmapDeckToGIF(count, gif_fp, gif_fname, tmp_fnames);
5050    }
5051    curPage->top = topObj = saved_top_obj;
5052    curPage->bot = botObj = saved_bot_obj;
5053    PopPageInfo();
5054 
5055    RedrawAnArea(botObj, obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
5056          obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
5057          obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
5058          obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
5059    topSel = botSel = SelectThisObject(obj_ptr);
5060    UpdSelBBox();
5061    HighLightForward();
5062    RestoreStatusStrings();
5063 }
5064 
DumpBitmap(FP,image,data,image_w,image_h,transformed,orig_x,orig_y,adj_x,pmtrx,indent)5065 void DumpBitmap(FP, image, data, image_w, image_h, transformed, orig_x, orig_y,
5066       adj_x, pmtrx, indent)
5067    FILE *FP;
5068    XImage *image;
5069    char *data;
5070    int image_w, image_h, transformed, orig_x, orig_y, adj_x, indent;
5071    struct MtrxRec *pmtrx;
5072 {
5073    register int m;
5074    int row, h_blocks, v_blocks, nibbles_per_row;
5075 
5076    h_blocks = ((image_w&0xff) == 0) ? (image_w>>8) : ((image_w>>8)+1);
5077    v_blocks = ((image_h&0xff) == 0) ? (image_h>>8) : ((image_h>>8)+1);
5078    nibbles_per_row = ((image_w%4)==0) ? (int)(image_w>>2) : (int)(image_w>>2)+1;
5079 
5080    for (m=0; m < indent; m++) fputc(' ', FP);
5081    fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
5082 
5083    for (m=0; m < indent; m++) fputc(' ', FP);
5084    if (transformed) {
5085       fprintf(FP, "   %1d %1d %s\n", orig_x, orig_y, gPsCmd[PS_TRANSLATE]);
5086    } else {
5087       fprintf(FP, "   %1d %1d %s %.3f %.3f %s %1d %s\n\n",
5088             orig_x, orig_y, gPsCmd[PS_TRANSLATE], pmtrx->dump_h_scale,
5089             pmtrx->dump_v_scale, gPsCmd[PS_SCALE], pmtrx->degree,
5090             gPsCmd[PS_ROTATE]);
5091    }
5092 
5093    for (row=0; row < v_blocks; row++) {
5094       int y, col, block_h;
5095 
5096       y = row<<8;
5097       block_h = (row == v_blocks-1) ? image_h-y : 0x100;
5098 
5099       for (col=0; col < h_blocks; col++) {
5100          int i, j, x, num_nibbles, nibble_count, block_w;
5101 
5102          x = col<<8;
5103          block_w = (col == h_blocks-1) ? image_w-x : 0x100;
5104 
5105          num_nibbles = ((block_w%4) == 0) ? (int)(block_w>>2) :
5106                (int)(block_w>>2)+1;
5107 
5108          for (m=0; m < indent; m++) fputc(' ', FP);
5109          fprintf(FP, "   %s\n", gPsCmd[PS_GSAVE]);
5110 
5111          for (m=0; m < indent; m++) fputc(' ', FP);
5112          fprintf(FP, "   %1d %1d %s\n", x+adj_x, y, gPsCmd[PS_TRANSLATE]);
5113 
5114          for (m=0; m < indent; m++) fputc(' ', FP);
5115          fprintf(FP, "   %1d %1d true [1 0 0 1 0 0]\n", block_w, block_h);
5116 
5117          for (m=0; m < indent; m++) fputc(' ', FP);
5118          fprintf(FP, "   {<");
5119 
5120          if (PRTGIF && !cmdLineOpenDisplay) {
5121             nibble_count = 0;
5122             for (i=0; i < block_h; i++) {
5123                for (j=0; j < num_nibbles; j++) {
5124                   if (nibble_count++ == 64) {
5125                      nibble_count = 1;
5126                      fprintf(FP, "\n");
5127                      for (m=0; m < indent; m++) fputc(' ', FP);
5128                      fprintf(FP, "     ");
5129                   }
5130                   fprintf(FP, "%c", data[(i+y)*nibbles_per_row+j+(x>>2)]);
5131                }
5132                if ((num_nibbles & 0x1) == 1) {
5133                   if (nibble_count++ == 64) {
5134                      nibble_count = 1;
5135                      fprintf(FP, "\n");
5136                      for (m=0; m < indent; m++) fputc(' ', FP);
5137                      fprintf(FP, "     ");
5138                   }
5139                   fprintf(FP, "0");
5140                }
5141             }
5142          } else {
5143             nibble_count = 0;
5144             for (i=0; i < block_h; i++) {
5145                int bit_count=0, data;
5146 
5147                data = 0;
5148                for (j=0; j < block_w; j++) {
5149                   data = (XGetPixel(image, j+x, i+y) == 1) ? (data<<1) | 1 :
5150                         (data<<1);
5151                   if (++bit_count == 4) {
5152                      if (nibble_count++ == 64) {
5153                         nibble_count = 1;
5154                         fprintf(FP, "\n");
5155                         for (m=0; m < indent; m++) fputc(' ', FP);
5156                         fprintf(FP, "     ");
5157                      }
5158                      fprintf(FP, "%c", hexValue[data]);
5159                      bit_count = 0;
5160                      data = 0;
5161                   }
5162                }
5163                if ((block_w % 4) != 0) {
5164                   data <<= (4 - (block_w % 4));
5165                   if (nibble_count++ == 64) {
5166                      nibble_count = 1;
5167                      fprintf(FP, "\n");
5168                      for (m=0; m < indent; m++) fputc(' ', FP);
5169                      fprintf(FP, "     ");
5170                   }
5171                   fprintf(FP, "%c", hexValue[data]);
5172                }
5173                if ((num_nibbles & 0x1) == 1) {
5174                   if (nibble_count++ == 64) {
5175                      nibble_count = 1;
5176                      fprintf(FP, "\n");
5177                      for (m=0; m < indent; m++) fputc(' ', FP);
5178                      fprintf(FP, "     ");
5179                   }
5180                   fprintf(FP, "0");
5181                }
5182             }
5183          }
5184          fprintf(FP, ">}\n");
5185 
5186          for (m=0; m < indent; m++) fputc(' ', FP);
5187          fprintf(FP, "   %s\n", gPsCmd[PS_IMAGEMASK]);
5188 
5189          for (m=0; m < indent; m++) fputc(' ', FP);
5190          fprintf(FP, "   %s\n", gPsCmd[PS_GRESTORE]);
5191 
5192          if (row!=v_blocks-1 || col!=h_blocks-1) {
5193             fprintf(FP, "\n");
5194          }
5195       }
5196    }
5197    for (m=0; m < indent; m++) fputc(' ', FP);
5198    fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
5199 }
5200 
DumpXBmObj(FP,ObjPtr)5201 void DumpXBmObj(FP, ObjPtr)
5202    FILE *FP;
5203    struct ObjRec *ObjPtr;
5204 {  /* called when printing in the PostScript format */
5205    int ltx, lty, rbx, rby, w, h, trans_pat, fill, image_w, image_h;
5206    int color_index, flip, orig_x=ObjPtr->x, orig_y=ObjPtr->y;
5207    Pixmap bitmap=None;
5208    XImage *image=NULL;
5209    struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
5210    struct MtrxRec mtrx;
5211 
5212    if (xbm_ptr->real_type == XBM_EPS) {
5213       DumpEPSObj(FP, ObjPtr);
5214       if (preDumpSetup) hasReadHexString = TRUE;
5215       return;
5216    }
5217 
5218    if (ObjPtr->ctm == NULL) {
5219       ltx = ObjPtr->obbox.ltx;
5220       lty = ObjPtr->obbox.lty;
5221       rbx = ObjPtr->obbox.rbx;
5222       rby = ObjPtr->obbox.rby;
5223    } else {
5224       ltx = ObjPtr->orig_obbox.ltx;
5225       lty = ObjPtr->orig_obbox.lty;
5226       rbx = ObjPtr->orig_obbox.rbx;
5227       rby = ObjPtr->orig_obbox.rby;
5228    }
5229 
5230    trans_pat = ObjPtr->trans_pat;
5231    bitmap = xbm_ptr->bitmap;
5232    fill = xbm_ptr->fill;
5233    flip = xbm_ptr->flip;
5234    image_w = xbm_ptr->image_w;
5235    image_h = xbm_ptr->image_h;
5236 
5237    w = rbx - ltx;
5238    h = rby - lty;
5239 
5240    if (!(PRTGIF && !cmdLineOpenDisplay)) {
5241       if ((image=xbm_ptr->image) == NULL) {
5242          if ((image=xbm_ptr->image=XGetImage(mainDisplay, bitmap, 0, 0,
5243                image_w, image_h, 1, ZPixmap)) == NULL) {
5244             MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
5245                   INFO_MB);
5246             return;
5247          }
5248       }
5249    }
5250    color_index = ObjPtr->color;
5251 
5252    if (ObjPtr->ctm == NULL) {
5253       memset(&mtrx, 0, sizeof(struct MtrxRec));
5254       mtrx.image_w = (float)image_w; mtrx.image_h = (float)image_h;
5255       mtrx.w = (float)w; mtrx.h = (float)h;
5256       mtrx.rotate = ROTATE0; mtrx.flip = flip;
5257 
5258       CalcTransform(&mtrx);
5259 
5260       orig_x = (mtrx.transformed_w >= 0.0) ? ltx : ltx+w;
5261       orig_y = (mtrx.transformed_h >= 0.0) ? lty : lty+h;
5262    }
5263    fprintf(FP, "%% XBM\n");
5264    if (ObjPtr->ctm != NULL) {
5265       float m[6];
5266 
5267       fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
5268       m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
5269       m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
5270       m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
5271       m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
5272       fprintf(FP, "   %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
5273             gPsCmd[PS_TRANSLATE]);
5274       fprintf(FP, "   [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
5275             m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
5276             ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
5277       fprintf(FP, "   %1d %s %1d %s %s\n",
5278             ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG],
5279             gPsCmd[PS_TRANSLATE]);
5280    }
5281    DumpRGBColorLine(FP, color_index, 0, TRUE);
5282 
5283    switch (fill) {
5284    case NONEPAT: break;
5285    case SOLIDPAT:
5286       DumpRectPath(FP, ltx, lty, rbx, rby, 0, FALSE);
5287       fprintf(FP, "%s\n", gPsCmd[PS_FILL]);
5288       break;
5289    case BACKPAT:
5290       if (!trans_pat) {
5291          DumpRectPath(FP, ltx, lty, rbx, rby, 0, FALSE);
5292          fprintf(FP, "1 %s %s\n\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
5293          DumpRGBColorLine(FP, color_index, 0, TRUE);
5294       }
5295       break;
5296    default:
5297       /* patterned */
5298       fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
5299       if (colorDump || !useGray) {
5300          if (preDumpSetup) PSUseColorPattern();
5301          if (!trans_pat) {
5302             DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
5303             fprintf(FP, "1 %s %s\n\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
5304             DumpRGBColorLine(FP, color_index, 3, TRUE);
5305          }
5306          DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
5307          fprintf(FP, "%s %s\n", gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
5308          DumpPatFill(FP, fill, ObjPtr->bbox, 3, TRUE);
5309       } else {
5310          GrayCheck(fill);
5311          fprintf(FP, "   %s %s\n", GrayStr(fill), gPsCmd[PS_SETGRAY]);
5312          DumpRectPath(FP, ltx, lty, rbx, rby, 3, FALSE);
5313          fprintf(FP, "%s\n", gPsCmd[PS_FILL]);
5314       }
5315       fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
5316       break;
5317    }
5318    DumpBitmap(FP, image, ObjPtr->detail.xbm->data, image_w, image_h,
5319          (ObjPtr->ctm!=0), orig_x, orig_y, 0, &mtrx, 0);
5320 
5321    if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
5322    fprintf(FP, "\n");
5323 }
5324 
NeedsToCacheXBmObj(ObjPtr)5325 int NeedsToCacheXBmObj(ObjPtr)
5326    struct ObjRec *ObjPtr;
5327 {
5328    register struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
5329    int w, h;
5330 
5331    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
5332    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
5333 
5334    return (ObjPtr->ctm != NULL || zoomScale != 0 ||
5335          xbm_ptr->image_w != w || xbm_ptr->image_h != h || xbm_ptr->flip != 0
5336    );
5337 }
5338 
5339 static
DrawHiddenXBm(win,ctm,vs,x,y,w,h,s)5340 void DrawHiddenXBm(win, ctm, vs, x, y, w, h, s)
5341    Window win;
5342    struct XfrmMtrxRec *ctm;
5343    XPoint *vs;
5344    int x, y, w, h;
5345    char *s;
5346 {
5347    int str_w, len, sx, sy;
5348    XGCValues values;
5349 
5350    values.foreground = GetDrawingFgPixel(INVALID, INVALID);
5351    values.function = GXcopy;;
5352    values.fill_style = FillSolid;
5353 #ifdef NO_THIN_LINE
5354    values.line_width = 1;
5355 #else
5356    values.line_width = 0;
5357 #endif
5358    values.font = rulerFontPtr->fid;
5359    values.line_style = LineSolid;
5360 
5361    XChangeGC(mainDisplay, drawGC,
5362          GCForeground | GCFunction | GCFillStyle | GCLineWidth | GCFont |
5363          GCLineStyle, &values);
5364    if (ctm != NULL) {
5365       XDrawLines(mainDisplay, win, drawGC, vs, 5, CoordModeOrigin);
5366    } else {
5367       XDrawRectangle(mainDisplay, win, drawGC, x, y, w, h);
5368    }
5369 
5370    len = strlen(s);
5371    str_w = rulerFontWidth*len;
5372    if (str_w < w && rulerFontHeight < h) {
5373       sx = x + ((w-str_w)>>1);
5374       sy = y + ((h-rulerFontHeight)>>1);
5375       XDrawString(mainDisplay, win, drawGC, sx, sy+rulerFontAsc, s, len);
5376    }
5377    XSetFont(mainDisplay, drawGC, canvasFontPtr->fid);
5378 }
5379 
DrawXBmObj(win,XOff,YOff,ObjPtr)5380 void DrawXBmObj(win, XOff, YOff, ObjPtr)
5381    Window win;
5382    int XOff, YOff;
5383    struct ObjRec *ObjPtr;
5384 {
5385    int ltx, lty, rbx, rby, w, h, scr_w, scr_h, fill, trans_pat;
5386    int real_x_off, real_y_off;
5387    char s[80];
5388    struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
5389    XGCValues values;
5390 
5391    if (userDisableRedraw) return;
5392 
5393    if (ObjPtr->prev != NULL && ObjPtr->prev->type == OBJ_XBM &&
5394          ObjPtr->prev->detail.xbm->real_type == XBM_XBM &&
5395          ObjPtr->prev->detail.xbm->fill != NONEPAT &&
5396          Inside(ObjPtr->obbox, ObjPtr->prev->obbox)) {
5397       return;
5398    }
5399    trans_pat = ObjPtr->trans_pat;
5400    fill = xbm_ptr->fill;
5401 
5402    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
5403    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
5404 
5405    real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
5406    real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
5407    ltx = ZOOMED_SIZE(ObjPtr->obbox.ltx - real_x_off);
5408    lty = ZOOMED_SIZE(ObjPtr->obbox.lty - real_y_off);
5409    rbx = ZOOMED_SIZE(ObjPtr->obbox.rbx - real_x_off);
5410    rby = ZOOMED_SIZE(ObjPtr->obbox.rby - real_y_off);
5411    scr_w = rbx - ltx;
5412    scr_h = rby - lty;
5413 
5414    if (xbm_ptr->real_type==XBM_XBM && fill != NONEPAT) {
5415       values.foreground = GetDrawingBgPixel(fill, colorPixels[ObjPtr->color]);
5416       values.function = GXcopy;
5417       values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
5418       values.stipple = patPixmap[fill];
5419       XChangeGC(mainDisplay, drawGC,
5420             GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
5421       if (ObjPtr->ctm != NULL) {
5422          XFillPolygon(mainDisplay, win, drawGC,  ObjPtr->rotated_obbox, 5,
5423                Convex, CoordModeOrigin);
5424       } else {
5425          XFillRectangle(mainDisplay, win, drawGC, ltx, lty, scr_w, scr_h);
5426       }
5427    }
5428    if (!mapShown) {
5429       if (xbm_ptr->real_type == XBM_EPS) {
5430          DrawHiddenXBm(win, ObjPtr->ctm, ObjPtr->rotated_obbox,
5431                ltx, lty, scr_w, scr_h, xbm_ptr->filename);
5432       } else {
5433          sprintf(s, "(%1dx%1d)", xbm_ptr->image_w, xbm_ptr->image_h);
5434          DrawHiddenXBm(win, ObjPtr->ctm, ObjPtr->rotated_obbox,
5435                ltx, lty, scr_w, scr_h, s);
5436       }
5437       return;
5438    }
5439    if (NeedsToCacheXBmObj(ObjPtr) && xbm_ptr->cached_bitmap == None) {
5440       MakeCachedBitmap(ObjPtr);
5441    }
5442    if (xbm_ptr->real_type==XBM_XBM || (xbm_ptr->real_type==XBM_EPS &&
5443          xbm_ptr->bitmap!=None)) {
5444       values.foreground = colorPixels[ObjPtr->color];
5445       values.function = GXcopy;
5446       values.fill_style = FillStippled;
5447       values.ts_x_origin = ltx;
5448       values.ts_y_origin = lty;
5449 
5450       if (ObjPtr->ctm==NULL && zoomScale==0 &&
5451             xbm_ptr->flip==0 && xbm_ptr->image_w==w && xbm_ptr->image_h==h) {
5452          values.stipple = xbm_ptr->bitmap;
5453       } else {
5454          if (xbm_ptr->cached_bitmap == None) return;
5455          values.stipple = xbm_ptr->cached_bitmap;
5456       }
5457 
5458       XChangeGC(mainDisplay, drawGC,
5459             GCForeground | GCFunction | GCFillStyle | GCStipple |
5460             GCTileStipXOrigin | GCTileStipYOrigin, &values);
5461       XFillRectangle(mainDisplay, win, drawGC, ltx, lty, scr_w, scr_h);
5462       XSetTSOrigin(mainDisplay, drawGC, 0, 0);
5463    } else if (xbm_ptr->real_type==XBM_EPS && xbm_ptr->bitmap==None) {
5464       DrawHiddenXBm(win, ObjPtr->ctm, ObjPtr->rotated_obbox,
5465                ltx, lty, rbx-ltx, rby-lty, xbm_ptr->filename);
5466    }
5467 }
5468 
CreateXBmObj(ImageW,ImageH,W,H,bitmap,image)5469 struct ObjRec *CreateXBmObj(ImageW, ImageH, W, H, bitmap, image)
5470    int ImageW, ImageH, W, H;
5471    Pixmap bitmap;
5472    XImage *image;
5473 {
5474    struct XBmRec *xbm_ptr;
5475    struct ObjRec *obj_ptr;
5476 
5477    xbm_ptr = (struct XBmRec *)malloc(sizeof(struct XBmRec));
5478    if (xbm_ptr == NULL) FailAllocMessage();
5479    memset(xbm_ptr, 0, sizeof(struct XBmRec));
5480 
5481    xbm_ptr->image = image;
5482    xbm_ptr->image_w = ImageW;
5483    xbm_ptr->image_h = ImageH;
5484    xbm_ptr->bitmap = bitmap;
5485    xbm_ptr->data = NULL;
5486 
5487    xbm_ptr->eps_w = xbm_ptr->eps_h = 0;
5488 
5489    xbm_ptr->fill = objFill;
5490    xbm_ptr->flip = xbm_ptr->cached_flip = 0;
5491    xbm_ptr->cached_zoom = 0;
5492    xbm_ptr->cached_bitmap = None;
5493    xbm_ptr->cached_w = xbm_ptr->cached_h = 0;
5494 
5495    xbm_ptr->real_type = XBM_XBM;
5496    xbm_ptr->filename = NULL;
5497    xbm_ptr->epsflines = NULL;
5498    xbm_ptr->num_epsf_lines = 0;
5499 
5500    obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
5501    if (obj_ptr == NULL) FailAllocMessage();
5502    memset(obj_ptr, 0, sizeof(struct ObjRec));
5503 
5504    obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = drawOrigX;
5505    obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = drawOrigY;
5506    obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = W + drawOrigX;
5507    obj_ptr->bbox.rby = obj_ptr->obbox.rby = H + drawOrigY;
5508    obj_ptr->type = OBJ_XBM;
5509    obj_ptr->color = colorIndex;
5510    if (mainDisplay != NULL) {
5511       UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
5512             colorMenuItems[colorIndex]);
5513    }
5514    obj_ptr->id = objId++;
5515    obj_ptr->dirty = FALSE;
5516    obj_ptr->rotation = 0;
5517    obj_ptr->locked = FALSE;
5518    obj_ptr->detail.xbm = xbm_ptr;
5519    obj_ptr->fattr = obj_ptr->lattr = NULL;
5520    obj_ptr->ctm = NULL;
5521    obj_ptr->invisible = FALSE;
5522    obj_ptr->trans_pat = transPat;
5523 
5524    if (importXBmRV) InvertXBmObject(obj_ptr);
5525    return (obj_ptr);
5526 }
5527 
5528 static
CopyXBmProperties(DestXbmObj,SrcXbmObj)5529 void CopyXBmProperties(DestXbmObj, SrcXbmObj)
5530    struct ObjRec *DestXbmObj, *SrcXbmObj;
5531 {
5532    struct XBmRec *dest_xbm_ptr=DestXbmObj->detail.xbm;
5533    struct XBmRec *src_xbm_ptr=SrcXbmObj->detail.xbm;
5534 
5535    dest_xbm_ptr->fill = src_xbm_ptr->fill;
5536    DestXbmObj->color = SrcXbmObj->color;
5537    memcpy(DestXbmObj->color_str, SrcXbmObj->color_str,
5538          sizeof(DestXbmObj->color_str));
5539    DestXbmObj->trans_pat = SrcXbmObj->trans_pat;
5540 }
5541 
5542 static
FinishBreakUpXBitmap(obj_ptr,cols_and_rows,cols,rows)5543 int FinishBreakUpXBitmap(obj_ptr, cols_and_rows, cols, rows)
5544    struct ObjRec *obj_ptr;
5545    int cols_and_rows, cols, rows;
5546 {
5547    struct XBmRec *xbm_ptr=obj_ptr->detail.xbm;
5548    int y, image_w=xbm_ptr->image_w, image_h=xbm_ptr->image_h;
5549    int chunk_w=0, chunk_h=0, total_chunks=0;
5550    int orig_x=obj_ptr->x, orig_y=obj_ptr->y;
5551 
5552    if (cols_and_rows) {
5553       chunk_w = (int)(image_w / cols);
5554       chunk_h = (int)(image_h / rows);
5555    } else {
5556       chunk_w = cols;
5557       chunk_h = rows;
5558    }
5559    for (y=0; y < image_h; y += chunk_h) {
5560       int h=min(image_h-y,chunk_h), x;
5561 
5562       for (x=0; x < image_w; x += chunk_w) {
5563          int w=min(image_w-x,chunk_w);
5564          struct ObjRec *new_obj_ptr;
5565          Pixmap dest_bitmap=None;
5566          XImage *dest_image=NULL;
5567 
5568          if (w <= 0 || h <= 0 ||
5569                !ExtractBitmap(xbm_ptr->bitmap, xbm_ptr->image, x, y, w, h,
5570                &dest_bitmap, &dest_image)) {
5571             continue;
5572          }
5573          total_chunks++;
5574          new_obj_ptr = CreateXBmObj(w, h, w, h, dest_bitmap, dest_image);
5575          CopyXBmProperties(new_obj_ptr, obj_ptr);
5576          AdjObjBBox(new_obj_ptr);
5577          MoveObj(new_obj_ptr, orig_x+x, orig_y+y);
5578          AddObj(NULL, topObj, new_obj_ptr);
5579       }
5580    }
5581    if (total_chunks > 0) {
5582       int i;
5583 
5584       RemoveAllSel();
5585       UnlinkObj(obj_ptr);
5586       FreeObj(obj_ptr);
5587 
5588       for (i=0, obj_ptr=topObj; obj_ptr != NULL && i < total_chunks; i++,
5589             obj_ptr=obj_ptr->next) {
5590          AddObjIntoSel(obj_ptr, botSel, NULL, &topSel, &botSel);
5591       }
5592    }
5593    return (total_chunks > 0);
5594 }
5595 
BreakUpXBitmap(obj_ptr,cols_and_rows,cols,rows)5596 void BreakUpXBitmap(obj_ptr, cols_and_rows, cols, rows)
5597    struct ObjRec *obj_ptr;
5598    int cols_and_rows, cols, rows;
5599 {
5600    struct XBmRec *xbm_ptr=obj_ptr->detail.xbm;
5601 
5602    if (xbm_ptr->real_type == XBM_EPS) {
5603       MsgBox(TgLoadString(STID_CANNOT_BREAKUP_EPS), TOOL_NAME, INFO_MB);
5604       return;
5605    }
5606    HighLightReverse();
5607    PrepareToReplaceAnObj(obj_ptr);
5608    if (FinishBreakUpXBitmap(obj_ptr, cols_and_rows, cols, rows)) {
5609       UpdSelBBox();
5610       RecordCmd(CMD_ONE_TO_MANY, NULL, topSel, botSel, numObjSelected);
5611       SetFileModified(TRUE);
5612       justDupped = FALSE;
5613    } else {
5614       AbortPrepareCmd(CMD_REPLACE);
5615    }
5616    HighLightForward();
5617 }
5618 
DumpXBmData(FP,bitmap,image,W,H)5619 void DumpXBmData(FP, bitmap, image, W, H)
5620    FILE *FP;
5621    Pixmap bitmap;
5622    XImage **image;
5623    int W, H;
5624 {
5625    register int nibble_count, bit_count, data, i, j;
5626 
5627    if (*image == NULL) {
5628       if ((*image=XGetImage(mainDisplay,bitmap,0,0,W,H,1,ZPixmap)) == NULL) {
5629          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
5630                INFO_MB);
5631          return;
5632       }
5633    }
5634 
5635    nibble_count = 0;
5636 
5637    for (i=0; i < H; i++) {
5638       bit_count = 0;
5639       data = 0;
5640 
5641       for (j=0; j < W; j++) {
5642          data = (XGetPixel(*image, j, i) == 1) ? (data<<1) | 1 : (data<<1);
5643 
5644          if (++bit_count == 4) {
5645             if (nibble_count++ == 64) {
5646                nibble_count = 1;
5647                if (fprintf(FP, "\n     ") == EOF) writeFileFailed = TRUE;
5648             }
5649             if (fprintf(FP, "%c", hexValue[data]) == EOF) {
5650                writeFileFailed = TRUE;
5651             }
5652             bit_count = 0;
5653             data = 0;
5654          }
5655       }
5656       if ((W % 4) != 0) {
5657          data <<= (4 - (W % 4));
5658          if (nibble_count++ == 64) {
5659             nibble_count = 1;
5660             if (fprintf(FP, "\n     ") == EOF) writeFileFailed = TRUE;
5661          }
5662          if (fprintf(FP, "%c", hexValue[data]) == EOF) writeFileFailed = TRUE;
5663       }
5664    }
5665 }
5666 
SaveXBmObj(FP,ObjPtr)5667 void SaveXBmObj(FP, ObjPtr)
5668    FILE *FP;
5669    struct ObjRec *ObjPtr;
5670 {
5671    register int i;
5672    int ltx, lty, rbx, rby, image_w, image_h;
5673    int no_bitmap, compressed=FALSE;
5674    struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
5675 
5676    no_bitmap = (xbm_ptr->real_type==XBM_EPS &&
5677          !(xbm_ptr->save_epsf && xbm_ptr->bitmap != None));
5678 
5679    ltx = ObjPtr->obbox.ltx; lty = ObjPtr->obbox.lty;
5680    rbx = ObjPtr->obbox.rbx; rby = ObjPtr->obbox.rby;
5681    if (no_bitmap) {
5682       image_w = xbm_ptr->eps_w;
5683       image_h = xbm_ptr->eps_h;
5684    } else {
5685       image_w = xbm_ptr->image_w;
5686       image_h = xbm_ptr->image_h;
5687    }
5688    if (fprintf(FP, "xbm('%s','',", colorMenuItems[ObjPtr->color]) == EOF) {
5689       writeFileFailed = TRUE;
5690    }
5691    if (fprintf(FP,
5692          "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,0,%1d,%1d,%1d,%1d,%1d,%1d,",
5693          ltx, lty, rbx, rby, xbm_ptr->fill, ObjPtr->id, ObjPtr->rotation,
5694          image_w, image_h, xbm_ptr->flip, xbm_ptr->real_type,
5695          xbm_ptr->llx, xbm_ptr->lly, xbm_ptr->urx, xbm_ptr->ury) == EOF) {
5696       writeFileFailed = TRUE;
5697    }
5698    if (fprintf(FP,
5699          "%1d,%1d,%1d,%1d,%1d,%1d,%1d,\n    ",
5700          no_bitmap, ObjPtr->locked, xbm_ptr->save_epsf, compressed,
5701          ObjPtr->ctm!=NULL, ObjPtr->invisible, ObjPtr->trans_pat) == EOF) {
5702       writeFileFailed = TRUE;
5703    }
5704    switch (xbm_ptr->real_type) {
5705    case XBM_XBM:
5706       if (fprintf(FP, "\"\",\"\",") == EOF) writeFileFailed = TRUE;
5707       break;
5708    case XBM_EPS:
5709       if (fprintf(FP, "\"%s\",\"%s\",", xbm_ptr->write_date,
5710             xbm_ptr->filename) == EOF) {
5711          writeFileFailed = TRUE;
5712       }
5713       break;
5714    }
5715    if (xbm_ptr->save_epsf) {
5716       if (fprintf(FP, "%1d,[", xbm_ptr->num_epsf_lines) == EOF) {
5717          writeFileFailed = TRUE;
5718       }
5719       for (i = 0; i < xbm_ptr->num_epsf_lines; i++) {
5720          if (fprintf(FP, "\n    \"%s\"%s,", xbm_ptr->epsflines[i],
5721                (i==xbm_ptr->num_epsf_lines-1 ? "]" : "")) == EOF) {
5722             writeFileFailed = TRUE;
5723          }
5724       }
5725    }
5726    if (!no_bitmap) {
5727       if (fprintf(FP, "\n    \"") == EOF) writeFileFailed = TRUE;
5728       DumpXBmData(FP, xbm_ptr->bitmap, &(xbm_ptr->image), image_w, image_h);
5729       if (fprintf(FP, "\",") == EOF) writeFileFailed = TRUE;
5730    }
5731    if (ObjPtr->ctm != NULL && fprintf(FP,
5732          "[\n    %1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
5733          ObjPtr->x, ObjPtr->y,
5734          ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
5735          ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
5736          ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
5737          ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
5738          ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
5739       writeFileFailed = TRUE;
5740    }
5741    if (serializingFile) SaveCreatorID(FP, ObjPtr, "    ");
5742    SaveAttrs(FP, ObjPtr->lattr);
5743    if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
5744 }
5745 
5746 static
ReadTransformAndAdjustForXBm(FP,ObjPtr,xbm_ptr,transformed,rotate,flip)5747 int ReadTransformAndAdjustForXBm(FP, ObjPtr, xbm_ptr, transformed, rotate, flip)
5748    FILE *FP;
5749    struct ObjRec **ObjPtr;
5750    struct XBmRec *xbm_ptr;
5751    int transformed, rotate, flip;
5752 {
5753    if (fileVersion >= 33 && transformed) {
5754       char inbuf[MAXSTRING];
5755       struct XfrmMtrxRec *ctm=NULL;
5756       int real_x=0, real_y=0;
5757       struct BBRec orig_obbox;
5758 
5759       (void)fgets(inbuf, MAXSTRING, FP);
5760       scanLineNum++;
5761       InitScan(inbuf, "\t\n, ");
5762 
5763       ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
5764       if (ctm == NULL) FailAllocMessage();
5765       if (GETINT("xbitmap", real_x,           "real_x") == INVALID ||
5766           GETINT("xbitmap", real_y,           "real_y") == INVALID ||
5767           GETINT("xbitmap", orig_obbox.ltx,   "orig_obbox.ltx") == INVALID ||
5768           GETINT("xbitmap", orig_obbox.lty,   "orig_obbox.lty") == INVALID ||
5769           GETINT("xbitmap", orig_obbox.rbx,   "orig_obbox.rbx") == INVALID ||
5770           GETINT("xbitmap", orig_obbox.rby,   "orig_obbox.rby") == INVALID ||
5771           GETDBL("xbitmap", ctm->m[CTM_SX],   "CTM_SX") == INVALID ||
5772           GETDBL("xbitmap", ctm->m[CTM_SIN],  "CTM_SIN") == INVALID ||
5773           GETDBL("xbitmap", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
5774           GETDBL("xbitmap", ctm->m[CTM_SY],   "CTM_SY") == INVALID ||
5775           GETINT("xbitmap", ctm->t[CTM_TX],   "CTM_TX") == INVALID ||
5776           GETINT("xbitmap", ctm->t[CTM_TY],   "CTM_TY") == INVALID) {
5777          return FALSE;
5778       }
5779       (*ObjPtr)->ctm = ctm;
5780       if (ctm != NULL) {
5781          memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
5782          (*ObjPtr)->x = real_x;
5783          (*ObjPtr)->y = real_y;
5784          GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
5785       }
5786    }
5787    if (fileVersion < 33 && (rotate != ROTATE0 || flip != NO_FLIP)) {
5788       int ltx, lty, rbx, rby;
5789       double dz=(double)0, d1=(double)1000.0, dm1=((double)-1000.0);
5790 
5791       if (rotate == ROTATE90 || rotate == ROTATE270) {
5792          int h=(*ObjPtr)->obbox.rbx-(*ObjPtr)->obbox.ltx;
5793          int w=(*ObjPtr)->obbox.rby-(*ObjPtr)->obbox.lty;
5794 
5795          (*ObjPtr)->obbox.rby = (*ObjPtr)->obbox.lty + h;
5796          (*ObjPtr)->obbox.rbx = (*ObjPtr)->obbox.ltx + w;
5797       }
5798       ltx = ((*ObjPtr)->obbox.ltx); lty = ((*ObjPtr)->obbox.lty);
5799       rbx = ((*ObjPtr)->obbox.rbx); rby = ((*ObjPtr)->obbox.rby);
5800       SetRotatePivotByObject(*ObjPtr);
5801 
5802       if ((*ObjPtr)->ctm == NULL) {
5803          int image_w=0, image_h=0;
5804 
5805          if (xbm_ptr->bitmap == None) {
5806             image_w = xbm_ptr->eps_w;
5807             image_h = xbm_ptr->eps_h;
5808          } else {
5809             image_w = xbm_ptr->image_w;
5810             image_h = xbm_ptr->image_h;
5811          }
5812          if (image_w != rbx-ltx || image_h != rby-lty) {
5813             float fval=(float)0;
5814             double dx_scale=(double)0, dy_scale=(double)0;
5815             struct XfrmMtrxRec ctm;
5816 
5817             memset(&ctm, 0, sizeof(struct XfrmMtrxRec));
5818             fval = ((float)(rbx-ltx))/((float)image_w)*((float)1000.0);
5819             dx_scale = (double)fval;
5820             fval = ((float)(rby-lty))/((float)image_h)*((float)1000.0);
5821             dy_scale = (double)fval;
5822             (*ObjPtr)->obbox.rbx = ltx+image_w;
5823             (*ObjPtr)->obbox.rby = lty+image_h;
5824             ShearObj(*ObjPtr, CORNER_RB, dz, dz, dx_scale, dy_scale,
5825                   NULL, NULL);
5826          }
5827       }
5828       if (flip & HORI_EVEN) {
5829          ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1,
5830                &ltx, &lty);
5831       }
5832       if (flip & VERT_EVEN) {
5833          ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1,
5834                &ltx, &lty);
5835       }
5836       if (rotate == ROTATE0) {
5837          if (flip & (HORI_ODD | VERT_ODD)) {
5838             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5839             if (flip & HORI_ODD) {
5840                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1,
5841                      &ltx, &lty);
5842             }
5843             if (flip & VERT_ODD) {
5844                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1,
5845                      &ltx, &lty);
5846             }
5847             RotateObj(*ObjPtr, CORNER_LT, COUNTER90, &ltx, &lty);
5848          }
5849       } else {
5850          switch (rotate) {
5851          case ROTATE90:
5852             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5853             if (flip & HORI_ODD) {
5854                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1,
5855                      &ltx, &lty);
5856             }
5857             if (flip & VERT_ODD) {
5858                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1,
5859                      &ltx, &lty);
5860             }
5861             break;
5862          case ROTATE180:
5863             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5864             if (flip & HORI_ODD) {
5865                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1,
5866                      &ltx, &lty);
5867             }
5868             if (flip & VERT_ODD) {
5869                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1,
5870                      &ltx, &lty);
5871             }
5872             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5873             break;
5874          case ROTATE270:
5875             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5876             if (flip & HORI_ODD) {
5877                ShearObj(*ObjPtr, CORNER_LEFT, dz, dz, dm1, d1,
5878                      &ltx, &lty);
5879             }
5880             if (flip & VERT_ODD) {
5881                ShearObj(*ObjPtr, CORNER_TOP, dz, dz, d1, dm1,
5882                      &ltx, &lty);
5883             }
5884             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5885             RotateObj(*ObjPtr, CORNER_LT, CLOCKWISE90, &ltx, &lty);
5886             break;
5887          }
5888       }
5889       xbm_ptr->flip = NO_FLIP;
5890    }
5891    return TRUE;
5892 }
5893 
ReadXBmObj(FP,Inbuf,ObjPtr)5894 void ReadXBmObj(FP, Inbuf, ObjPtr)
5895    FILE *FP;
5896    char *Inbuf;
5897    struct ObjRec **ObjPtr;
5898 {
5899    struct XBmRec *xbm_ptr=NULL;
5900    char color_str[40], bg_color_str[40], *s, inbuf[MAXSTRING], *c_ptr;
5901    int ltx, lty, rbx, rby, i, j, k, data=0, color_index;
5902    int nibble_count, bit_count, num_nibbles, fill, trans_pat=FALSE;
5903    int rotation=0, new_alloc, id=0, image_w=0, image_h=0;
5904    int rotate=ROTATE0, flip=NO_FLIP, real_type=XBM_XBM, len;
5905    int no_bitmap=FALSE, llx=0, lly=0, urx=0, ury=0;
5906    int locked=FALSE, save_epsf=FALSE, compressed=FALSE;
5907    int num_epsf_lines=0, transform_read=FALSE;
5908    int transformed=FALSE, invisible=FALSE;
5909    Pixmap bitmap;
5910    char **epsflines=NULL;
5911    char *xbm_data, write_date[32], *filename;
5912    XImage *image;
5913 
5914    *ObjPtr = NULL;
5915 
5916    s = FindChar((int)'(', Inbuf);
5917    s = ParseStr(s, (int)',', color_str, sizeof(color_str));
5918    if (fileVersion >= 37) {
5919       s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str));
5920    }
5921    InitScan(s, "\t\n, ");
5922 
5923    if (fileVersion <= 8) {
5924       sprintf(inbuf, TgLoadCachedString(CSTID_INVALID_FILEVER_FOR_XBM),
5925             fileVersion);
5926       if (PRTGIF) {
5927          fprintf(stderr, "%s\n", inbuf);
5928       } else {
5929          Msg(inbuf);
5930       }
5931       return;
5932    } else if (fileVersion <= 13) {
5933       if (GETINT("xbitmap", ltx,      "ltx") == INVALID ||
5934           GETINT("xbitmap", lty,      "lty") == INVALID ||
5935           GETINT("xbitmap", rbx,      "rbx") == INVALID ||
5936           GETINT("xbitmap", rby,      "rby") == INVALID ||
5937           GETINT("xbitmap", fill,     "fill") == INVALID ||
5938           GETINT("xbitmap", id,       "id") == INVALID) {
5939          return;
5940       }
5941       if (id >= objId) objId = id+1;
5942    } else if (fileVersion <= 22) {
5943       if (GETINT("xbitmap", ltx,      "ltx") == INVALID ||
5944           GETINT("xbitmap", lty,      "lty") == INVALID ||
5945           GETINT("xbitmap", rbx,      "rbx") == INVALID ||
5946           GETINT("xbitmap", rby,      "rby") == INVALID ||
5947           GETINT("xbitmap", fill,     "fill") == INVALID ||
5948           GETINT("xbitmap", id,       "id") == INVALID ||
5949           GETINT("xbitmap", rotation, "rotation") == INVALID) {
5950          return;
5951       }
5952       if (id >= objId) objId = id+1;
5953    } else if (fileVersion <= 23) {
5954       if (GETINT("xbitmap", ltx,      "ltx") == INVALID ||
5955           GETINT("xbitmap", lty,      "lty") == INVALID ||
5956           GETINT("xbitmap", rbx,      "rbx") == INVALID ||
5957           GETINT("xbitmap", rby,      "rby") == INVALID ||
5958           GETINT("xbitmap", fill,     "fill") == INVALID ||
5959           GETINT("xbitmap", id,       "id") == INVALID ||
5960           GETINT("xbitmap", rotation, "rotation") == INVALID ||
5961           GETINT("xbitmap", image_w,  "image_w") == INVALID ||
5962           GETINT("xbitmap", image_h,  "image_h") == INVALID ||
5963           GETINT("xbitmap", rotate,   "rotate") == INVALID ||
5964           GETINT("xbitmap", flip,     "flip") == INVALID) {
5965          return;
5966       }
5967       if (id >= objId) objId = id+1;
5968    } else if (fileVersion <= 25) {
5969       if (GETINT("xbitmap", ltx,       "ltx") == INVALID ||
5970           GETINT("xbitmap", lty,       "lty") == INVALID ||
5971           GETINT("xbitmap", rbx,       "rbx") == INVALID ||
5972           GETINT("xbitmap", rby,       "rby") == INVALID ||
5973           GETINT("xbitmap", fill,      "fill") == INVALID ||
5974           GETINT("xbitmap", id,        "id") == INVALID ||
5975           GETINT("xbitmap", rotation,  "rotation") == INVALID ||
5976           GETINT("xbitmap", image_w,   "image_w") == INVALID ||
5977           GETINT("xbitmap", image_h,   "image_h") == INVALID ||
5978           GETINT("xbitmap", rotate,    "rotate") == INVALID ||
5979           GETINT("xbitmap", flip,      "flip") == INVALID ||
5980           GETINT("xbitmap", real_type, "real_type") == INVALID ||
5981           GETINT("xbitmap", llx,       "llx") == INVALID ||
5982           GETINT("xbitmap", lly,       "lly") == INVALID ||
5983           GETINT("xbitmap", urx,       "urx") == INVALID ||
5984           GETINT("xbitmap", ury,       "ury") == INVALID ||
5985           GETINT("xbitmap", no_bitmap, "no_bitmap") == INVALID) {
5986          return;
5987       }
5988       if (id >= objId) objId = id+1;
5989    } else if (fileVersion <= 28) {
5990       if (GETINT("xbitmap", ltx,       "ltx") == INVALID ||
5991           GETINT("xbitmap", lty,       "lty") == INVALID ||
5992           GETINT("xbitmap", rbx,       "rbx") == INVALID ||
5993           GETINT("xbitmap", rby,       "rby") == INVALID ||
5994           GETINT("xbitmap", fill,      "fill") == INVALID ||
5995           GETINT("xbitmap", id,        "id") == INVALID ||
5996           GETINT("xbitmap", rotation,  "rotation") == INVALID ||
5997           GETINT("xbitmap", image_w,   "image_w") == INVALID ||
5998           GETINT("xbitmap", image_h,   "image_h") == INVALID ||
5999           GETINT("xbitmap", rotate,    "rotate") == INVALID ||
6000           GETINT("xbitmap", flip,      "flip") == INVALID ||
6001           GETINT("xbitmap", real_type, "real_type") == INVALID ||
6002           GETINT("xbitmap", llx,       "llx") == INVALID ||
6003           GETINT("xbitmap", lly,       "lly") == INVALID ||
6004           GETINT("xbitmap", urx,       "urx") == INVALID ||
6005           GETINT("xbitmap", ury,       "ury") == INVALID ||
6006           GETINT("xbitmap", no_bitmap, "no_bitmap") == INVALID ||
6007           GETINT("xbitmap", locked,    "locked") == INVALID) {
6008          return;
6009       }
6010       if (id >= objId) objId = id+1;
6011    } else if (fileVersion <= 32) {
6012       if (GETINT("xbitmap", ltx,       "ltx") == INVALID ||
6013           GETINT("xbitmap", lty,       "lty") == INVALID ||
6014           GETINT("xbitmap", rbx,       "rbx") == INVALID ||
6015           GETINT("xbitmap", rby,       "rby") == INVALID ||
6016           GETINT("xbitmap", fill,      "fill") == INVALID ||
6017           GETINT("xbitmap", id,        "id") == INVALID ||
6018           GETINT("xbitmap", rotation,  "rotation") == INVALID ||
6019           GETINT("xbitmap", image_w,   "image_w") == INVALID ||
6020           GETINT("xbitmap", image_h,   "image_h") == INVALID ||
6021           GETINT("xbitmap", rotate,    "rotate") == INVALID ||
6022           GETINT("xbitmap", flip,      "flip") == INVALID ||
6023           GETINT("xbitmap", real_type, "real_type") == INVALID ||
6024           GETINT("xbitmap", llx,       "llx") == INVALID ||
6025           GETINT("xbitmap", lly,       "lly") == INVALID ||
6026           GETINT("xbitmap", urx,       "urx") == INVALID ||
6027           GETINT("xbitmap", ury,       "ury") == INVALID ||
6028           GETINT("xbitmap", no_bitmap, "no_bitmap") == INVALID ||
6029           GETINT("xbitmap", locked,    "locked") == INVALID ||
6030           GETINT("xbitmap", save_epsf, "save_epsf") == INVALID) {
6031          return;
6032       }
6033       if (id >= objId) objId = id+1;
6034    } else if (fileVersion <= 34) {
6035       if (GETINT("xbitmap", ltx,         "ltx") == INVALID ||
6036           GETINT("xbitmap", lty,         "lty") == INVALID ||
6037           GETINT("xbitmap", rbx,         "rbx") == INVALID ||
6038           GETINT("xbitmap", rby,         "rby") == INVALID ||
6039           GETINT("xbitmap", fill,        "fill") == INVALID ||
6040           GETINT("xbitmap", id,          "id") == INVALID ||
6041           GETINT("xbitmap", rotation,    "rotation") == INVALID ||
6042           GETINT("xbitmap", image_w,     "image_w") == INVALID ||
6043           GETINT("xbitmap", image_h,     "image_h") == INVALID ||
6044           GETINT("xbitmap", rotate,      "rotate") == INVALID ||
6045           GETINT("xbitmap", flip,        "flip") == INVALID ||
6046           GETINT("xbitmap", real_type,   "real_type") == INVALID ||
6047           GETINT("xbitmap", llx,         "llx") == INVALID ||
6048           GETINT("xbitmap", lly,         "lly") == INVALID ||
6049           GETINT("xbitmap", urx,         "urx") == INVALID ||
6050           GETINT("xbitmap", ury,         "ury") == INVALID ||
6051           GETINT("xbitmap", no_bitmap,   "no_bitmap") == INVALID ||
6052           GETINT("xbitmap", locked,      "locked") == INVALID ||
6053           GETINT("xbitmap", save_epsf,   "save_epsf") == INVALID ||
6054           GETINT("xbitmap", compressed,  "compressed") == INVALID ||
6055           GETINT("xbitmap", transformed, "transformed") == INVALID ||
6056           GETINT("xbitmap", invisible,   "invisible") == INVALID) {
6057          return;
6058       }
6059       if (id >= objId) objId = id+1;
6060    } else {
6061       if (GETINT("xbitmap", ltx,         "ltx") == INVALID ||
6062           GETINT("xbitmap", lty,         "lty") == INVALID ||
6063           GETINT("xbitmap", rbx,         "rbx") == INVALID ||
6064           GETINT("xbitmap", rby,         "rby") == INVALID ||
6065           GETINT("xbitmap", fill,        "fill") == INVALID ||
6066           GETINT("xbitmap", id,          "id") == INVALID ||
6067           GETINT("xbitmap", rotation,    "rotation") == INVALID ||
6068           GETINT("xbitmap", image_w,     "image_w") == INVALID ||
6069           GETINT("xbitmap", image_h,     "image_h") == INVALID ||
6070           GETINT("xbitmap", rotate,      "rotate") == INVALID ||
6071           GETINT("xbitmap", flip,        "flip") == INVALID ||
6072           GETINT("xbitmap", real_type,   "real_type") == INVALID ||
6073           GETINT("xbitmap", llx,         "llx") == INVALID ||
6074           GETINT("xbitmap", lly,         "lly") == INVALID ||
6075           GETINT("xbitmap", urx,         "urx") == INVALID ||
6076           GETINT("xbitmap", ury,         "ury") == INVALID ||
6077           GETINT("xbitmap", no_bitmap,   "no_bitmap") == INVALID ||
6078           GETINT("xbitmap", locked,      "locked") == INVALID ||
6079           GETINT("xbitmap", save_epsf,   "save_epsf") == INVALID ||
6080           GETINT("xbitmap", compressed,  "compressed") == INVALID ||
6081           GETINT("xbitmap", transformed, "transformed") == INVALID ||
6082           GETINT("xbitmap", invisible,   "invisible") == INVALID ||
6083           GETINT("xbitmap", trans_pat,   "trans_pat") == INVALID) {
6084          return;
6085       }
6086       if (id >= objId) objId = id+1;
6087    }
6088    if (fileVersion <= 22) {
6089       image_w = rbx-ltx;
6090       image_h = rby-lty;
6091       rotate = ROTATE0;
6092       flip = 0;
6093    }
6094    if (fileVersion >= 24) {
6095       char *tmp_str, *s, *s1;
6096 
6097       (void)fgets(inbuf, MAXSTRING, FP);
6098       scanLineNum++;
6099 
6100       tmp_str = FindChar((int)'"', inbuf);
6101       s = s1 = ReadString(tmp_str);
6102       s1++;
6103       *(--s) = '\0';
6104       len = strlen(tmp_str);
6105       if (len > 24) {
6106          (void)sprintf(gszMsgBox,
6107                TgLoadCachedString(CSTID_FIELD_TOO_LONG_IN_OBJ_TRUNC),
6108                scanFileName, scanLineNum, "write_date", "xbm");
6109          if (PRTGIF) {
6110             fprintf(stderr, "%s\n", gszMsgBox);
6111          } else {
6112             Msg(gszMsgBox);
6113          }
6114          tmp_str[23] = '\0';
6115       }
6116       strcpy(write_date, tmp_str);
6117 
6118       tmp_str = FindChar((int)'"', s1);
6119       s = ReadString(tmp_str);
6120       *(--s) = '\0';
6121       len = strlen(tmp_str);
6122       filename = (char*)malloc((len+1)*sizeof(char));
6123       if (filename == NULL) FailAllocMessage();
6124       strcpy(filename, tmp_str);
6125       if (save_epsf) {
6126          if (sscanf(&s[2], "%d", &num_epsf_lines) != 1) {
6127             sprintf(gszMsgBox,
6128                   TgLoadCachedString(CSTID_FILE_LINE_BAD_FLD_IN_OBJ_STR),
6129                   scanFileName, scanLineNum, "num_epsf_lines", "xbm", &s[2]);
6130             if (PRTGIF) {
6131                fprintf(stderr, "%s\n", gszMsgBox);
6132             } else {
6133                Msg(gszMsgBox);
6134             }
6135             return;
6136          }
6137          epsflines = (char**)malloc(num_epsf_lines*sizeof(char*));
6138          if (epsflines == NULL) FailAllocMessage();
6139          for (i=0; i < num_epsf_lines; i++) {
6140             if (fgets(inbuf, MAXSTRING, FP) == NULL) {
6141                sprintf(gszMsgBox,
6142                      TgLoadString(STID_UNEXPECTED_EOF_IN_ABORT_READ),
6143                      scanLineNum, scanFileName, "ReadXBmObj()");
6144                if (PRTGIF) {
6145                   fprintf(stderr, "%s\n", gszMsgBox);
6146                } else {
6147                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6148                }
6149                return;
6150             }
6151             scanLineNum++;
6152             len = strlen(inbuf);
6153             if ((c_ptr=strchr(inbuf, '"')) == NULL) {
6154                sprintf(gszMsgBox,
6155                      TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
6156                      scanLineNum, scanFileName);
6157                if (PRTGIF) {
6158                   fprintf(stderr, "%s\n", gszMsgBox);
6159                } else {
6160                   Msg(gszMsgBox);
6161                }
6162                return;
6163             }
6164             c_ptr++;
6165             len -= (c_ptr-inbuf);
6166             if (c_ptr[len-1] != '\n') {
6167                int cur_size=2*MAXSTRING-1, done=FALSE;
6168                char *line=(char*)malloc((cur_size+1)*sizeof(char));
6169 
6170                if (line == NULL) FailAllocMessage();
6171                strcpy(line, c_ptr);
6172                c_ptr = &(line[len]);
6173 
6174                while (!done && fgets(inbuf, MAXSTRING, FP) != NULL) {
6175                   len = strlen(inbuf);
6176                   if (inbuf[len-1] == '\r' || inbuf[len-1] == '\n') {
6177                      done = TRUE;
6178                      inbuf[len-1] = '\0';
6179                      strcpy(c_ptr, inbuf);
6180                   } else {
6181                      int n=c_ptr-line;
6182 
6183                      cur_size += MAXSTRING-1;
6184                      line = (char*)realloc(line, cur_size+1);
6185                      c_ptr = line + n;
6186                      strcpy(c_ptr, inbuf);
6187                      c_ptr += MAXSTRING-1;
6188                   }
6189                }
6190                if (!done) {
6191                   sprintf(gszMsgBox,
6192                         TgLoadString(STID_UNEXPECTED_EOF_IN_ABORT_READ),
6193                         scanLineNum, scanFileName, "ReadXBmObj()");
6194                   if (PRTGIF) {
6195                      fprintf(stderr, "%s\n", gszMsgBox);
6196                   } else {
6197                      MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6198                   }
6199                   return;
6200                }
6201                epsflines[i] = line;
6202                len = strlen(line);
6203             } else {
6204                c_ptr[--len] = '\0';
6205                epsflines[i] = (char*)malloc((len+1)*sizeof(char));
6206                if (epsflines[i] == NULL) FailAllocMessage();
6207                strncpy(epsflines[i], c_ptr, len);
6208                epsflines[i][len] = '\0';
6209             }
6210             for (c_ptr=(&(epsflines[i])[len]); c_ptr != epsflines[i] &&
6211                   *c_ptr != '"'; c_ptr--) ;
6212             if (*c_ptr != '"') {
6213                sprintf(gszMsgBox,
6214                      TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
6215                      scanLineNum, scanFileName);
6216                if (PRTGIF) {
6217                   fprintf(stderr, "%s\n", gszMsgBox);
6218                } else {
6219                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6220                }
6221                return;
6222             }
6223             *c_ptr = '\0';
6224          }
6225       }
6226    } else {
6227       *write_date = '\0';
6228       filename = NULL;
6229    }
6230    fill = UpgradePenFill(fill);
6231 
6232    *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
6233    if (*ObjPtr == NULL) FailAllocMessage();
6234    memset(*ObjPtr, 0, sizeof(struct ObjRec));
6235    xbm_ptr = (struct XBmRec *)malloc(sizeof(struct XBmRec));
6236    if (xbm_ptr == NULL) FailAllocMessage();
6237    memset(xbm_ptr, 0, sizeof(struct XBmRec));
6238 
6239    color_index = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE);
6240 
6241    (*ObjPtr)->color = color_index;
6242    if (mainDisplay != NULL) {
6243       UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str),
6244             colorMenuItems[color_index]);
6245    }
6246    (*ObjPtr)->dirty = FALSE;
6247    (*ObjPtr)->id = id;
6248    (*ObjPtr)->rotation = rotation;
6249    (*ObjPtr)->locked = locked;
6250    (*ObjPtr)->type = OBJ_XBM;
6251    (*ObjPtr)->obbox.ltx = (*ObjPtr)->bbox.ltx = (*ObjPtr)->x = ltx;
6252    (*ObjPtr)->obbox.lty = (*ObjPtr)->bbox.lty = (*ObjPtr)->y = lty;
6253    (*ObjPtr)->obbox.rbx = (*ObjPtr)->bbox.rbx = rbx;
6254    (*ObjPtr)->obbox.rby = (*ObjPtr)->bbox.rby = rby;
6255    (*ObjPtr)->detail.xbm = xbm_ptr;
6256    (*ObjPtr)->ctm = NULL;
6257    (*ObjPtr)->invisible = invisible;
6258    (*ObjPtr)->trans_pat = trans_pat;
6259 
6260    xbm_ptr->bitmap = None;
6261    xbm_ptr->image = NULL;
6262    xbm_ptr->cached_bitmap = None;
6263    xbm_ptr->cached_zoom = 0;
6264    xbm_ptr->data = NULL;
6265    xbm_ptr->fill = fill;
6266    xbm_ptr->flip = flip;
6267    xbm_ptr->cached_flip = 0;
6268    xbm_ptr->cached_w = xbm_ptr->cached_h = 0;
6269    xbm_ptr->image_w = image_w;
6270    xbm_ptr->image_h = image_h;
6271    xbm_ptr->llx = llx; xbm_ptr->lly = lly;
6272    xbm_ptr->urx = urx; xbm_ptr->ury = ury;
6273 
6274    xbm_ptr->real_type = real_type;
6275    strcpy(xbm_ptr->write_date, write_date);
6276    xbm_ptr->filename = filename;
6277    xbm_ptr->epsflines = epsflines;
6278    xbm_ptr->num_epsf_lines = num_epsf_lines;
6279    xbm_ptr->save_epsf = save_epsf;
6280 
6281    if (no_bitmap && xbm_ptr->real_type==XBM_EPS) {
6282       float file_llx=0.0, file_lly=0.0, file_urx=0.0, file_ury=0.0;
6283 
6284       xbm_ptr->eps_w = xbm_ptr->image_w;
6285       xbm_ptr->eps_h = xbm_ptr->image_h;
6286       xbm_ptr->image_w = 0;
6287       xbm_ptr->image_h = 0;
6288 
6289       if (!(PRTGIF && !cmdLineOpenDisplay)) {
6290          transform_read = TRUE;
6291          if (!ReadTransformAndAdjustForXBm(FP, ObjPtr, xbm_ptr, transformed,
6292                rotate, flip)) {
6293             return;
6294          }
6295          if (MyReadEPSFile(xbm_ptr->filename, &image_w,  &image_h,
6296                &(xbm_ptr->bitmap), &(xbm_ptr->image),
6297                (save_epsf ? &(xbm_ptr->num_epsf_lines) : NULL),
6298                (save_epsf ? &(xbm_ptr->epsflines) : NULL),
6299                &(xbm_ptr->epsf_level), &file_llx, &file_lly, &file_urx,
6300                &file_ury, xbm_ptr->write_date) != BitmapSuccess) {
6301             return;
6302          } else if (xbm_ptr->bitmap == None) {
6303             xbm_ptr->eps_w = (file_urx >= file_llx) ?
6304                   (int)(file_urx-file_llx) : (int)(file_llx-file_urx);
6305             xbm_ptr->eps_h = (file_ury >= file_lly) ?
6306                   (int)(file_ury-file_lly) : (int)(file_lly-file_ury);
6307          } else {
6308             xbm_ptr->image_w = image_w;
6309             xbm_ptr->image_h = image_h;
6310             /* same as above! */
6311             xbm_ptr->eps_w = (file_urx >= file_llx) ?
6312                   (int)(file_urx-file_llx) : (int)(file_llx-file_urx);
6313             xbm_ptr->eps_h = (file_ury >= file_lly) ?
6314                   (int)(file_ury-file_lly) : (int)(file_lly-file_ury);
6315          }
6316          xbm_ptr->llx = (int)(file_llx*1000.0);
6317          xbm_ptr->lly = (int)(file_lly*1000.0);
6318          xbm_ptr->urx = (int)(file_urx*1000.0);
6319          xbm_ptr->ury = (int)(file_ury*1000.0);
6320       }
6321    } else {
6322       if (xbm_ptr->real_type == XBM_EPS) {
6323          float file_llx=((float)xbm_ptr->llx)/1000.0;
6324          float file_lly=((float)xbm_ptr->lly)/1000.0;
6325          float file_urx=((float)xbm_ptr->urx)/1000.0;
6326          float file_ury=((float)xbm_ptr->ury)/1000.0;
6327 
6328          /* same as above! */
6329          xbm_ptr->eps_w = (file_urx >= file_llx) ?
6330                (int)(file_urx-file_llx) : (int)(file_llx-file_urx);
6331          xbm_ptr->eps_h = (file_ury >= file_lly) ?
6332                (int)(file_ury-file_lly) : (int)(file_lly-file_ury);
6333       } else {
6334          xbm_ptr->eps_w = xbm_ptr->eps_h = 0;
6335       }
6336       num_nibbles = ((image_w % 4) == 0) ? (int)(image_w>>2) :
6337             (int)(image_w>>2)+1;
6338 
6339       (void)fgets(inbuf, MAXSTRING, FP);
6340       scanLineNum++;
6341       c_ptr = &inbuf[5];
6342       nibble_count = 0;
6343 
6344       if (PRTGIF && !cmdLineOpenDisplay) {
6345          xbm_data = (char*)malloc((image_h*num_nibbles)*sizeof(char));
6346          if (xbm_data == NULL) FailAllocMessage();
6347          for (i = 0; i < image_h; i++) {
6348             for (j = 0; j < num_nibbles; j++) {
6349                if (nibble_count++ == 64) {
6350                   (void)fgets(inbuf, MAXSTRING, FP);
6351                   scanLineNum++;
6352                   c_ptr = &inbuf[5];
6353                   nibble_count = 1;
6354                }
6355                xbm_data[i*num_nibbles+j] = *c_ptr++;
6356             }
6357          }
6358          xbm_ptr->data = xbm_data;
6359       } else {
6360          bitmap = XCreatePixmap(mainDisplay, dummyBitmap, image_w, image_h, 1);
6361          XFillRectangle(mainDisplay, bitmap, xbmGC, 0, 0, image_w, image_h);
6362          image = XGetImage(mainDisplay,bitmap,0,0,image_w,image_h,1,ZPixmap);
6363 
6364          for (i = 0; i < image_h; i++) {
6365             bit_count = 0;
6366             for (j = 0; j < num_nibbles; j++) {
6367                if (nibble_count++ == 64) {
6368                   (void)fgets(inbuf, MAXSTRING, FP);
6369                   scanLineNum++;
6370                   c_ptr = &inbuf[5];
6371                   nibble_count = 1;
6372                }
6373                if (*c_ptr >= '0' && *c_ptr <= '9') {
6374                   data = (int)(*c_ptr++) - (int)('0');
6375                } else if (*c_ptr >= 'a' && *c_ptr <= 'f') {
6376                   data = (int)(*c_ptr++) - (int)('a') + 10;
6377                }
6378                for (k = 0; k < 4; k++) {
6379                   if (bit_count++ == image_w) break;
6380 
6381                   if (data & (1<<(3-k))) {
6382                      XPutPixel(image, j*4+k, i, 1);
6383                   }
6384                }
6385             }
6386          }
6387          XPutImage(mainDisplay,bitmap,xbmGC,image,0,0,0,0,image_w,image_h);
6388          xbm_ptr->bitmap = bitmap;
6389          xbm_ptr->image = image;
6390       }
6391    }
6392    if (!transform_read && !ReadTransformAndAdjustForXBm(FP, ObjPtr, xbm_ptr,
6393          transformed, rotate, flip)) {
6394       return;
6395    }
6396    if (!transform_read && (!(PRTGIF && !cmdLineOpenDisplay)) &&
6397          (*ObjPtr)->ctm == NULL) {
6398       struct BBRec orig_obbox;
6399 
6400       SetBBRec(&orig_obbox, ltx, lty, rbx, rby);
6401       SetEPSObjCTM(*ObjPtr, &orig_obbox);
6402    }
6403 }
6404 
SetXBmPropMask(ObjPtr,plMask,plSkip,pProp)6405 void SetXBmPropMask(ObjPtr, plMask, plSkip, pProp)
6406    struct ObjRec *ObjPtr;
6407    long *plMask, *plSkip;
6408    struct PropertiesRec *pProp;
6409 {
6410    struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
6411 
6412    SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
6413 
6414    if (xbm_ptr->real_type != XBM_EPS) {
6415       SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
6416             colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
6417    }
6418 }
6419 
FreeXBmObj(ObjPtr)6420 void FreeXBmObj(ObjPtr)
6421    struct ObjRec *ObjPtr;
6422 {
6423    register struct XBmRec *xbm_ptr=ObjPtr->detail.xbm;
6424    register int i;
6425 
6426    if (xbm_ptr->bitmap != None) XFreePixmap(mainDisplay, xbm_ptr->bitmap);
6427    if (xbm_ptr->image != NULL) XDestroyImage(xbm_ptr->image);
6428    if (xbm_ptr->cached_bitmap != None) {
6429       XFreePixmap(mainDisplay, xbm_ptr->cached_bitmap);
6430    }
6431    xbm_ptr->bitmap = None;
6432    xbm_ptr->image = NULL;
6433    xbm_ptr->cached_bitmap = None;
6434    xbm_ptr->cached_zoom = 0;
6435    if (xbm_ptr->data != NULL) free(xbm_ptr->data);
6436    if (xbm_ptr->filename != NULL) free(xbm_ptr->filename);
6437    if (xbm_ptr->real_type == XBM_EPS) {
6438       for (i = 0; i < xbm_ptr->num_epsf_lines; i++) {
6439          if (xbm_ptr->epsflines[i] != NULL) {
6440             free(xbm_ptr->epsflines[i]);
6441          }
6442       }
6443       if (xbm_ptr->epsflines != NULL) free(xbm_ptr->epsflines);
6444    }
6445    free(xbm_ptr);
6446    free(ObjPtr);
6447 }
6448