8206fb941da561129c2fd37eebf6d90adb2ad82d
[oweals/cde.git] / cde / programs / dticon / fileIO.c
1 /* $XConsortium: fileIO.c /main/8 1996/10/21 17:31:11 mgreess $ */
2 /*********************************************************************
3 *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4 *  (c) Copyright 1993, 1994 International Business Machines Corp.
5 *  (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
6 *  (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
7 *      Novell, Inc.
8 **********************************************************************/
9 /******************************************************************************
10  **  Program:           dticon
11  **
12  **  Description:       X11-based multi-color icon editor
13  **
14  **  File:              fileIO.c, which contains the following subroutines or
15  **                     functions:
16  **                       Do_FileIO()
17  **                       Read_File()
18  **                       Write_File()
19  **                       Display_XPMFile()
20  **                       Display_XBMFile()
21  **                       Dump_AttribStruct()
22  **
23  ******************************************************************************
24  **
25  **  Copyright Hewlett-Packard Company, 1990, 1991, 1992.
26  **  All rights are reserved.  Copying or reproduction of this program,
27  **  except for archival purposes, is prohibited without prior written
28  **  consent of Hewlett-Packard Company.
29  **
30  **  Hewlett-Packard makes no representations about the suitibility of this
31  **  software for any purpose.  It is provided "as is" without express or
32  **  implied warranty.
33  **
34  ******************************************************************************/
35 #ifdef __osf__
36 #include <stdlib.h>   /* for getenv() function prototype */
37 #endif
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <Xm/Xm.h>
41 #include <Xm/TextF.h>
42 #include <Xm/FileSB.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include "externals.h"
46 #include "main.h"
47
48 #ifdef __TOOLTALK
49 #include <Tt/tttk.h>
50 extern void ReplyToMessage( );
51 extern Tt_message replyMsg;
52 #endif
53
54 extern XtPointer _XmStringUngenerate (
55                                 XmString string,
56                                 XmStringTag tag,
57                                 XmTextType tag_type,
58                                 XmTextType output_type);
59
60 extern Widget   formatMenu_xpm_tb, formatMenu_xbm_tb;
61 extern Window tablet_win;
62 extern Widget editMenu_deleteHS_pb;
63 Boolean Read_File(), Write_File();
64 Pixmap pix_ret, shape_ret, mask_ret;
65 int successFormat, x_hot, y_hot;
66 unsigned int width_ret, height_ret;
67 extern GC scratch_gc;
68
69 extern void PixelTableClear();
70 extern int PixelTableLookup();
71 extern void send_tt_saved();
72 extern void Display_XPMFile(int, int);
73 extern void Display_XBMFile(int, int);
74
75
76 char  *tmpSave;            /* Save the file path being saved */
77 char  dummy[256];           /* mask file for use in main */
78 extern int SaveMeNot;
79 extern int SavedOnce;
80
81 /***************************************************************************
82  *                                                                         *
83  * Routine:   Do_FileIO                                                    *
84  *                                                                         *
85  * Purpose:   To read/write the current icon from/to the filename          *
86  *            selected in the file selection box.                          *
87  *                                                                         *
88  *            If fileIOMode is FILE_READ, this file should be read in.     *
89  *            If the read attempt fails, an error dialog pops up to        *
90  *            inform the user.                                             *
91  *                                                                         *
92  *            If fileIOMode is FILE_WRITE, the currently loaded icon       *
93  *            should be written to the named file, using the current file  *
94  *            format (specified by 'fileFormat').  As with FILE_READ, if   *
95  *            the write attempt fails, an error dialog pops up to inform   *
96  *            the user.                                                    *
97  *                                                                         *
98  ***************************************************************************/
99
100 void
101 Do_FileIO(
102         Widget wid,
103         XtPointer client_unused,
104         XmFileSelectionBoxCallbackStruct *callback_data )
105 {
106   int   unmanageFileIO = True;
107   struct stat statbuf;        /* Information on a file. */
108
109 #ifdef DEBUG
110   if (debug)
111     stat_out("Entering Do_FileIO\n");
112 #endif
113   pix_ret = NULL;
114   shape_ret = NULL;
115   mask_ret = NULL;
116
117   /* get file name */
118   if (SaveMeNot){
119   tmpSave = (char *) _XmStringUngenerate(
120                                         callback_data->value, NULL,
121                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
122   }
123
124   if (fileIOMode == FILE_READ) {
125     if (!Read_File(tmpSave))
126     {
127       unmanageFileIO = False;
128       DoErrorDialog( (GETSTR(16,2, "The file cannot be accessed\nor contains invalid data")) );
129     }
130     else {
131       if (successFormat == FORMAT_XPM) {
132         X_Hot = xpm_ReadAttribs.x_hotspot;
133         Y_Hot = xpm_ReadAttribs.y_hotspot;
134         Display_XPMFile(xpm_ReadAttribs.width, xpm_ReadAttribs.height);
135        }
136       else if (successFormat == FORMAT_XBM) {
137         X_Hot = x_hot;
138         Y_Hot = y_hot;
139         Display_XBMFile(width_ret, height_ret);
140        }
141       Dirty = False;
142       SavedOnce = True;   /* Implicitly saved, since we loaded the file */
143       /*
144          Turn off the HotSpot thing in the File menu.
145       */
146       if ( X_Hot == -1 )
147         XtSetSensitive((Widget) editMenu_deleteHS_pb, False );
148
149       if (unmanageFileIO)
150          XtUnmanageChild(fileIODialog);
151     } /* else */
152   } /* if(FileIOMode...) */
153
154   if (fileIOMode == FILE_WRITE) {
155     if (stat(tmpSave, &statbuf) == 0 && SaveMeNot)
156     {
157       DialogFlag=SAVE_AS;
158       DoQueryDialog( GETSTR(16,25, "File already exists.\n\nOK to overwrite the file?") );
159     }
160     else
161     {
162       if (!Write_File(tmpSave))
163       {
164         unmanageFileIO = False;
165         DoErrorDialog( (GETSTR(16,4, "Unable to write data to file")) );
166       }
167       else{
168           if (!SaveMeNot)
169               SaveMeNot = True;
170           Dirty = False;
171           SavedOnce = True;
172           if (unmanageFileIO)
173              XtUnmanageChild(fileIODialog);
174       }
175     }
176   }
177
178 #ifdef DEBUG
179   if (debug)
180     stat_out("Leaving Do_FileIO\n");
181 #endif
182 }
183
184
185 /***************************************************************************
186  *                                                                         *
187  * Routine:   Read_File                                                    *
188  *                                                                         *
189  * Purpose:   To read the contents of the specified file and create either *
190  *            a multi-color icon (if the file is an XPM file) or a bi-     *
191  *            color icon (if the file is an XBM file).  Further, if the    *
192  *            file is an XBM file, attempt to find a matching mask file    *
193  *            and read it as well, using to result to determine which      *
194  *            pixels should be set to transparent.                         *
195  *                                                                         *
196  ***************************************************************************/
197
198 Boolean
199 Read_File(
200         char *fnameIn )
201 {
202   char *base_name, *suffix, fname[MAXPATHLEN+1], *tmp, *tmp2;
203   unsigned int mask_width_ret, mask_height_ret;
204   int mask_x_hot, mask_y_hot, first;
205   struct stat statBuf;
206
207 #ifdef DEBUG
208   if (debug)
209     stat_out("Entering Read_File\n");
210 #endif
211
212   if ( !fnameIn || !(*fnameIn) )
213     return False;
214
215   tmp  = strchr(fnameIn, ':');
216   tmp2 = strchr(fnameIn, '/');
217
218   /*** - convert from "<host>:/..." to a path on the locale host. ***/
219   if (tmp && tmp2 && (tmp2 == tmp+1))
220   {
221     char        *netfile, *localfile;
222     
223     tmp[0] = '\0';
224     netfile = tt_host_file_netfile(fnameIn, tmp+1);
225     localfile = tt_netfile_file(netfile);
226
227     strncpy(fname, localfile, MAXPATHLEN);
228     tmp[0] = ':';
229
230     tt_free(netfile);
231     tt_free(localfile);
232   }
233   else     /* wasn't in form "<host>:/<path>" so use name as is... */
234   {
235     strcpy(fname, fnameIn);
236   }
237
238   /*** - if we got a NULL base_name, return FALSE             ***/
239   base_name = strrchr(fname, '/');
240   if (fname)
241     base_name = (base_name ? base_name + 1 : fname);
242   if (!base_name)
243     return (False);
244
245   /*** - if it's not a regular file, don't use it            ***/
246   if (stat(fname, &statBuf) == 0)                   /* success */
247   {
248     if ( (statBuf.st_mode & S_IFMT) == S_IFDIR ||
249          (statBuf.st_mode & S_IFMT) == S_IFCHR ||
250          (statBuf.st_mode & S_IFMT) == S_IFBLK )
251     {
252       return False;
253     }
254     if (statBuf.st_size == 0)
255     {
256       Process_Clear();
257       Process_Resize();
258       strcpy(last_fname, fname);
259       ChangeTitle();
260       successFormat = FORMAT_NONE;
261       return True;
262     }
263   }
264   else
265   {
266     return False;            /* file doesn't exist, return failure */
267   }
268
269
270 /*** before we do anything else, make sure ***/
271 /*** the editor interface refreshes itself ***/
272
273   XmUpdateDisplay(mainWindow);
274
275   pix_ret = NULL;
276   shape_ret = NULL;
277   mask_ret = NULL;
278   xpm_ReadAttribs.valuemask = READ_FLAGS;
279   xpm_ReadAttribs.colorsymbols = colorSymbols;
280   xpm_ReadAttribs.numsymbols = NUM_PENS;
281
282
283 /*** if the file ends in .pm or .xpm, try reading it as an ***/
284 /*** XPM file first.  Then try XBM format if XPM fails.    ***/
285 /***                                                       ***/
286 /*** if the file ends in .bm or .xbm, try reading it as an ***/
287 /*** XBM file first.  Then try XPM format if XBM fails.    ***/
288 /***                                                       ***/
289 /*** if the file doesn't match any of these suffixes, try  ***/
290 /*** reading it as an XPM file first.  Then try XBM format ***/
291 /*** if XPM fails.                                         ***/
292
293 /*** FIRST, does a suffix exist? ***/
294   suffix = strrchr(base_name, '.');
295   if ((suffix) && ((int)strlen(suffix) > 1))
296     suffix++;
297   if (suffix) {
298     if (!strcmp(suffix, "bm") || !strcmp(suffix, "xbm"))
299       first = FORMAT_XBM;
300     else
301       first = FORMAT_XPM;
302    }
303   else
304     first = FORMAT_XPM;
305
306 /*** try to read the XPM/XBM file, in the order ***/
307 /*** specified by the 'first' format.           ***/
308   if (first == FORMAT_XPM) {
309     status = _DtXpmReadFileToPixmap(dpy, tablet_win,
310                 fname, &pix_ret, &shape_ret, &xpm_ReadAttribs);
311
312 #ifdef DEBUG
313   if (debug) {
314     if (debug_image)
315       XDestroyImage(debug_image);
316     if (debug_shape)
317       XDestroyImage(debug_shape);
318     debug_status = _DtXpmReadFileToImage(dpy, fname,
319                 &debug_image, &debug_shape, &xpm_ReadAttribs);
320    }
321 #endif
322
323     if (status != XpmSuccess) {
324       status = XReadBitmapFile(dpy, tablet_win,
325                 fname, &width_ret, &height_ret, &pix_ret, &x_hot,
326                 &y_hot);
327       if (status != BitmapSuccess) {
328 #ifdef DEBUG
329   if (debug)
330     stat_out("Leaving Read_File - XPM/XBM read attempt failed.\n");
331 #endif
332         return (False);
333        }
334       else
335         successFormat = FORMAT_XBM;
336      }
337     else
338       successFormat = FORMAT_XPM;
339    }
340   else {
341     status = XReadBitmapFile(dpy, tablet_win, fname,
342                 &width_ret, &height_ret, &pix_ret, &x_hot, &y_hot);
343     if (status != BitmapSuccess) {
344       status = _DtXpmReadFileToPixmap(dpy, tablet_win,
345                 fname, &pix_ret, &shape_ret, &xpm_ReadAttribs);
346       if (status != XpmSuccess) {
347 #ifdef DEBUG
348   if (debug)
349     stat_out("Leaving Read_File - XBM/XPM read attempt failed.\n");
350 #endif
351         return (False);
352        }
353       else
354         successFormat = FORMAT_XPM;
355      }
356     else
357       successFormat = FORMAT_XBM;
358    }
359
360 /*** If we got this far, we successfully read in a file. ***/
361 /*** If the 'successFormat' is FORMAT_XBM, try to find   ***/
362 /*** and accompanying mask file and load it too.  The    ***/
363 /*** format for a mask file name is:                     ***/
364 /***     <pathname><base_name>_m<suffix> (optional suffix)***/
365   if (successFormat == FORMAT_XBM) {
366 /*** does a suffix exist? ***/
367     if (suffix) {
368       strncpy(dummy, fname, ((suffix-fname)-1));
369       dummy[(int) (suffix-fname)-1] = NULL;
370       strcat(dummy, "_m.");
371       strcat(dummy, suffix);
372 #ifdef DEBUG
373   if (debug) {
374     stat_out("  full-filename = '%s'\n", fname);
375     stat_out("  suffix = '%s'\n", suffix);
376    }
377 #endif
378      }
379     else {
380          strcpy(dummy, fname);
381          strcat(dummy, "_m");
382     }
383 #ifdef DEBUG
384   if (debug)
385     stat_out("  mask-file = '%s'\n", dummy);
386 #endif
387     status = XReadBitmapFile(dpy, tablet_win, dummy,
388                 &mask_width_ret, &mask_height_ret, &mask_ret,
389                 &mask_x_hot, &mask_y_hot);
390     if (status == BitmapSuccess) {
391       if ((width_ret != mask_width_ret) || (height_ret != mask_height_ret)) {
392         XFreePixmap(dpy, mask_ret);
393         mask_ret = NULL;
394        }
395      }
396     else
397       mask_ret = NULL;
398    }
399
400   strcpy(last_fname, fname);
401   ChangeTitle();
402
403 #ifdef DEBUG
404   if (debug) {
405     stat_out("Finished Reading file '%s'\n", last_fname);
406     stat_out("Leaving Read_File\n");
407    }
408 #endif
409
410   return (True);
411 }
412
413
414 /***************************************************************************
415  *                                                                         *
416  * Routine:   Write_File                                                   *
417  *                                                                         *
418  * Purpose:   To write the current icon to the specified filename as       *
419  *            either an XPM file or XBM file, depending on the current     *
420  *            value of the fileFormat flag.  Further, if the current       *
421  *            fileFormat is FORMAT_XBM, create a second XBM file which     *
422  *            contains a mask for the XBM file just written.               *
423  *                                                                         *
424  ***************************************************************************/
425 Boolean
426 Write_File(
427         char *fnameIn )
428 {
429   extern int tt_tmpfile_fd;
430   int i, j;
431   int mask_needed;
432   Boolean SUN;
433   char *base_name, *suffix, fname[256], *tmp, *tmp2, *vend;
434   Pixmap scratch_pix;
435   XImage *scratch_shape, *scratch_mask;
436   struct stat statbuf;        /* Information on a file. */
437
438
439 #ifdef DEBUG
440   if (debug)
441     stat_out("Entering Write_File\n");
442 #endif
443   SUN = False;   /* Assume machine other than SUN */
444   if ( !fnameIn || !(*fnameIn) )
445     return False;
446
447   tmp  = strchr(fnameIn, ':');
448   tmp2 = strchr(fnameIn, '/');
449
450   /*** - convert from "<host>:/..." to a path on the locale host. ***/
451   if (tmp && tmp2 && (tmp2 == tmp+1))
452   {
453     char        *netfile, *localfile;
454     
455     tmp[0] = '\0';
456     netfile = tt_host_file_netfile(fnameIn, tmp+1);
457     localfile = tt_netfile_file(netfile);
458
459     strncpy(fname, localfile, MAXPATHLEN);
460     tmp[0] = ':';
461
462     tt_free(netfile);
463     tt_free(localfile);
464   }
465   else     /* wasn't in form "<host>:/<path>" so use name as is... */
466   {
467     strcpy(fname, fnameIn);
468   }
469
470
471   base_name = strrchr(fname, '/');
472   if (fname) {
473     base_name = (base_name ? base_name + 1 : fname);
474   }
475
476   strcpy(last_fname, fname);
477   ChangeTitle();
478
479 #ifdef DEBUG
480   if (debug)
481     stat_out("Writing file '%s'\n", last_fname);
482 #endif
483
484   if (fileFormat == FORMAT_XPM) {
485     xpm_WriteAttribs.x_hotspot = X_Hot;
486     xpm_WriteAttribs.y_hotspot = Y_Hot;
487     xpm_WriteAttribs.width  = icon_width;
488     xpm_WriteAttribs.height = icon_height;
489     xpm_WriteAttribs.cpp    = 1;
490     xpm_WriteAttribs.colorsymbols = colorSymbols;
491     xpm_WriteAttribs.numsymbols = NUM_PENS;
492     xpm_WriteAttribs.ncolors = NUM_PENS;
493     xpm_WriteAttribs.valuemask = WRITE_FLAGS;
494 #ifdef DEBUG
495   if (debug)
496     Dump_AttribStruct(&xpm_WriteAttribs);
497 #endif
498     status = _DtXpmWriteFileFromPixmap(dpy, fname, color_icon, NULL,
499                                 &xpm_WriteAttribs);
500
501 /*******
502     status = _DtXpmWriteFileFromPixmap(dpy, fname, color_icon, NULL, NULL);
503 ********/
504     if (status != XpmSuccess) {
505 #ifdef DEBUG
506   if (debug) {
507     stat_out("Leaving Write_File - XPM write failed. ");
508     switch (status) {
509       case XpmOpenFailed : stat_out("(XpmOpenFailed)\n"); break;
510       case XpmNoMemory   : stat_out("(XpmNoMemory)\n"); break;
511       default            : stat_out("(UNKNOWN cause)\n"); break;
512     }
513   }
514 #endif
515       return (False);
516     }
517   }
518   else {
519 /*** FIRST, does a suffix exist? ***/
520   suffix = strrchr(base_name, '.');
521   if ((suffix) && ((int)strlen(suffix) > 1))
522     suffix++;
523 /*** SECOND, is it a valid suffix? ***/
524   if (suffix) {
525     if (strcmp(suffix, "bm") && strcmp(suffix, "xbm"))
526       suffix = NULL;
527   }
528 /*** THIRD, construct the mask filename ***/
529     if (suffix) {
530       strncpy(dummy, fname, ((suffix-fname)-1));
531       dummy[(int) (suffix-fname)-1] = NULL;
532       strcat(dummy, "_m.");
533       strcat(dummy, suffix);
534     }
535     else {
536       strcpy(dummy, fname);
537       strcat(dummy, "_m");
538     }
539 /*** FOURTH, construct XImages for the shape and mask bitmaps ***/
540     mask_needed = False;
541     scratch_shape = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height,
542                         AllPlanes, format);
543     scratch_mask = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height,
544                         AllPlanes, format);
545     if (!scratch_shape || !scratch_mask) {
546       if (scratch_shape)
547         XDestroyImage(scratch_shape);
548       if (scratch_mask)
549         XDestroyImage(scratch_mask);
550       return (False);
551     }
552
553     /* is this a SUN machine?                   */
554     /* if so use special code else use old code */
555     vend = ServerVendor(dpy);
556     if ( strncmp( vend, "Sun", 3) == 0) {
557        SUN = TRUE;
558        for (i=0; i<icon_width; i++)
559          for (j=0; j<icon_height; j++)
560            if (XGetPixel(scratch_shape, i, j) == Transparent) {
561             XPutPixel(scratch_shape, i, j,  white_pixel);
562             mask_needed = True;
563         }
564        for (i=0; i<icon_width; i++)
565          for (j=0; j<icon_height; j++)
566            if (XGetPixel(scratch_mask, i, j) != Transparent)
567              XPutPixel(scratch_mask, i, j,  black_pixel);
568            else
569              XPutPixel(scratch_mask, i, j,  white_pixel);
570     }else {
571        for (i=0; i<icon_width; i++)
572          for (j=0; j<icon_height; j++)
573           if (XGetPixel(scratch_shape, i, j) == Transparent) {
574             XPutPixel(scratch_shape, i, j,  black_pixel);
575             mask_needed = True;
576           }
577        for (i=0; i<icon_width; i++)
578          for (j=0; j<icon_height; j++)
579            if (XGetPixel(scratch_mask, i, j) != Transparent)
580              XPutPixel(scratch_mask, i, j,  white_pixel);
581            else
582              XPutPixel(scratch_mask, i, j,  black_pixel);
583     }
584
585
586 /*** FIFTH, write out the shape and mask bitmaps ***/
587     scratch_pix = XCreatePixmap(dpy, root, icon_width, icon_height,
588                                 DefaultDepth(dpy, screen));
589     if (!scratch_pix) {
590       if (scratch_shape)
591         XDestroyImage(scratch_shape);
592       if (scratch_mask)
593         XDestroyImage(scratch_mask);
594       return (False);
595     }
596     /* don't set GXcopyInverte for SUN machines */
597     if (!SUN)
598     XSetFunction(dpy, Mono_gc, GXcopyInverted);
599     XPutImage(dpy, scratch_pix, Mono_gc, scratch_shape, 0, 0, 0, 0,
600                         icon_width, icon_height);
601     XSetFunction(dpy, Mono_gc, GXcopy);
602     status = XWriteBitmapFile(dpy, fname, scratch_pix, icon_width, icon_height,
603                         X_Hot, Y_Hot);
604     if (status != BitmapSuccess)
605     {
606       XDestroyImage(scratch_shape);
607       XDestroyImage(scratch_mask);
608       XFreePixmap(dpy, scratch_pix);
609       return (False);
610     }
611     if (mask_needed) {
612       XPutImage(dpy, scratch_pix, Mono_gc, scratch_mask, 0, 0, 0, 0,
613                         icon_width, icon_height);
614       status = XWriteBitmapFile(dpy, dummy, scratch_pix, icon_width,
615                         icon_height, X_Hot, Y_Hot);
616       if (status != BitmapSuccess)
617       {
618         XDestroyImage(scratch_shape);
619         XDestroyImage(scratch_mask);
620         XFreePixmap(dpy, scratch_pix);
621         return (False);
622       }
623     } /***TAG***/
624     XFreePixmap(dpy, scratch_pix);
625     XDestroyImage(scratch_shape);
626     XDestroyImage(scratch_mask);
627   } /* else */
628
629   /* Don't know if this is needed....
630   if ( SUN )
631      {
632         SUN = False;
633         black_pixel = 0;
634         white_pixel = 1;
635      }
636   */
637
638 #ifdef DEBUG
639   if (debug)
640     stat_out("Leaving Write_File\n");
641 #endif
642     if( (fileFormat != FORMAT_XPM) && (!mask_needed) && (stat(tmpSave, &statbuf) == 0) )
643       unlink(dummy);
644 #ifdef __TOOLTALK
645     if (tt_tmpfile_fd != -1)
646        send_tt_saved();
647 #endif
648
649   return (True);
650 }
651
652 /***************************************************************************
653  *                                                                         *
654  * Routine:   Display_XPMFile                                              *
655  *                                                                         *
656  * Purpose:   Assuming that we have successfully read in an XPM file, use  *
657  *            the data from the file to render the proper rasters to the   *
658  *            color_icon and mono_icon (and their corresponding widgets).  *
659  *                                                                         *
660  *            Rendering the color icon is straight-forward, since the      *
661  *            pixmap generated by Read_File() is already correct.  For     *
662  *            the mono icon, we extract an XImage for the entire color     *
663  *            pixmap, and then convert each pixel individually to one      *
664  *            three values: black, white, or transparent.  For each pixel, *
665  *            the following test is performed: 1st) compare it to each     *
666  *            static color.  If a match is found, convert the pixel to     *
667  *            the appropriate mono equivalent.  2nd) if the 1st step fails *
668  *            to find a match, try the same comparisons against the        *
669  *            dynamic colors.  3rd) if the 2nd step also fails, use the    *
670  *            PixelTableLookup() function.                                 *
671  *                                                                         *
672  *            Once the coversion process is complete, both the color_icon  *
673  *            and mono_icon (and their corresponding widgets) can be       *
674  *            rendered.                                                    *
675  *                                                                         *
676  ***************************************************************************/
677
678 void
679 Display_XPMFile(
680         int width,
681         int height )
682 {
683   int converted, i, j, k;
684   int pixelTableIndex;
685   XImage *scratch_img, *mono_img, *mask_img;
686   Pixel cpixel, mpixel;
687 #ifdef DEBUG
688   int reset_debug;
689 #endif
690
691 #ifdef DEBUG
692   if (debug)
693     stat_out("Entering Display_XPMFile\n");
694   reset_debug=False;
695 #endif
696
697 /*** resize the color and mono icon windows, and the tablet ***/
698 /*** to their (new) correct height and width.               ***/
699   Init_Icons(width, height, DO_NOT_SAVE);
700
701 /*** Grab an image for both (potentially modified) ***/
702 /*** color and mono conversions                    ***/
703   scratch_img = XGetImage(dpy, pix_ret, 0, 0, width, height,
704                                 AllPlanes, format);
705   mono_img = XGetImage(dpy, pix_ret, 0, 0, width, height,
706                                 AllPlanes, format);
707   mask_img = NULL;
708   if (shape_ret)
709     mask_img = XGetImage(dpy, shape_ret, 0, 0, width, height,
710                                 AllPlanes, format);
711 #ifdef DEBUG
712   if (debug) {
713     debug = False;
714     reset_debug = True;
715    }
716 #endif
717   PixelTableClear;  /* force new pixel table now */
718   for (i=0; i<width; i++)
719     for (j=0; j<height; j++) {
720       converted = False;
721       cpixel = XGetPixel(scratch_img, i, j);
722       if (mask_img) {
723         mpixel = XGetPixel(mask_img, i, j);
724         if (!mpixel) {
725           cpixel = Transparent;
726           XPutPixel(scratch_img, i, j, cpixel);
727          }
728        } /* if(mask_img) */
729       for (k = 0; k < NUM_STATICS; k++)
730         if (cpixel == StaticPen[k]) {
731           XPutPixel(mono_img, i, j, StaticMono[k]);
732           converted = True;
733          } /* if(cpixel...) */
734       if (!converted) {
735         for (k = 0; k < NUM_DYNAMICS; k++)
736           if (cpixel == DynamicPen[k]) {
737             XPutPixel(mono_img, i, j, DynamicMono[k]);
738             converted = True;
739            } /* if(cpixel...) */
740        } /* if(!converted) */
741       if (!converted) {
742         pixelTableIndex = PixelTableLookup (cpixel, False);
743         XPutPixel(mono_img, i, j, PIXEL_TABLE_MONO(pixelTableIndex));
744        } /* if(!converted) */
745      } /* for(j...) */
746 #ifdef DEBUG
747   if (reset_debug) {
748     debug = True;
749     reset_debug = False;
750    }
751 #endif
752
753   XPutImage(dpy, color_icon, Color_gc, scratch_img,
754                 0, 0, 0, 0, width, height);
755   XPutImage(dpy, mono_icon, Mono_gc, mono_img,
756                 0, 0, 0, 0, width, height);
757
758 /*** this following stuff all gets done regardless ***/
759
760   XCopyArea(dpy, color_icon, XtWindow(iconImage),
761                 Color_gc, 0, 0, width, height, 0, 0);
762   XCopyArea(dpy, mono_icon, XtWindow(monoImage),
763                 Mono_gc, 0, 0, width, height, 0, 0);
764   icon_width = width;
765   icon_height = height;
766   fileFormat = FORMAT_XPM;
767   XmToggleButtonGadgetSetState(formatMenu_xpm_tb, True, True);
768 /* This line is not realy needed since an Exposed event will be generated */
769   Repaint_Exposed_Tablet();
770   XDestroyImage(scratch_img);
771   XFreePixmap(dpy, pix_ret);
772   if (shape_ret)
773     XFreePixmap(dpy, shape_ret);
774
775 #ifdef DEBUG
776   if (debug)
777     stat_out("Leaving Display_XPMFile\n");
778 #endif
779 }
780
781
782 /***************************************************************************
783  *                                                                         *
784  * Routine:   Display_XBMFile                                              *
785  *                                                                         *
786  * Purpose:   Assuming that we have successfully read in an X bitmap file  *
787  *            (and, potentially, a mask file as well), use the data from   *
788  *            the file(s) to render the proper rasters to the color_icon   *
789  *            and mono_icon (and their corresponding widgets).             *
790  *                                                                         *
791  *            Rendering the bitmap is straight-forward (create a scratch   *
792  *            pixmap of the correct depth and copy-plane the just-read     *
793  *            bitmap onto it).  If there is a mask bitmap as well, then    *
794  *            the scratch pixmap must be modified such that for every      *
795  *            0 bit in the mask bitmap, the corresponding pixel of the     *
796  *            scratch pixmap should be set to the Transparent pixel.       *
797  *            Once this is done, the scratch pixmap is copied to both      *
798  *            the color_icon and mono_icon (since, for bitmaps, they're    *
799  *            identical).  Then free the scratch pixmap.                   *
800  *                                                                         *
801  ***************************************************************************/
802
803 void
804 Display_XBMFile(
805         int width,
806         int height )
807 {
808   int i, j;
809   XImage *test_img, *scratch_img;
810   Pixmap scratch_pix;
811
812 #ifdef DEBUG
813   if (debug)
814     stat_out("Entering Display_XBMFile\n");
815 #endif
816
817   scratch_pix = XCreatePixmap(dpy, root, width, height,
818                                 DefaultDepth(dpy, screen));
819   Init_Icons(width, height, DO_NOT_SAVE);
820   XSetBackground(dpy, scratch_gc, white_pixel);
821   XFillRectangle(dpy, scratch_pix, scratch_gc, 0, 0, width, height);
822   XSetForeground(dpy, scratch_gc, black_pixel);
823   XCopyPlane(dpy, pix_ret, scratch_pix, scratch_gc, 0, 0,
824                 width, height, 0, 0, 1);
825   if (mask_ret) {
826     test_img = XGetImage(dpy, mask_ret, 0, 0, width, height,
827         AllPlanes, format);
828     scratch_img = XGetImage(dpy, scratch_pix, 0, 0, width, height,
829         AllPlanes, format);
830     for (i=0; i<width; i++)
831       for (j=0; j<height; j++)
832         if (!XGetPixel(test_img, i, j))
833           XPutPixel(scratch_img, i, j, Transparent);
834     XPutImage(dpy, scratch_pix, scratch_gc, scratch_img,
835                 0, 0, 0, 0, width, height);
836    } /* if(mask_ret) */
837   XCopyArea(dpy, scratch_pix, color_icon, Color_gc, 0, 0,
838                 width, height, 0, 0);
839   XCopyArea(dpy, scratch_pix, mono_icon, Mono_gc, 0, 0,
840                 width, height, 0, 0);
841   XCopyArea(dpy, color_icon, XtWindow(iconImage),
842                 Color_gc, 0, 0, width, height, 0, 0);
843   XCopyArea(dpy, mono_icon, XtWindow(monoImage),
844                 Mono_gc, 0, 0, width, height, 0, 0);
845   icon_width = width;
846   icon_height = height;
847   fileFormat = FORMAT_XBM;
848   XmToggleButtonGadgetSetState(formatMenu_xbm_tb, True, True);
849 /* This line is not realy needed since an Exposed event will be generated */
850   Repaint_Exposed_Tablet();
851   if (mask_ret) {
852     XDestroyImage(test_img);
853     XDestroyImage(scratch_img);
854    }
855   XFreePixmap(dpy, scratch_pix);
856   XFreePixmap(dpy, pix_ret);
857   if (mask_ret)
858     XFreePixmap(dpy, mask_ret);
859
860 #ifdef DEBUG
861   if (debug)
862     stat_out("Leaving Display_XBMFile\n");
863 #endif
864 }
865
866
867 /***************************************************************************
868  *                                                                         *
869  * Routine:   SetFileIODialogInfo                                          *
870  *                                                                         *
871  * Purpose:   Set FileIODialog information... title, path, etc.            *
872  *                                                                         *
873  ***************************************************************************/
874 void
875 SetFileIODialogInfo( void )
876 {
877   static int currentTitle = SAVE_AS;  /* initial title is for Save_As... */
878   static XmString saveTitle = NULL;
879   static XmString openTitle = NULL;
880   static XmString saveLabel = NULL;
881   static XmString openLabel = NULL;
882   static XmString OpenOKLabel = NULL;
883   static XmString SaveOKLabel = NULL;
884
885   static char *untitledStr = NULL;
886   static Widget textWidget = NULL;
887   static char newName[MAX_FNAME];
888   static char dirStr[MAX_FNAME];
889   static char tmpStr[MAX_FNAME];
890
891   Arg args[10];
892   int  n,dirlen=0,filelen=0,tst, ln;
893   char *strOrig = NULL;
894   XmString  tmpXmStr;
895   char tmp[MAX_FNAME];
896   char *tmp1= NULL;
897   char *tmp2= NULL;
898   int c;
899   int startSelect, endSelect;
900
901   if (DialogFlag == OPEN) /* Dialog is for File-Open menu item */
902   {
903     /* set title to "Icon Editor - Open File" if needed */
904       if (!openTitle)
905         openTitle = GETXMSTR(2,8,  "Icon Editor - Open File");
906       n = 0;
907       XtSetArg (args[n], XmNdialogTitle, openTitle);         n++;
908       XtSetValues (fileIODialog, args, n);
909       currentTitle = OPEN;
910
911       /* set selection label to "Open File" */
912       if (!openLabel)
913         openLabel = GETXMSTR(2,17,  "Enter file name:");
914       n = 0;
915       XtSetArg (args[n], XmNselectionLabelString, openLabel);         n++;
916       OpenOKLabel = GETXMSTR(2,22,  "Open");
917       XtSetArg (args[n], XmNokLabelString, OpenOKLabel);              n++;
918       XtSetValues (fileIODialog, args, n);
919   }
920   else  /* Dialog is for File-Save or File-Save_As menu item */
921   {
922     /* set title to "Icon Editor - Save As" if needed */
923       if (!saveTitle)
924         saveTitle = GETXMSTR(2,6,  "Icon Editor - Save As");
925       n = 0;
926       XtSetArg (args[n], XmNdialogTitle, saveTitle);         n++;
927       XtSetValues (fileIODialog, args, n);
928       currentTitle = SAVE_AS;
929
930       /* set selection label to "Enter file name:" */
931       if (!saveLabel)
932         saveLabel = GETXMSTR(2,16,  "Enter file name:");
933       n = 0;
934       XtSetArg (args[n], XmNselectionLabelString, saveLabel);         n++;
935       SaveOKLabel = GETXMSTR(2,24,  "Save");
936       XtSetArg (args[n], XmNokLabelString, SaveOKLabel);              n++;
937       XtSetValues (fileIODialog, args, n);
938   }
939     /*                                                  */
940     /* set string to "UNTITLED" with appropriate suffix */
941     /* when apropriate                                  */
942
943     if (!untitledStr)
944       untitledStr = GETSTR(2,20, "UNTITLED");
945     if (!textWidget)
946       textWidget = XmFileSelectionBoxGetChild(fileIODialog, XmDIALOG_TEXT);
947     strOrig = XmTextFieldGetString(textWidget);
948
949     dirStr[0] = '\0';
950     newName[0]='\0';
951     tmpStr[0]='\0';
952     startSelect = 0;
953
954     /* prepare to test */
955     tmp1 = strrchr(strOrig, '.');
956
957     strcat(tmpStr, untitledStr);
958     strcat(tmpStr, ".m.pm");
959     tst=strcmp(last_fname, tmpStr);
960
961     if ( tst==0 ) {/* untitled */
962        if ( tmp1 ) { /* previous string exists */
963           if (currentTitle != SAVE_AS) strcat(newName, strOrig);
964           else {
965                strcat(newName, untitledStr);
966                strcat(newName, ".m.pm");}
967                /* Update the FSB */
968                XmFileSelectionDoSearch(fileIODialog,(XmString)NULL);
969
970        }
971        else { /* First time arownd */
972           if (strOrig && strOrig[0]!='\0')
973              strcat(newName, strOrig);
974           else {
975              strcat(newName, untitledStr);
976              strcat(newName, ".m.pm");
977           }
978
979     XSync(dpy, 0);
980           /* rebuild last file name */
981           last_fname[0] = '\0';
982           strcpy(last_fname, dirStr);
983           strcat(last_fname, newName);
984        }
985     }
986     else { /* not untitled */
987          tmp1= strrchr(last_fname, '/');
988
989          /*
990           * Check if any '/' characters found
991           */
992          if (tmp1)
993          {
994              /*
995               * Strip path into directory name and file name
996               */
997              c = tmp1[1];
998              tmp2 = strchr(tmp1, c);
999              strcpy(newName, tmp2);
1000
1001              /* make and insert the directory name */
1002              ln = strlen(last_fname) - strlen(tmp1);
1003              strncpy(dirStr, last_fname, ln);
1004              dirStr[ln] = '\0';
1005          }
1006          else
1007          {
1008              /*
1009               * Path is a simple filename
1010               * Set filename to be path name
1011               * Set directory name = "."
1012               */
1013              strcpy(newName, last_fname);
1014              dirStr[0] = '.';
1015              dirStr[1] = '\0';
1016          }
1017
1018          tmpXmStr = XmStringCreateLocalized (dirStr);
1019          n = 0;
1020          XtSetArg (args[n], XmNdirectory, tmpXmStr);      n++;
1021          XtSetValues (fileIODialog, args, n);
1022          XmStringFree(tmpXmStr);
1023     }
1024      ln=0;
1025      /* set the Highlighted string */
1026      newName[strlen(newName)+1] ='\0';
1027      tmp1 = strchr(newName, '.');
1028      if (tmp1 && tmp1[0]!='\0') ln = (int)strlen(tmp1);
1029      endSelect = strlen(newName)- ln;
1030
1031     /* now set the text field and set selection for highlighted portion */
1032     XmTextFieldSetString(textWidget, newName);
1033     XmTextFieldSetSelection(textWidget, startSelect, endSelect, CurrentTime);
1034
1035     XSync(dpy, 0);
1036     XmProcessTraversal(textWidget, XmTRAVERSE_CURRENT);
1037     XSync(dpy, 0);
1038
1039     XtFree(strOrig);
1040
1041   /* if file lists are being used, re-scan the directory contents */
1042  /* if (xrdb.useFileLists)
1043     XmFileSelectionDoSearch(fileIODialog, NULL);*/
1044 }
1045
1046
1047
1048 #ifdef DEBUG
1049 /***************************************************************************
1050  *                                                                         *
1051  * Routine:   Dump_AttribStruct  #ifdef DEBUG only (for bba)               *
1052  *                                                                         *
1053  * Purpose:   Print out the entier contents of the XpmAttributes struct.   *
1054  *                                                                         *
1055  ***************************************************************************/
1056 int
1057 Dump_AttribStruct(
1058         XpmAttributes *xpma )
1059 {
1060   int i, j;
1061
1062   if (xpma->valuemask) {
1063     stat_out("  valuemask: (");
1064     if (xpma->valuemask & XpmVisual)
1065         stat_out("XpmVisual|");
1066     if (xpma->valuemask & XpmColormap)
1067         stat_out("XpmColormap|");
1068     if (xpma->valuemask & XpmDepth)
1069         stat_out("XpmDepth|");
1070     if (xpma->valuemask & XpmSize)
1071         stat_out("XpmSize|");
1072     if (xpma->valuemask & XpmHotspot)
1073         stat_out("XpmHotspot|");
1074     if (xpma->valuemask & XpmCharsPerPixel)
1075         stat_out("XpmCharsPerPixel|");
1076     if (xpma->valuemask & XpmColorSymbols)
1077         stat_out("XpmColorSymbols|");
1078     if (xpma->valuemask & XpmRgbFilename)
1079         stat_out("XpmRgbFilename|");
1080     if (xpma->valuemask & XpmInfos)
1081         stat_out("XpmInfos");
1082     stat_out(")\n");
1083    }
1084   else
1085     stat_out("  valuemask: NULL\n");
1086
1087   stat_out("  Colormap: %d\n", xpma->colormap);
1088   stat_out("  depth: %d\n", xpma->depth);
1089   stat_out("  width: %d\n", xpma->width);
1090   stat_out("  height: %d\n", xpma->height);
1091   stat_out("  x_hotspot: %d\n", xpma->x_hotspot);
1092   stat_out("  y_hotspot: %d\n", xpma->y_hotspot);
1093   stat_out("  cpp: %d\n", xpma->cpp);
1094   stat_out("  npixels: %d\n", xpma->npixels);
1095   if (xpma->npixels) {
1096     stat_out("  Pixels: ");
1097     for (i=0; i<xpma->npixels; i++) {
1098       stat_out("%d, ", xpma->pixels[i]);
1099       if (i%10 == 0)
1100         stat_out("\n");
1101      }
1102     stat_out("\n");
1103    }
1104   stat_out("  numsymbols: %d\n", xpma->numsymbols);
1105   if (xpma->numsymbols) {
1106     for (i=0; i<xpma->numsymbols; i++)
1107       stat_out("    %18s | %18s | %d\n", xpma->colorsymbols[i].name,
1108                  xpma->colorsymbols[i].value, xpma->colorsymbols[i].pixel);
1109    }
1110   stat_out("  rgb_fname: \"%s\"\n",((xpma->rgb_fname)?(xpma->rgb_fname):"(nil)"));
1111   stat_out("  ---------------------------------\n");
1112   stat_out("  ncolors: %d\n", xpma->ncolors);
1113   if (xpma->ncolors) {
1114     for (i=0; i<xpma->ncolors; i++)
1115       if (xpma->colorTable[i][0] != NULL)
1116         stat_out("    %3d \"%1s\" \"%18s\" \"%5s\" \"%5s\" \"%5s\" \"%5s\"\n",
1117                 i+1,
1118                 ((xpma->colorTable[i][0])?(xpma->colorTable[i][0]):"(nil)"), 
1119                 ((xpma->colorTable[i][1])?(xpma->colorTable[i][1]):"(nil)"),
1120                 ((xpma->colorTable[i][2])?(xpma->colorTable[i][2]):"(nil)"), 
1121                 ((xpma->colorTable[i][3])?(xpma->colorTable[i][3]):"(nil)"),
1122                 ((xpma->colorTable[i][4])?(xpma->colorTable[i][4]):"(nil)"), 
1123                 ((xpma->colorTable[i][5])?(xpma->colorTable[i][5]):"(nil)")
1124         );
1125    }
1126   stat_out("  hints_cmt: \"%s\"\n",((xpma->hints_cmt)?(xpma->hints_cmt):"(nil)"));
1127   stat_out("  colors_cmt: \"%s\"\n",((xpma->colors_cmt)?(xpma->colors_cmt):"(nil)"));
1128   stat_out("  pixels_cmt: \"%s\"\n",((xpma->pixels_cmt)?(xpma->pixels_cmt):"(nil)"));
1129   stat_out("  mask_pixel: 0x%x\n",xpma->mask_pixel);
1130 }
1131 #endif