/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $XConsortium: fileIO.c /main/8 1996/10/21 17:31:11 mgreess $ */ /********************************************************************* * (c) Copyright 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc. * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of * Novell, Inc. **********************************************************************/ /****************************************************************************** ** Program: dticon ** ** Description: X11-based multi-color icon editor ** ** File: fileIO.c, which contains the following subroutines or ** functions: ** Do_FileIO() ** Read_File() ** Write_File() ** Display_XPMFile() ** Display_XBMFile() ** Dump_AttribStruct() ** ****************************************************************************** ** ** Copyright Hewlett-Packard Company, 1990, 1991, 1992. ** All rights are reserved. Copying or reproduction of this program, ** except for archival purposes, is prohibited without prior written ** consent of Hewlett-Packard Company. ** ** Hewlett-Packard makes no representations about the suitibility of this ** software for any purpose. It is provided "as is" without express or ** implied warranty. ** ******************************************************************************/ #include #include #include #include #include #include #include #include #include #include "externals.h" #include "main.h" #include "utils.h" #include "process.h" #ifdef __TOOLTALK #include extern void ReplyToMessage( ); extern Tt_message replyMsg; #endif extern XtPointer _XmStringUngenerate ( XmString string, XmStringTag tag, XmTextType tag_type, XmTextType output_type); extern Widget formatMenu_xpm_tb, formatMenu_xbm_tb; extern Window tablet_win; extern Widget editMenu_deleteHS_pb; Boolean Read_File(), Write_File(); Pixmap pix_ret, shape_ret, mask_ret; int successFormat, x_hot, y_hot; unsigned int width_ret, height_ret; extern GC scratch_gc; extern void PixelTableClear(); extern void send_tt_saved(); extern void Display_XPMFile(int, int); extern void Display_XBMFile(int, int); char *tmpSave; /* Save the file path being saved */ char dummy[256]; /* mask file for use in main */ extern int SaveMeNot; extern int SavedOnce; /*************************************************************************** * * * Routine: Do_FileIO * * * * Purpose: To read/write the current icon from/to the filename * * selected in the file selection box. * * * * If fileIOMode is FILE_READ, this file should be read in. * * If the read attempt fails, an error dialog pops up to * * inform the user. * * * * If fileIOMode is FILE_WRITE, the currently loaded icon * * should be written to the named file, using the current file * * format (specified by 'fileFormat'). As with FILE_READ, if * * the write attempt fails, an error dialog pops up to inform * * the user. * * * ***************************************************************************/ void Do_FileIO( Widget wid, XtPointer client_unused, XmFileSelectionBoxCallbackStruct *callback_data ) { int unmanageFileIO = True; struct stat statbuf; /* Information on a file. */ #ifdef DEBUG if (debug) stat_out("Entering Do_FileIO\n"); #endif pix_ret = 0; shape_ret = 0; mask_ret = 0; /* get file name */ if (SaveMeNot){ tmpSave = (char *) _XmStringUngenerate( callback_data->value, NULL, XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT); } if (fileIOMode == FILE_READ) { if (!Read_File(tmpSave)) { unmanageFileIO = False; DoErrorDialog( (GETSTR(16,2, "The file cannot be accessed\nor contains invalid data")) ); } else { if (successFormat == FORMAT_XPM) { X_Hot = xpm_ReadAttribs.x_hotspot; Y_Hot = xpm_ReadAttribs.y_hotspot; Display_XPMFile(xpm_ReadAttribs.width, xpm_ReadAttribs.height); } else if (successFormat == FORMAT_XBM) { X_Hot = x_hot; Y_Hot = y_hot; Display_XBMFile(width_ret, height_ret); } Dirty = False; SavedOnce = True; /* Implicitly saved, since we loaded the file */ /* Turn off the HotSpot thing in the File menu. */ if ( X_Hot == -1 ) XtSetSensitive((Widget) editMenu_deleteHS_pb, False ); if (unmanageFileIO) XtUnmanageChild(fileIODialog); } /* else */ } /* if(FileIOMode...) */ if (fileIOMode == FILE_WRITE) { if (stat(tmpSave, &statbuf) == 0 && SaveMeNot) { DialogFlag=SAVE_AS; DoQueryDialog( GETSTR(16,25, "File already exists.\n\nOK to overwrite the file?") ); } else { if (!Write_File(tmpSave)) { unmanageFileIO = False; DoErrorDialog( (GETSTR(16,4, "Unable to write data to file")) ); } else{ if (!SaveMeNot) SaveMeNot = True; Dirty = False; SavedOnce = True; if (unmanageFileIO) XtUnmanageChild(fileIODialog); } } } #ifdef DEBUG if (debug) stat_out("Leaving Do_FileIO\n"); #endif } /*************************************************************************** * * * Routine: Read_File * * * * Purpose: To read the contents of the specified file and create either * * a multi-color icon (if the file is an XPM file) or a bi- * * color icon (if the file is an XBM file). Further, if the * * file is an XBM file, attempt to find a matching mask file * * and read it as well, using to result to determine which * * pixels should be set to transparent. * * * ***************************************************************************/ Boolean Read_File( char *fnameIn ) { char *base_name = NULL, *suffix = NULL, fname[MAXPATHLEN], *tmp = NULL, *tmp2 = NULL; unsigned int mask_width_ret = 0, mask_height_ret = 0; int mask_x_hot = 0, mask_y_hot = 0, first = 0; struct stat statBuf = {}; fname[0] = 0; #ifdef DEBUG if (debug) stat_out("Entering Read_File\n"); #endif if ( !fnameIn || !(*fnameIn) ) return False; tmp = strchr(fnameIn, ':'); tmp2 = strchr(fnameIn, '/'); /*** - convert from ":/..." to a path on the locale host. ***/ if (tmp && tmp2 && (tmp2 == tmp+1)) { char *netfile, *localfile; tmp[0] = '\0'; netfile = tt_host_file_netfile(fnameIn, tmp+1); localfile = tt_netfile_file(netfile); strncpy(fname, localfile, MAXPATHLEN); tmp[0] = ':'; tt_free(netfile); tt_free(localfile); } else /* wasn't in form ":/" so use name as is... */ { snprintf(fname, sizeof(fname), "%s", fnameIn); } /*** - if we got a NULL base_name, return FALSE ***/ base_name = strrchr(fname, '/'); if (fname[0]) base_name = (base_name ? base_name + 1 : fname); if (!base_name) return (False); /*** - if it's not a regular file, don't use it ***/ if (stat(fname, &statBuf) == 0) /* success */ { if ( (statBuf.st_mode & S_IFMT) == S_IFDIR || (statBuf.st_mode & S_IFMT) == S_IFCHR || (statBuf.st_mode & S_IFMT) == S_IFBLK ) { return False; } if (statBuf.st_size == 0) { Process_Clear(); Process_Resize(); snprintf(last_fname, sizeof(last_fname), "%s", fname); ChangeTitle(); successFormat = FORMAT_NONE; return True; } } else { return False; /* file doesn't exist, return failure */ } /*** before we do anything else, make sure ***/ /*** the editor interface refreshes itself ***/ XmUpdateDisplay(mainWindow); pix_ret = 0; shape_ret = 0; mask_ret = 0; xpm_ReadAttribs.valuemask = READ_FLAGS; xpm_ReadAttribs.colorsymbols = colorSymbols; xpm_ReadAttribs.numsymbols = NUM_PENS; /*** if the file ends in .pm or .xpm, try reading it as an ***/ /*** XPM file first. Then try XBM format if XPM fails. ***/ /*** ***/ /*** if the file ends in .bm or .xbm, try reading it as an ***/ /*** XBM file first. Then try XPM format if XBM fails. ***/ /*** ***/ /*** if the file doesn't match any of these suffixes, try ***/ /*** reading it as an XPM file first. Then try XBM format ***/ /*** if XPM fails. ***/ /*** FIRST, does a suffix exist? ***/ suffix = strrchr(base_name, '.'); if ((suffix) && ((int)strlen(suffix) > 1)) suffix++; if (suffix) { if (!strcmp(suffix, "bm") || !strcmp(suffix, "xbm")) first = FORMAT_XBM; else first = FORMAT_XPM; } else first = FORMAT_XPM; /*** try to read the XPM/XBM file, in the order ***/ /*** specified by the 'first' format. ***/ if (first == FORMAT_XPM) { status = XpmReadFileToPixmap(dpy, tablet_win, fname, &pix_ret, &shape_ret, &xpm_ReadAttribs); #ifdef DEBUG if (debug) { if (debug_image) XDestroyImage(debug_image); if (debug_shape) XDestroyImage(debug_shape); debug_status = XpmReadFileToImage(dpy, fname, &debug_image, &debug_shape, &xpm_ReadAttribs); } #endif if (status != XpmSuccess) { status = XReadBitmapFile(dpy, tablet_win, fname, &width_ret, &height_ret, &pix_ret, &x_hot, &y_hot); if (status != BitmapSuccess) { #ifdef DEBUG if (debug) stat_out("Leaving Read_File - XPM/XBM read attempt failed.\n"); #endif return (False); } else successFormat = FORMAT_XBM; } else successFormat = FORMAT_XPM; } else { status = XReadBitmapFile(dpy, tablet_win, fname, &width_ret, &height_ret, &pix_ret, &x_hot, &y_hot); if (status != BitmapSuccess) { status = XpmReadFileToPixmap(dpy, tablet_win, fname, &pix_ret, &shape_ret, &xpm_ReadAttribs); if (status != XpmSuccess) { #ifdef DEBUG if (debug) stat_out("Leaving Read_File - XBM/XPM read attempt failed.\n"); #endif return (False); } else successFormat = FORMAT_XPM; } else successFormat = FORMAT_XBM; } /*** If we got this far, we successfully read in a file. ***/ /*** If the 'successFormat' is FORMAT_XBM, try to find ***/ /*** and accompanying mask file and load it too. The ***/ /*** format for a mask file name is: ***/ /*** _m (optional suffix)***/ if (successFormat == FORMAT_XBM) { /*** does a suffix exist? ***/ if (suffix) { strncpy(dummy, fname, ((suffix-fname)-1)); dummy[(int) (suffix-fname)-1] = '\0'; strcat(dummy, "_m."); strcat(dummy, suffix); #ifdef DEBUG if (debug) { stat_out(" full-filename = '%s'\n", fname); stat_out(" suffix = '%s'\n", suffix); } #endif } else { snprintf(dummy, sizeof(dummy), "%s_m", fname); } #ifdef DEBUG if (debug) stat_out(" mask-file = '%s'\n", dummy); #endif status = XReadBitmapFile(dpy, tablet_win, dummy, &mask_width_ret, &mask_height_ret, &mask_ret, &mask_x_hot, &mask_y_hot); if (status == BitmapSuccess) { if ((width_ret != mask_width_ret) || (height_ret != mask_height_ret)) { XFreePixmap(dpy, mask_ret); mask_ret = 0; } } else mask_ret = 0; } snprintf(last_fname, sizeof(last_fname), "%s", fname); ChangeTitle(); #ifdef DEBUG if (debug) { stat_out("Finished Reading file '%s'\n", last_fname); stat_out("Leaving Read_File\n"); } #endif return (True); } /*************************************************************************** * * * Routine: Write_File * * * * Purpose: To write the current icon to the specified filename as * * either an XPM file or XBM file, depending on the current * * value of the fileFormat flag. Further, if the current * * fileFormat is FORMAT_XBM, create a second XBM file which * * contains a mask for the XBM file just written. * * * ***************************************************************************/ Boolean Write_File( char *fnameIn ) { extern int tt_tmpfile_fd; int i, j; int mask_needed = False; Boolean SUN; char *base_name, *suffix, fname[MAXPATHLEN], *tmp, *tmp2, *vend; Pixmap scratch_pix; XImage *scratch_shape, *scratch_mask; struct stat statbuf; /* Information on a file. */ #ifdef DEBUG if (debug) stat_out("Entering Write_File\n"); #endif SUN = False; /* Assume machine other than SUN */ if ( !fnameIn || !(*fnameIn) ) return False; tmp = strchr(fnameIn, ':'); tmp2 = strchr(fnameIn, '/'); /*** - convert from ":/..." to a path on the locale host. ***/ if (tmp && tmp2 && (tmp2 == tmp+1)) { char *netfile, *localfile; tmp[0] = '\0'; netfile = tt_host_file_netfile(fnameIn, tmp+1); localfile = tt_netfile_file(netfile); strncpy(fname, localfile, MAXPATHLEN - 1); fname[MAXPATHLEN - 1] = 0; tmp[0] = ':'; tt_free(netfile); tt_free(localfile); } else /* wasn't in form ":/" so use name as is... */ { snprintf(fname, sizeof(fname), "%s", fnameIn); } base_name = strrchr(fname, '/'); if (fname[0]) { base_name = (base_name ? base_name + 1 : fname); } snprintf(last_fname, sizeof(last_fname), "%s", fname); ChangeTitle(); #ifdef DEBUG if (debug) stat_out("Writing file '%s'\n", last_fname); #endif if (fileFormat == FORMAT_XPM) { xpm_WriteAttribs.x_hotspot = X_Hot; xpm_WriteAttribs.y_hotspot = Y_Hot; xpm_WriteAttribs.width = icon_width; xpm_WriteAttribs.height = icon_height; xpm_WriteAttribs.cpp = 1; xpm_WriteAttribs.colorsymbols = colorSymbols; xpm_WriteAttribs.numsymbols = NUM_PENS; xpm_WriteAttribs.ncolors = NUM_PENS; xpm_WriteAttribs.valuemask = WRITE_FLAGS; #ifdef DEBUG if (debug) Dump_AttribStruct(&xpm_WriteAttribs); #endif status = XpmWriteFileFromPixmap(dpy, fname, color_icon, 0, &xpm_WriteAttribs); /******* status = XpmWriteFileFromPixmap(dpy, fname, color_icon, NULL, NULL); ********/ if (status != XpmSuccess) { #ifdef DEBUG if (debug) { stat_out("Leaving Write_File - XPM write failed. "); switch (status) { case XpmOpenFailed : stat_out("(XpmOpenFailed)\n"); break; case XpmNoMemory : stat_out("(XpmNoMemory)\n"); break; default : stat_out("(UNKNOWN cause)\n"); break; } } #endif return (False); } } else { /*** FIRST, does a suffix exist? ***/ suffix = strrchr(base_name, '.'); if ((suffix) && ((int)strlen(suffix) > 1)) suffix++; /*** SECOND, is it a valid suffix? ***/ if (suffix) { if (strcmp(suffix, "bm") && strcmp(suffix, "xbm")) suffix = NULL; } /*** THIRD, construct the mask filename ***/ if (suffix) { strncpy(dummy, fname, ((suffix-fname)-1)); dummy[(int) (suffix-fname)-1] = '\0'; strcat(dummy, "_m."); strcat(dummy, suffix); } else { snprintf(dummy, sizeof(dummy), "%s_m", fname); } /*** FOURTH, construct XImages for the shape and mask bitmaps ***/ mask_needed = False; scratch_shape = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height, AllPlanes, format); scratch_mask = XGetImage(dpy, mono_icon, 0, 0, icon_width, icon_height, AllPlanes, format); if (!scratch_shape || !scratch_mask) { if (scratch_shape) XDestroyImage(scratch_shape); if (scratch_mask) XDestroyImage(scratch_mask); return (False); } /* is this a SUN machine? */ /* if so use special code else use old code */ vend = ServerVendor(dpy); if ( strncmp( vend, "Sun", 3) == 0) { SUN = TRUE; for (i=0; ivaluemask) { stat_out(" valuemask: ("); if (xpma->valuemask & XpmVisual) stat_out("XpmVisual|"); if (xpma->valuemask & XpmColormap) stat_out("XpmColormap|"); if (xpma->valuemask & XpmDepth) stat_out("XpmDepth|"); if (xpma->valuemask & XpmSize) stat_out("XpmSize|"); if (xpma->valuemask & XpmHotspot) stat_out("XpmHotspot|"); if (xpma->valuemask & XpmCharsPerPixel) stat_out("XpmCharsPerPixel|"); if (xpma->valuemask & XpmColorSymbols) stat_out("XpmColorSymbols|"); if (xpma->valuemask & XpmRgbFilename) stat_out("XpmRgbFilename|"); if (xpma->valuemask & XpmInfos) stat_out("XpmInfos"); stat_out(")\n"); } else stat_out(" valuemask: NULL\n"); stat_out(" Colormap: %d\n", xpma->colormap); stat_out(" depth: %d\n", xpma->depth); stat_out(" width: %d\n", xpma->width); stat_out(" height: %d\n", xpma->height); stat_out(" x_hotspot: %d\n", xpma->x_hotspot); stat_out(" y_hotspot: %d\n", xpma->y_hotspot); stat_out(" cpp: %d\n", xpma->cpp); stat_out(" npixels: %d\n", xpma->npixels); if (xpma->npixels) { stat_out(" Pixels: "); for (i=0; inpixels; i++) { stat_out("%d, ", xpma->pixels[i]); if (i%10 == 0) stat_out("\n"); } stat_out("\n"); } stat_out(" numsymbols: %d\n", xpma->numsymbols); if (xpma->numsymbols) { for (i=0; inumsymbols; i++) stat_out(" %18s | %18s | %d\n", xpma->colorsymbols[i].name, xpma->colorsymbols[i].value, xpma->colorsymbols[i].pixel); } stat_out(" rgb_fname: \"%s\"\n",((xpma->rgb_fname)?(xpma->rgb_fname):"(nil)")); stat_out(" ---------------------------------\n"); stat_out(" ncolors: %d\n", xpma->ncolors); if (xpma->ncolors) { for (i=0; incolors; i++) if (xpma->colorTable[i][0] != NULL) stat_out(" %3d \"%1s\" \"%18s\" \"%5s\" \"%5s\" \"%5s\" \"%5s\"\n", i+1, ((xpma->colorTable[i][0])?(xpma->colorTable[i][0]):"(nil)"), ((xpma->colorTable[i][1])?(xpma->colorTable[i][1]):"(nil)"), ((xpma->colorTable[i][2])?(xpma->colorTable[i][2]):"(nil)"), ((xpma->colorTable[i][3])?(xpma->colorTable[i][3]):"(nil)"), ((xpma->colorTable[i][4])?(xpma->colorTable[i][4]):"(nil)"), ((xpma->colorTable[i][5])?(xpma->colorTable[i][5]):"(nil)") ); } stat_out(" hints_cmt: \"%s\"\n",((xpma->hints_cmt)?(xpma->hints_cmt):"(nil)")); stat_out(" colors_cmt: \"%s\"\n",((xpma->colors_cmt)?(xpma->colors_cmt):"(nil)")); stat_out(" pixels_cmt: \"%s\"\n",((xpma->pixels_cmt)?(xpma->pixels_cmt):"(nil)")); stat_out(" mask_pixel: 0x%x\n",xpma->mask_pixel); } #endif