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