b99d2ede0b813795759a97237425a2711630b9d6
[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     snprintf(fname, sizeof(fname), "%s", 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       snprintf(last_fname, sizeof(last_fname), "%s", 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          snprintf(dummy, sizeof(dummy), "%s_m", fname);
403     }
404 #ifdef DEBUG
405   if (debug)
406     stat_out("  mask-file = '%s'\n", dummy);
407 #endif
408     status = XReadBitmapFile(dpy, tablet_win, dummy,
409                 &mask_width_ret, &mask_height_ret, &mask_ret,
410                 &mask_x_hot, &mask_y_hot);
411     if (status == BitmapSuccess) {
412       if ((width_ret != mask_width_ret) || (height_ret != mask_height_ret)) {
413         XFreePixmap(dpy, mask_ret);
414         mask_ret = 0;
415        }
416      }
417     else
418       mask_ret = 0;
419    }
420
421   snprintf(last_fname, sizeof(last_fname), "%s", fname);
422   ChangeTitle();
423
424 #ifdef DEBUG
425   if (debug) {
426     stat_out("Finished Reading file '%s'\n", last_fname);
427     stat_out("Leaving Read_File\n");
428    }
429 #endif
430
431   return (True);
432 }
433
434
435 /***************************************************************************
436  *                                                                         *
437  * Routine:   Write_File                                                   *
438  *                                                                         *
439  * Purpose:   To write the current icon to the specified filename as       *
440  *            either an XPM file or XBM file, depending on the current     *
441  *            value of the fileFormat flag.  Further, if the current       *
442  *            fileFormat is FORMAT_XBM, create a second XBM file which     *
443  *            contains a mask for the XBM file just written.               *
444  *                                                                         *
445  ***************************************************************************/
446 Boolean
447 Write_File(
448         char *fnameIn )
449 {
450   extern int tt_tmpfile_fd;
451   int i, j;
452   int mask_needed;
453   Boolean SUN;
454   char *base_name, *suffix, fname[MAXPATHLEN], *tmp, *tmp2, *vend;
455   Pixmap scratch_pix;
456   XImage *scratch_shape, *scratch_mask;
457   struct stat statbuf;        /* Information on a file. */
458
459
460 #ifdef DEBUG
461   if (debug)
462     stat_out("Entering Write_File\n");
463 #endif
464   SUN = False;   /* Assume machine other than SUN */
465   if ( !fnameIn || !(*fnameIn) )
466     return False;
467
468   tmp  = strchr(fnameIn, ':');
469   tmp2 = strchr(fnameIn, '/');
470
471   /*** - convert from "<host>:/..." to a path on the locale host. ***/
472   if (tmp && tmp2 && (tmp2 == tmp+1))
473   {
474     char        *netfile, *localfile;
475     
476     tmp[0] = '\0';
477     netfile = tt_host_file_netfile(fnameIn, tmp+1);
478     localfile = tt_netfile_file(netfile);
479
480     strncpy(fname, localfile, MAXPATHLEN - 1);
481     fname[MAXPATHLEN - 1] = 0;
482     tmp[0] = ':';
483
484     tt_free(netfile);
485     tt_free(localfile);
486   }
487   else     /* wasn't in form "<host>:/<path>" so use name as is... */
488   {
489     snprintf(fname, sizeof(fname), "%s", fnameIn);
490   }
491
492
493   base_name = strrchr(fname, '/');
494   if (fname) {
495     base_name = (base_name ? base_name + 1 : fname);
496   }
497
498   snprintf(last_fname, sizeof(last_fname), "%s", fname);
499   ChangeTitle();
500
501 #ifdef DEBUG
502   if (debug)
503     stat_out("Writing file '%s'\n", last_fname);
504 #endif
505
506   if (fileFormat == FORMAT_XPM) {
507     xpm_WriteAttribs.x_hotspot = X_Hot;
508     xpm_WriteAttribs.y_hotspot = Y_Hot;
509     xpm_WriteAttribs.width  = icon_width;
510     xpm_WriteAttribs.height = icon_height;
511     xpm_WriteAttribs.cpp    = 1;
512     xpm_WriteAttribs.colorsymbols = colorSymbols;
513     xpm_WriteAttribs.numsymbols = NUM_PENS;
514     xpm_WriteAttribs.ncolors = NUM_PENS;
515     xpm_WriteAttribs.valuemask = WRITE_FLAGS;
516 #ifdef DEBUG
517   if (debug)
518     Dump_AttribStruct(&xpm_WriteAttribs);
519 #endif
520     status = _DtXpmWriteFileFromPixmap(dpy, fname, color_icon, 0,
521                                 &xpm_WriteAttribs);
522
523 /*******
524     status = _DtXpmWriteFileFromPixmap(dpy, fname, color_icon, NULL, NULL);
525 ********/
526     if (status != XpmSuccess) {
527 #ifdef DEBUG
528   if (debug) {
529     stat_out("Leaving Write_File - XPM write failed. ");
530     switch (status) {
531       case XpmOpenFailed : stat_out("(XpmOpenFailed)\n"); break;
532       case XpmNoMemory   : stat_out("(XpmNoMemory)\n"); break;
533       default            : stat_out("(UNKNOWN cause)\n"); break;
534     }
535   }
536 #endif
537       return (False);
538     }
539   }
540   else {
541 /*** FIRST, does a suffix exist? ***/
542   suffix = strrchr(base_name, '.');
543   if ((suffix) && ((int)strlen(suffix) > 1))
544     suffix++;
545 /*** SECOND, is it a valid suffix? ***/
546   if (suffix) {
547     if (strcmp(suffix, "bm") && strcmp(suffix, "xbm"))
548       suffix = NULL;
549   }
550 /*** THIRD, construct the mask filename ***/
551     if (suffix) {
552       strncpy(dummy, fname, ((suffix-fname)-1));
553       dummy[(int) (suffix-fname)-1] = '\0';
554       strcat(dummy, "_m.");
555       strcat(dummy, suffix);
556     }
557     else {
558       snprintf(dummy, sizeof(dummy), "%s_m", fname);
559     }
560 /*** FOURTH, construct XImages for the shape and mask bitmaps ***/
561     mask_needed = False;
562     scratch_shape = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height,
563                         AllPlanes, format);
564     scratch_mask = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height,
565                         AllPlanes, format);
566     if (!scratch_shape || !scratch_mask) {
567       if (scratch_shape)
568         XDestroyImage(scratch_shape);
569       if (scratch_mask)
570         XDestroyImage(scratch_mask);
571       return (False);
572     }
573
574     /* is this a SUN machine?                   */
575     /* if so use special code else use old code */
576     vend = ServerVendor(dpy);
577     if ( strncmp( vend, "Sun", 3) == 0) {
578        SUN = TRUE;
579        for (i=0; i<icon_width; i++)
580          for (j=0; j<icon_height; j++)
581            if (XGetPixel(scratch_shape, i, j) == Transparent) {
582             XPutPixel(scratch_shape, i, j,  white_pixel);
583             mask_needed = True;
584         }
585        for (i=0; i<icon_width; i++)
586          for (j=0; j<icon_height; j++)
587            if (XGetPixel(scratch_mask, i, j) != Transparent)
588              XPutPixel(scratch_mask, i, j,  black_pixel);
589            else
590              XPutPixel(scratch_mask, i, j,  white_pixel);
591     }else {
592        for (i=0; i<icon_width; i++)
593          for (j=0; j<icon_height; j++)
594           if (XGetPixel(scratch_shape, i, j) == Transparent) {
595             XPutPixel(scratch_shape, i, j,  black_pixel);
596             mask_needed = True;
597           }
598        for (i=0; i<icon_width; i++)
599          for (j=0; j<icon_height; j++)
600            if (XGetPixel(scratch_mask, i, j) != Transparent)
601              XPutPixel(scratch_mask, i, j,  white_pixel);
602            else
603              XPutPixel(scratch_mask, i, j,  black_pixel);
604     }
605
606
607 /*** FIFTH, write out the shape and mask bitmaps ***/
608     scratch_pix = XCreatePixmap(dpy, root, icon_width, icon_height,
609                                 DefaultDepth(dpy, screen));
610     if (!scratch_pix) {
611       if (scratch_shape)
612         XDestroyImage(scratch_shape);
613       if (scratch_mask)
614         XDestroyImage(scratch_mask);
615       return (False);
616     }
617     /* don't set GXcopyInverte for SUN machines */
618     if (!SUN)
619     XSetFunction(dpy, Mono_gc, GXcopyInverted);
620     XPutImage(dpy, scratch_pix, Mono_gc, scratch_shape, 0, 0, 0, 0,
621                         icon_width, icon_height);
622     XSetFunction(dpy, Mono_gc, GXcopy);
623     status = XWriteBitmapFile(dpy, fname, scratch_pix, icon_width, icon_height,
624                         X_Hot, Y_Hot);
625     if (status != BitmapSuccess)
626     {
627       XDestroyImage(scratch_shape);
628       XDestroyImage(scratch_mask);
629       XFreePixmap(dpy, scratch_pix);
630       return (False);
631     }
632     if (mask_needed) {
633       XPutImage(dpy, scratch_pix, Mono_gc, scratch_mask, 0, 0, 0, 0,
634                         icon_width, icon_height);
635       status = XWriteBitmapFile(dpy, dummy, scratch_pix, icon_width,
636                         icon_height, X_Hot, Y_Hot);
637       if (status != BitmapSuccess)
638       {
639         XDestroyImage(scratch_shape);
640         XDestroyImage(scratch_mask);
641         XFreePixmap(dpy, scratch_pix);
642         return (False);
643       }
644     } /***TAG***/
645     XFreePixmap(dpy, scratch_pix);
646     XDestroyImage(scratch_shape);
647     XDestroyImage(scratch_mask);
648   } /* else */
649
650   /* Don't know if this is needed....
651   if ( SUN )
652      {
653         SUN = False;
654         black_pixel = 0;
655         white_pixel = 1;
656      }
657   */
658
659 #ifdef DEBUG
660   if (debug)
661     stat_out("Leaving Write_File\n");
662 #endif
663     if( (fileFormat != FORMAT_XPM) && (!mask_needed) && (stat(tmpSave, &statbuf) == 0) )
664       unlink(dummy);
665 #ifdef __TOOLTALK
666     if (tt_tmpfile_fd != -1)
667        send_tt_saved();
668 #endif
669
670   return (True);
671 }
672
673 /***************************************************************************
674  *                                                                         *
675  * Routine:   Display_XPMFile                                              *
676  *                                                                         *
677  * Purpose:   Assuming that we have successfully read in an XPM file, use  *
678  *            the data from the file to render the proper rasters to the   *
679  *            color_icon and mono_icon (and their corresponding widgets).  *
680  *                                                                         *
681  *            Rendering the color icon is straight-forward, since the      *
682  *            pixmap generated by Read_File() is already correct.  For     *
683  *            the mono icon, we extract an XImage for the entire color     *
684  *            pixmap, and then convert each pixel individually to one      *
685  *            three values: black, white, or transparent.  For each pixel, *
686  *            the following test is performed: 1st) compare it to each     *
687  *            static color.  If a match is found, convert the pixel to     *
688  *            the appropriate mono equivalent.  2nd) if the 1st step fails *
689  *            to find a match, try the same comparisons against the        *
690  *            dynamic colors.  3rd) if the 2nd step also fails, use the    *
691  *            PixelTableLookup() function.                                 *
692  *                                                                         *
693  *            Once the coversion process is complete, both the color_icon  *
694  *            and mono_icon (and their corresponding widgets) can be       *
695  *            rendered.                                                    *
696  *                                                                         *
697  ***************************************************************************/
698
699 void
700 Display_XPMFile(
701         int width,
702         int height )
703 {
704   int converted, i, j, k;
705   int pixelTableIndex;
706   XImage *scratch_img, *mono_img, *mask_img;
707   Pixel cpixel, mpixel;
708 #ifdef DEBUG
709   int reset_debug;
710 #endif
711
712 #ifdef DEBUG
713   if (debug)
714     stat_out("Entering Display_XPMFile\n");
715   reset_debug=False;
716 #endif
717
718 /*** resize the color and mono icon windows, and the tablet ***/
719 /*** to their (new) correct height and width.               ***/
720   Init_Icons(width, height, DO_NOT_SAVE);
721
722 /*** Grab an image for both (potentially modified) ***/
723 /*** color and mono conversions                    ***/
724   scratch_img = XGetImage(dpy, pix_ret, 0, 0, width, height,
725                                 AllPlanes, format);
726   mono_img = XGetImage(dpy, pix_ret, 0, 0, width, height,
727                                 AllPlanes, format);
728   mask_img = NULL;
729   if (shape_ret)
730     mask_img = XGetImage(dpy, shape_ret, 0, 0, width, height,
731                                 AllPlanes, format);
732 #ifdef DEBUG
733   if (debug) {
734     debug = False;
735     reset_debug = True;
736    }
737 #endif
738   PixelTableClear;  /* force new pixel table now */
739   for (i=0; i<width; i++)
740     for (j=0; j<height; j++) {
741       converted = False;
742       cpixel = XGetPixel(scratch_img, i, j);
743       if (mask_img) {
744         mpixel = XGetPixel(mask_img, i, j);
745         if (!mpixel) {
746           cpixel = Transparent;
747           XPutPixel(scratch_img, i, j, cpixel);
748          }
749        } /* if(mask_img) */
750       for (k = 0; k < NUM_STATICS; k++)
751         if (cpixel == StaticPen[k]) {
752           XPutPixel(mono_img, i, j, StaticMono[k]);
753           converted = True;
754          } /* if(cpixel...) */
755       if (!converted) {
756         for (k = 0; k < NUM_DYNAMICS; k++)
757           if (cpixel == DynamicPen[k]) {
758             XPutPixel(mono_img, i, j, DynamicMono[k]);
759             converted = True;
760            } /* if(cpixel...) */
761        } /* if(!converted) */
762       if (!converted) {
763         pixelTableIndex = PixelTableLookup (cpixel, False);
764         XPutPixel(mono_img, i, j, PIXEL_TABLE_MONO(pixelTableIndex));
765        } /* if(!converted) */
766      } /* for(j...) */
767 #ifdef DEBUG
768   if (reset_debug) {
769     debug = True;
770     reset_debug = False;
771    }
772 #endif
773
774   XPutImage(dpy, color_icon, Color_gc, scratch_img,
775                 0, 0, 0, 0, width, height);
776   XPutImage(dpy, mono_icon, Mono_gc, mono_img,
777                 0, 0, 0, 0, width, height);
778
779 /*** this following stuff all gets done regardless ***/
780
781   XCopyArea(dpy, color_icon, XtWindow(iconImage),
782                 Color_gc, 0, 0, width, height, 0, 0);
783   XCopyArea(dpy, mono_icon, XtWindow(monoImage),
784                 Mono_gc, 0, 0, width, height, 0, 0);
785   icon_width = width;
786   icon_height = height;
787   fileFormat = FORMAT_XPM;
788   XmToggleButtonGadgetSetState(formatMenu_xpm_tb, True, True);
789 /* This line is not really needed since an Exposed event will be generated */
790   Repaint_Exposed_Tablet();
791   XDestroyImage(scratch_img);
792   XFreePixmap(dpy, pix_ret);
793   if (shape_ret)
794     XFreePixmap(dpy, shape_ret);
795
796 #ifdef DEBUG
797   if (debug)
798     stat_out("Leaving Display_XPMFile\n");
799 #endif
800 }
801
802
803 /***************************************************************************
804  *                                                                         *
805  * Routine:   Display_XBMFile                                              *
806  *                                                                         *
807  * Purpose:   Assuming that we have successfully read in an X bitmap file  *
808  *            (and, potentially, a mask file as well), use the data from   *
809  *            the file(s) to render the proper rasters to the color_icon   *
810  *            and mono_icon (and their corresponding widgets).             *
811  *                                                                         *
812  *            Rendering the bitmap is straight-forward (create a scratch   *
813  *            pixmap of the correct depth and copy-plane the just-read     *
814  *            bitmap onto it).  If there is a mask bitmap as well, then    *
815  *            the scratch pixmap must be modified such that for every      *
816  *            0 bit in the mask bitmap, the corresponding pixel of the     *
817  *            scratch pixmap should be set to the Transparent pixel.       *
818  *            Once this is done, the scratch pixmap is copied to both      *
819  *            the color_icon and mono_icon (since, for bitmaps, they're    *
820  *            identical).  Then free the scratch pixmap.                   *
821  *                                                                         *
822  ***************************************************************************/
823
824 void
825 Display_XBMFile(
826         int width,
827         int height )
828 {
829   int i, j;
830   XImage *test_img, *scratch_img;
831   Pixmap scratch_pix;
832
833 #ifdef DEBUG
834   if (debug)
835     stat_out("Entering Display_XBMFile\n");
836 #endif
837
838   scratch_pix = XCreatePixmap(dpy, root, width, height,
839                                 DefaultDepth(dpy, screen));
840   Init_Icons(width, height, DO_NOT_SAVE);
841   XSetBackground(dpy, scratch_gc, white_pixel);
842   XFillRectangle(dpy, scratch_pix, scratch_gc, 0, 0, width, height);
843   XSetForeground(dpy, scratch_gc, black_pixel);
844   XCopyPlane(dpy, pix_ret, scratch_pix, scratch_gc, 0, 0,
845                 width, height, 0, 0, 1);
846   if (mask_ret) {
847     test_img = XGetImage(dpy, mask_ret, 0, 0, width, height,
848         AllPlanes, format);
849     scratch_img = XGetImage(dpy, scratch_pix, 0, 0, width, height,
850         AllPlanes, format);
851     for (i=0; i<width; i++)
852       for (j=0; j<height; j++)
853         if (!XGetPixel(test_img, i, j))
854           XPutPixel(scratch_img, i, j, Transparent);
855     XPutImage(dpy, scratch_pix, scratch_gc, scratch_img,
856                 0, 0, 0, 0, width, height);
857    } /* if(mask_ret) */
858   XCopyArea(dpy, scratch_pix, color_icon, Color_gc, 0, 0,
859                 width, height, 0, 0);
860   XCopyArea(dpy, scratch_pix, mono_icon, Mono_gc, 0, 0,
861                 width, height, 0, 0);
862   XCopyArea(dpy, color_icon, XtWindow(iconImage),
863                 Color_gc, 0, 0, width, height, 0, 0);
864   XCopyArea(dpy, mono_icon, XtWindow(monoImage),
865                 Mono_gc, 0, 0, width, height, 0, 0);
866   icon_width = width;
867   icon_height = height;
868   fileFormat = FORMAT_XBM;
869   XmToggleButtonGadgetSetState(formatMenu_xbm_tb, True, True);
870 /* This line is not really needed since an Exposed event will be generated */
871   Repaint_Exposed_Tablet();
872   if (mask_ret) {
873     XDestroyImage(test_img);
874     XDestroyImage(scratch_img);
875    }
876   XFreePixmap(dpy, scratch_pix);
877   XFreePixmap(dpy, pix_ret);
878   if (mask_ret)
879     XFreePixmap(dpy, mask_ret);
880
881 #ifdef DEBUG
882   if (debug)
883     stat_out("Leaving Display_XBMFile\n");
884 #endif
885 }
886
887
888 /***************************************************************************
889  *                                                                         *
890  * Routine:   SetFileIODialogInfo                                          *
891  *                                                                         *
892  * Purpose:   Set FileIODialog information... title, path, etc.            *
893  *                                                                         *
894  ***************************************************************************/
895 void
896 SetFileIODialogInfo( void )
897 {
898   static int currentTitle = SAVE_AS;  /* initial title is for Save_As... */
899   static XmString saveTitle = NULL;
900   static XmString openTitle = NULL;
901   static XmString saveLabel = NULL;
902   static XmString openLabel = NULL;
903   static XmString OpenOKLabel = NULL;
904   static XmString SaveOKLabel = NULL;
905
906   static char *untitledStr = NULL;
907   static Widget textWidget = NULL;
908   static char newName[MAX_FNAME];
909   static char dirStr[MAX_FNAME];
910   static char tmpStr[MAX_FNAME];
911
912   Arg args[10];
913   int  n,dirlen=0,filelen=0,tst, ln;
914   char *strOrig = NULL;
915   XmString  tmpXmStr;
916   char tmp[MAX_FNAME];
917   char *tmp1= NULL;
918   char *tmp2= NULL;
919   int c;
920   int startSelect, endSelect;
921
922   if (DialogFlag == OPEN) /* Dialog is for File-Open menu item */
923   {
924     /* set title to "Icon Editor - Open File" if needed */
925       if (!openTitle)
926         openTitle = GETXMSTR(2,8,  "Icon Editor - Open File");
927       n = 0;
928       XtSetArg (args[n], XmNdialogTitle, openTitle);         n++;
929       XtSetValues (fileIODialog, args, n);
930       currentTitle = OPEN;
931
932       /* set selection label to "Open File" */
933       if (!openLabel)
934         openLabel = GETXMSTR(2,17,  "Enter file name:");
935       n = 0;
936       XtSetArg (args[n], XmNselectionLabelString, openLabel);         n++;
937       OpenOKLabel = GETXMSTR(2,22,  "Open");
938       XtSetArg (args[n], XmNokLabelString, OpenOKLabel);              n++;
939       XtSetValues (fileIODialog, args, n);
940   }
941   else  /* Dialog is for File-Save or File-Save_As menu item */
942   {
943     /* set title to "Icon Editor - Save As" if needed */
944       if (!saveTitle)
945         saveTitle = GETXMSTR(2,6,  "Icon Editor - Save As");
946       n = 0;
947       XtSetArg (args[n], XmNdialogTitle, saveTitle);         n++;
948       XtSetValues (fileIODialog, args, n);
949       currentTitle = SAVE_AS;
950
951       /* set selection label to "Enter file name:" */
952       if (!saveLabel)
953         saveLabel = GETXMSTR(2,16,  "Enter file name:");
954       n = 0;
955       XtSetArg (args[n], XmNselectionLabelString, saveLabel);         n++;
956       SaveOKLabel = GETXMSTR(2,24,  "Save");
957       XtSetArg (args[n], XmNokLabelString, SaveOKLabel);              n++;
958       XtSetValues (fileIODialog, args, n);
959   }
960     /*                                                  */
961     /* set string to "UNTITLED" with appropriate suffix */
962     /* when apropriate                                  */
963
964     if (!untitledStr)
965       untitledStr = GETSTR(2,20, "UNTITLED");
966     if (!textWidget)
967       textWidget = XmFileSelectionBoxGetChild(fileIODialog, XmDIALOG_TEXT);
968     strOrig = XmTextFieldGetString(textWidget);
969
970     dirStr[0] = '\0';
971     newName[0]='\0';
972     tmpStr[0]='\0';
973     startSelect = 0;
974
975     /* prepare to test */
976     tmp1 = strrchr(strOrig, '.');
977
978     snprintf(tmpStr, sizeof(tmpStr), "%s.m.pm", untitledStr);
979     tst=strcmp(last_fname, tmpStr);
980
981     if ( tst==0 ) {/* untitled */
982        if ( tmp1 ) { /* previous string exists */
983           if (currentTitle != SAVE_AS) {
984               snprintf(newName, sizeof(newName), "%s", strOrig);
985           } else {
986               snprintf(newName, sizeof(newName), "%s.m.pm", untitledStr);
987           }
988                /* Update the FSB */
989                XmFileSelectionDoSearch(fileIODialog,(XmString)NULL);
990
991        }
992        else { /* First time arownd */
993           if (strOrig && strOrig[0]!='\0')
994              snprintf(newName, sizeof(newName), "%s", strOrig);
995           else {
996              snprintf(newName, sizeof(newName), "%s.m.pm", untitledStr);
997           }
998
999     XSync(dpy, 0);
1000           /* rebuild last file name */
1001           last_fname[0] = '\0';
1002           strcpy(last_fname, dirStr);
1003           strcat(last_fname, newName);
1004        }
1005     }
1006     else { /* not untitled */
1007          tmp1= strrchr(last_fname, '/');
1008
1009          /*
1010           * Check if any '/' characters found
1011           */
1012          if (tmp1)
1013          {
1014              /*
1015               * Strip path into directory name and file name
1016               */
1017              c = tmp1[1];
1018              tmp2 = strchr(tmp1, c);
1019              if(tmp2) {
1020                snprintf(newName, sizeof(newName), "%s", tmp2);
1021              }
1022
1023              /* make and insert the directory name */
1024              ln = strlen(last_fname) - strlen(tmp1);
1025              strncpy(dirStr, last_fname, ln);
1026              dirStr[ln] = '\0';
1027          }
1028          else
1029          {
1030              /*
1031               * Path is a simple filename
1032               * Set filename to be path name
1033               * Set directory name = "."
1034               */
1035              strcpy(newName, last_fname);
1036              dirStr[0] = '.';
1037              dirStr[1] = '\0';
1038          }
1039
1040          tmpXmStr = XmStringCreateLocalized (dirStr);
1041          n = 0;
1042          XtSetArg (args[n], XmNdirectory, tmpXmStr);      n++;
1043          XtSetValues (fileIODialog, args, n);
1044          XmStringFree(tmpXmStr);
1045     }
1046      ln=0;
1047      /* set the Highlighted string */
1048      newName[strlen(newName)+1] ='\0';
1049      tmp1 = strchr(newName, '.');
1050      if (tmp1 && tmp1[0]!='\0') ln = (int)strlen(tmp1);
1051      endSelect = strlen(newName)- ln;
1052
1053     /* now set the text field and set selection for highlighted portion */
1054     XmTextFieldSetString(textWidget, newName);
1055     XmTextFieldSetSelection(textWidget, startSelect, endSelect, CurrentTime);
1056
1057     XSync(dpy, 0);
1058     XmProcessTraversal(textWidget, XmTRAVERSE_CURRENT);
1059     XSync(dpy, 0);
1060
1061     XtFree(strOrig);
1062
1063   /* if file lists are being used, re-scan the directory contents */
1064  /* if (xrdb.useFileLists)
1065     XmFileSelectionDoSearch(fileIODialog, NULL);*/
1066 }
1067
1068
1069
1070 #ifdef DEBUG
1071 /***************************************************************************
1072  *                                                                         *
1073  * Routine:   Dump_AttribStruct  #ifdef DEBUG only (for bba)               *
1074  *                                                                         *
1075  * Purpose:   Print out the entier contents of the XpmAttributes struct.   *
1076  *                                                                         *
1077  ***************************************************************************/
1078 int
1079 Dump_AttribStruct(
1080         XpmAttributes *xpma )
1081 {
1082   int i, j;
1083
1084   if (xpma->valuemask) {
1085     stat_out("  valuemask: (");
1086     if (xpma->valuemask & XpmVisual)
1087         stat_out("XpmVisual|");
1088     if (xpma->valuemask & XpmColormap)
1089         stat_out("XpmColormap|");
1090     if (xpma->valuemask & XpmDepth)
1091         stat_out("XpmDepth|");
1092     if (xpma->valuemask & XpmSize)
1093         stat_out("XpmSize|");
1094     if (xpma->valuemask & XpmHotspot)
1095         stat_out("XpmHotspot|");
1096     if (xpma->valuemask & XpmCharsPerPixel)
1097         stat_out("XpmCharsPerPixel|");
1098     if (xpma->valuemask & XpmColorSymbols)
1099         stat_out("XpmColorSymbols|");
1100     if (xpma->valuemask & XpmRgbFilename)
1101         stat_out("XpmRgbFilename|");
1102     if (xpma->valuemask & XpmInfos)
1103         stat_out("XpmInfos");
1104     stat_out(")\n");
1105    }
1106   else
1107     stat_out("  valuemask: NULL\n");
1108
1109   stat_out("  Colormap: %d\n", xpma->colormap);
1110   stat_out("  depth: %d\n", xpma->depth);
1111   stat_out("  width: %d\n", xpma->width);
1112   stat_out("  height: %d\n", xpma->height);
1113   stat_out("  x_hotspot: %d\n", xpma->x_hotspot);
1114   stat_out("  y_hotspot: %d\n", xpma->y_hotspot);
1115   stat_out("  cpp: %d\n", xpma->cpp);
1116   stat_out("  npixels: %d\n", xpma->npixels);
1117   if (xpma->npixels) {
1118     stat_out("  Pixels: ");
1119     for (i=0; i<xpma->npixels; i++) {
1120       stat_out("%d, ", xpma->pixels[i]);
1121       if (i%10 == 0)
1122         stat_out("\n");
1123      }
1124     stat_out("\n");
1125    }
1126   stat_out("  numsymbols: %d\n", xpma->numsymbols);
1127   if (xpma->numsymbols) {
1128     for (i=0; i<xpma->numsymbols; i++)
1129       stat_out("    %18s | %18s | %d\n", xpma->colorsymbols[i].name,
1130                  xpma->colorsymbols[i].value, xpma->colorsymbols[i].pixel);
1131    }
1132   stat_out("  rgb_fname: \"%s\"\n",((xpma->rgb_fname)?(xpma->rgb_fname):"(nil)"));
1133   stat_out("  ---------------------------------\n");
1134   stat_out("  ncolors: %d\n", xpma->ncolors);
1135   if (xpma->ncolors) {
1136     for (i=0; i<xpma->ncolors; i++)
1137       if (xpma->colorTable[i][0] != NULL)
1138         stat_out("    %3d \"%1s\" \"%18s\" \"%5s\" \"%5s\" \"%5s\" \"%5s\"\n",
1139                 i+1,
1140                 ((xpma->colorTable[i][0])?(xpma->colorTable[i][0]):"(nil)"), 
1141                 ((xpma->colorTable[i][1])?(xpma->colorTable[i][1]):"(nil)"),
1142                 ((xpma->colorTable[i][2])?(xpma->colorTable[i][2]):"(nil)"), 
1143                 ((xpma->colorTable[i][3])?(xpma->colorTable[i][3]):"(nil)"),
1144                 ((xpma->colorTable[i][4])?(xpma->colorTable[i][4]):"(nil)"), 
1145                 ((xpma->colorTable[i][5])?(xpma->colorTable[i][5]):"(nil)")
1146         );
1147    }
1148   stat_out("  hints_cmt: \"%s\"\n",((xpma->hints_cmt)?(xpma->hints_cmt):"(nil)"));
1149   stat_out("  colors_cmt: \"%s\"\n",((xpma->colors_cmt)?(xpma->colors_cmt):"(nil)"));
1150   stat_out("  pixels_cmt: \"%s\"\n",((xpma->pixels_cmt)?(xpma->pixels_cmt):"(nil)"));
1151   stat_out("  mask_pixel: 0x%x\n",xpma->mask_pixel);
1152 }
1153 #endif