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