/* * 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 */ /* $TOG: utils.c /main/9 1998/09/24 12:32:05 samborn $ */ /********************************************************************* * (c) Copyright 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994 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: utils.c, which contains the following subroutines or ** functions: ** Create_Gfx_Labels() ** Init_Editor() ** New_MagFactor() ** New_FileFormat() ** Icon_Coords() ** Tablet_Coords() ** Quantize() ** Repaint_Exposed_Tablet() ** Repaint_Tablet() ** Paint_Tile() ** Transfer_Back_Image() ** Init_Widget_List() ** Init_Pen_Colors() ** Init_Color_Table() ** Size_IconForm() ** Init_Icons() ** Abort() ** stat_out() ** Switch_FillSolids() ** Select_New_Pen() ** Backup_Icons() ** DoErrorDialog() ** DoQueryDialog() ** Do_GrabOp() ** LoadGrabbedImage() ** ParseAppArgs() ** ProcessAppArgs() ** Set_Gfx_Labels() ** PixelTableLookup() ** PixelTableClear() ** ****************************************************************************** ** ** Copyright 1991 by 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
#include
#include #include
#include
#include "externals.h" #include "main.h" #include "process.h" #include "fileIO.h" #include "graphics.h" #include "image.h" /* Copied from Xm/BaseClassI.h */ extern XmWidgetExtData _XmGetWidgetExtData( Widget widget, #if NeedWidePrototypes unsigned int extType) ; #else unsigned char extType) ; #endif /* NeedWidePrototypes */ #include "pixmaps/Circle.pm" #include "pixmaps/CircleSolid.pm" #include "pixmaps/Connected.pm" #include "pixmaps/ConnectedClosed.pm" #include "pixmaps/ConnecClosedSolid.pm" #include "pixmaps/Ellipse.pm" #include "pixmaps/EllipseSolid.pm" #include "pixmaps/Eraser.pm" #include "pixmaps/Rectangle.pm" #include "pixmaps/RectangleSolid.pm" #include "pixmaps/PaintBucket.pm" #include "pixmaps/Pencil.pm" #include "pixmaps/Line.pm" #include "pixmaps/SelectArea.pm" #include "bitmaps/q_mark.xbm" extern Widget color_pb1, color_pb2, color_pb3, color_pb4, color_pb5, color_pb6, color_pb7, color_pb8; extern Widget grey_pb1, grey_pb2, grey_pb3, grey_pb4, grey_pb5, grey_pb6, grey_pb7, grey_pb8; extern Widget fgColorToggle, bgColorToggle, tsColorToggle, bsColorToggle, selectColorToggle, transparentColorToggle; extern Widget pointButton, floodButton, lineButton, polylineButton, rectangleButton, polygonButton, circleButton, ellipseButton, eraseButton, selectButton; extern Widget viewport, tablet, tabletBorder, tabletFrame; extern Widget iconForm, iconSize, monoLabel; extern Widget fillToggle, magMenu_8x_tb; extern Widget formatMenu_xbm_tb, formatMenu_xpm_tb; extern Widget optionsMenu_grid, menu1, queryDialog, stdErrDialog; extern Widget tablet_wid; extern Window tablet_win; static int jskXerrorDebug(); static int jskXerrorIODebug(); extern Widget editMenu_undo_pb; void GetSessionInfo( void ); void Set_Gfx_Labels( Boolean ); void Init_Icons( Dimension width, Dimension height, Boolean saveFlag); int PixelTableLookup( Pixel pixelIn, Boolean allocNew); extern void Repaint_Tablet(Window, int, int, int, int); extern void Init_Widget_List(void); extern void Init_Pen_Colors(Widget); extern void Init_Color_Table(void); extern void RegisterDropSites(void); extern void Abort(char *); extern void DoErrorDialog(char *); char dash_list[2] = {1,1}; char err_str[80]; char start_file[256]; char start_size[80]; Widget clip_wid; GC scratch_gc; Position x_margin, y_margin; Pixmap pointPix, floodPix, linePix, polylinePix, rectPix; Pixmap polygonPix, circlePix, ellipsePix, eraserPix, selectPix; Pixmap rectSolidPix, circleSolidPix, polygonSolidPix, ellipseSolidPix; extern int successFormat, x_hot, y_hot; extern unsigned int width_ret, height_ret; /* Structure used on a save session to see if a dt is iconic */ typedef struct { int state; Window icon; } WM_STATE; /*************************************************************************** * * * Routine: Create_Gfx_Labels * * * * Purpose: Initialize all the global variables used by the icon editor. * * * ***************************************************************************/ void Create_Gfx_Labels( unsigned long fg, unsigned long bg ) { Arg args[10]; int i, depth; Pixmap q_markPix, mask; depth = XDefaultDepth(dpy, screen); /********** pointPix = XCreatePixmapFromBitmapData(dpy, root, point_bits, point_width, point_height, fg, bg, depth); floodPix = XCreatePixmapFromBitmapData(dpy, root, flood_bits, flood_width, flood_height, fg, bg, depth); linePix = XCreatePixmapFromBitmapData(dpy, root, line_bits, line_width, line_height, fg, bg, depth); polylinePix = XCreatePixmapFromBitmapData(dpy, root, polyline_bits, polyline_width, polyline_height, fg, bg, depth); rectPix = XCreatePixmapFromBitmapData(dpy, root, rectangle_bits, rectangle_width, rectangle_height, fg, bg, depth); polygonPix = XCreatePixmapFromBitmapData(dpy, root, polygon_bits, polygon_width, polygon_height, fg, bg, depth); circlePix = XCreatePixmapFromBitmapData(dpy, root, circle_bits, circle_width, circle_height, fg, bg, depth); ellipsePix = XCreatePixmapFromBitmapData(dpy, root, ellipse_bits, ellipse_width, ellipse_height, fg, bg, depth); eraserPix = XCreatePixmapFromBitmapData(dpy, root, eraser_bits, eraser_width, eraser_height, fg, bg, depth); selectPix = XCreatePixmapFromBitmapData(dpy, root, select_bits, select_width, select_height, fg, bg, depth); **********/ xpm_ReadAttribs.valuemask = READ_FLAGS; xpm_ReadAttribs.colorsymbols = colorSymbols; xpm_ReadAttribs.numsymbols = NUM_PENS; status = XpmCreatePixmapFromData(dpy, root, Circle, &circlePix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,2, "Cannot initialize button icon for circle")); status = XpmCreatePixmapFromData(dpy, root, CircleSolid, &circleSolidPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,4, "Cannot initialize button icon for solid circle")); status = XpmCreatePixmapFromData(dpy, root, Connected, &polylinePix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,6, "Cannot initialize button icon for polyline")); status = XpmCreatePixmapFromData(dpy, root, ConnectedClosed, &polygonPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,8, "Cannot initialize button icon for polygon")); status = XpmCreatePixmapFromData(dpy, root, ConnecClosedSolid, &polygonSolidPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,10, "Cannot initialize button icon for solid polygon")); status = XpmCreatePixmapFromData(dpy, root, Ellipse, &ellipsePix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,12, "Cannot initialize button icon for ellipse")); status = XpmCreatePixmapFromData(dpy, root, EllipseSolid, &ellipseSolidPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,14, "Cannot initialize button icon for solid ellipse")); status = XpmCreatePixmapFromData(dpy, root, Eraser, &eraserPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,16, "Cannot initialize button icon for eraser")); status = XpmCreatePixmapFromData(dpy, root, Line, &linePix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,18, "Cannot initialize button icon for line")); status = XpmCreatePixmapFromData(dpy, root, PaintBucket, &floodPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,20, "Cannot initialize button icon for flood")); status = XpmCreatePixmapFromData(dpy, root, Pencil, &pointPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,22, "Cannot initialize button icon for point")); status = XpmCreatePixmapFromData(dpy, root, Rectangle, &rectPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,24, "Cannot initialize button icon for rectangle")); status = XpmCreatePixmapFromData(dpy, root, RectangleSolid, &rectSolidPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,26, "Cannot initialize button icon for solid rectangle")); status = XpmCreatePixmapFromData(dpy, root, SelectArea, &selectPix, &mask, &xpm_ReadAttribs); if (status != XpmSuccess) Abort(GETSTR(10,28, "Cannot initialize button icon for select")); q_markPix = XCreatePixmapFromBitmapData(dpy, root, (char*)q_mark_bits, q_mark_width, q_mark_height, fg, bg, depth); i = 0; XtSetArg(args[i], XmNlabelPixmap, pointPix); i++; XtSetValues(pointButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, linePix); i++; XtSetValues(lineButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, eraserPix); i++; XtSetValues(eraseButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, floodPix); i++; XtSetValues(floodButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, polylinePix); i++; XtSetValues(polylineButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, selectPix); i++; XtSetValues(selectButton, args, i); i = 0; XtSetArg(args[i], XmNlabelPixmap, q_markPix); i++; XtSetValues(queryDialog, args, i); Set_Gfx_Labels(HOLLOW); } /*************************************************************************** * * * Routine: Init_Editor * * * * Purpose: Initialize all the global variables, states, widgets, etc, * * for the icon editor. This is a long, messy, somewhat * * rambling routine. * * * ***************************************************************************/ void Init_Editor( Widget wid ) { Window win; Arg args[10]; int i; Position lx, ly; /*** window ID of tablet ***/ tablet_win = 0; /*** Nothing needs to be saved, yet ***/ Dirty = False; /*** Initial Graphics states, pen color, etc. ***/ GraphicsOp = POINT; CurrentColor = COLOR1; ColorBlock = STATIC_COLOR; FillSolids = False; MagFactor = 8; pointCount = 0; /*** file I/O related globals ***/ last_fname[0] = '\0'; X_Hot = -1; Y_Hot = -1; XSetErrorHandler(jskXerrorDebug); XSetIOErrorHandler(jskXerrorIODebug); /*** Xlib-related globals ***/ dpy = XtDisplay(wid); win = XtWindow(wid); root = DefaultRootWindow(dpy); screen = DefaultScreen(dpy); screen_ptr = XtScreen(wid); black_pixel = BlackPixel(dpy, screen); white_pixel = WhitePixel(dpy, screen); Cmap = DefaultColormap(dpy, screen); /*** initialize global pixel table data ***/ pixelTable.pixelTableSize = 0; pixelTable.numItems = 0; pixelTable.lastFound = 0; pixelTable.item = NULL; /*** Initialize the GCs used by the app. ***/ Color_gc = XCreateGC(dpy, root, 0, 0); Mono_gc = XCreateGC(dpy, root, 0, 0); Grid_gc = XCreateGC(dpy, root, 0, 0); Erase_gc = XCreateGC(dpy, root, 0, 0); Flicker_gc = XCreateGC(dpy, root, 0, 0); scratch_gc = XCreateGC(dpy, root, 0, 0); XSetState(dpy, Flicker_gc, black_pixel, white_pixel, GXinvert, (DefaultDepthOfScreen(XtScreen(wid)) > 8) ? AllPlanes : 0x01); XSetSubwindowMode(dpy, Flicker_gc, IncludeInferiors); XSetDashes(dpy, Grid_gc, 0, dash_list, 2); XSetLineAttributes(dpy, Grid_gc, 0, LineDoubleDash, CapButt, JoinMiter); /*** Initialize the widget variables ***/ Init_Widget_List(); /*** Initialize the pen colors and the internal color table ***/ Init_Pen_Colors(wid); Init_Color_Table(); XSetForeground(dpy, Erase_gc, Transparent); /*** configure the color and mono icons to their initial size ***/ Init_Icons(icon_width, icon_height, DO_NOT_SAVE); xrdb.useBMS = FALSE; DtInitialize (dpy, wid, progName, progName); /*** Drop site registration must occur after DtInitialize() ***/ RegisterDropSites(); multiClickTime = XtGetMultiClickTime(dpy); /*** Now, do all the tedious widget initialization ***/ i = 0; XtSetArg(args[i], XmNset, True); i++; XtSetValues(StaticWid[CurrentColor], args, i); XtSetValues(GraphicOpsWid[GraphicsOp], args, i); XtSetValues(magMenu_8x_tb, args, i); XtSetValues(optionsMenu_grid, args, i); XtSetValues(formatMenu_xpm_tb, args, i); i = 0; XtSetArg(args[i], XmNbackground, Transparent); i++; XtSetValues(tablet_wid, args, i); XtSetValues(tabletBorder, args, i); XSetForeground(dpy, Color_gc, StaticPen[0]); XSetForeground(dpy, Mono_gc, StaticMono[0]); i = 0; XtSetArg(args[i], XmNset, FillSolids); i++; XtSetValues(fillToggle, args, i); i = 0; XtSetArg(args[i], XmNclipWindow, &clip_wid); i++; XtGetValues(viewport, args, i); x_margin = 0; y_margin = 0; #ifdef DEBUG if (debug) { stat_out("DEFAULT TIME-OUT VALUE IS %d MILLISECONDS\n", multiClickTime); stat_out("****CLIP WINDOW WIDGET = %d\n", clip_wid); stat_out(" TABLET OFFSETS [x,y] = [%d,%d]\n", x_margin, y_margin); } #endif i = 0; XtSetArg(args[i], XmNbackground, Transparent); i++; XtSetValues(clip_wid, args, i); i = 0; XtSetArg(args[i], XmNset, False); i++; XtSetValues(floodButton, args, i); XtSetValues(lineButton, args, i); XtSetValues(polylineButton, args, i); XtSetValues(rectangleButton, args, i); XtSetValues(polygonButton, args, i); XtSetValues(circleButton, args, i); XtSetValues(ellipseButton, args, i); XtSetValues(eraseButton, args, i); XtSetValues(selectButton, args, i); i = 0; XtSetArg(args[i], XmNset, True); i++; XtSetValues(pointButton, args, i); } /*************************************************************************** * * * Routine: GetMarginData * * * * Purpose: We need to get margin data AFTER these widgets are realized * * in order to get valid data... so do it here * * * ***************************************************************************/ void GetMarginData( void ) { Arg args[10]; int i; Position lx, ly; #ifdef DEBUG if (debug) stat_out("****** Getting margin data: x=%d y=%d\n", x_margin, y_margin); #endif i = 0; XtSetArg(args[i], XmNx, &lx); i++; XtSetArg(args[i], XmNy, &ly); i++; XtGetValues(tabletFrame, args, i); x_margin = lx; y_margin = ly; i = 0; XtSetArg(args[i], XmNx, &lx); i++; XtSetArg(args[i], XmNy, &ly); i++; XtGetValues(tablet_wid, args, i); x_margin += lx; y_margin += ly; #ifdef DEBUG if (debug) stat_out("****** margin data: x=%d y=%d\n", x_margin, y_margin); #endif } /*************************************************************************** * * * Routine: New_MagFactor * * * * Purpose: The user has just selected a new magnification factor for * * the fat pixels on the tablet. Update the MagFactor global * * variable and reapaint the visible portion of the tablet to * * reflect the change. * * * ***************************************************************************/ void New_MagFactor( int new_value ) { Arg args[10]; int i; #ifdef DEBUG if (debug) stat_out("****** Changing MagFactor to %d\n", new_value); #endif MagFactor = new_value; i = 0; XtSetArg(args[i], XmNwidth, (icon_width*MagFactor)); i++; XtSetArg(args[i], XmNheight, (icon_height*MagFactor)); i++; XtSetValues(tablet_wid, args, i); if (Selected) Set_HotBox_Coords(); /* This code does not seem to be needed and since it slows down the grid drawing I'll take it out */ /*Repaint_Exposed_Tablet();*/ } /*************************************************************************** * * * Routine: New_FileFormat * * * * Purpose: Update the fileFormat value to reflect the user's current * * choice of default file output formats. * * * ***************************************************************************/ void New_FileFormat( int new_value ) { #ifdef DEBUG if (debug) { stat_out("****** Changing Output File Format to "); switch (new_value) { case FORMAT_XPM : stat_out("XPM\n"); break; case FORMAT_XBM : stat_out("XBM\n"); break; default : stat_out("UNKNOWN\n"); break; } /* switch */ } /* if */ #endif fileFormat = new_value; } /*************************************************************************** * * * Routine: Icon_Coords * * * * Purpose: Convert a set of [x,y] values (acquired from the tablet) * * into the equivalent [x,y] values they represent on the * * actual icon being created/modified. * * * ***************************************************************************/ void Icon_Coords( int normal_x, int normal_y, int *fat_x, int *fat_y ) { *fat_x = normal_x / MagFactor; *fat_y = normal_y / MagFactor; } /*************************************************************************** * * * Routine: Tablet_Coords * * * * Purpose: Convert a set of fat [x,y] values back into raw [x,y] values * * which map to the top-left corner of the fat pixel value. * * * ***************************************************************************/ void Tablet_Coords( int fat_x, int fat_y, int *raw_x, int *raw_y ) { *raw_x = fat_x * MagFactor; *raw_y = fat_y * MagFactor; } /*************************************************************************** * * * Routine: Quantize * * * * Purpose: Adjust a set of [x,] values so that they mark the top-left * * corner (or the middle, depending on the 'center' flag) of * * whatever 'fat' pixel they map onto. This will insure that * * any operation involving rubberband lines leaps from fat * * pixel center to fat pixel center, providing a clear visual * * indicator of which pixel currently contains the line/point. * * * ***************************************************************************/ void Quantize( int *x, int *y, int center ) { int lx, ly, half; lx = *x; ly = *y; half = MagFactor/2; if ((lx%MagFactor) != 0) lx = (lx / MagFactor) * MagFactor; if ((ly%MagFactor) != 0) ly = (ly / MagFactor) * MagFactor; if (center) { lx += half; ly += half; } *x = lx; *y = ly; } /*************************************************************************** * * * Routine: Repaint_Exposed_Tablet * * * * Purpose: Repaint the rectangular section of the tablet currently * * visible in the clipping area widget of the scrolled window * * widget. To do this, we get the current width and height * * of the clipping area widget, the current width and height * * of the drawing area manager widget (the clipping area * * widget's immediate child), and the x and y position of the * * drawing area manager widget. This will allow us to cal- * * culate what portion of the tablet (drawn button widget) is * * currently visible in the clipping area widget. We then * * request th Repaint_Tablet() routine to repaint that portion * * of the drawn button. * * * ***************************************************************************/ void Repaint_Exposed_Tablet( void ) { int i; Arg args[10]; Position t_x, t_y; Dimension c_width, c_height, t_width, t_height; i = 0; XtSetArg(args[i], XmNwidth, &c_width); i++; XtSetArg(args[i], XmNheight, &c_height); i++; XtGetValues(clip_wid, args, i); i = 0; XtSetArg(args[i], XmNx, &t_x); i++; XtSetArg(args[i], XmNy, &t_y); i++; XtSetArg(args[i], XmNwidth, &t_width); i++; XtSetArg(args[i], XmNheight, &t_height); i++; XtGetValues(tabletBorder, args, i); t_x += x_margin; t_y += y_margin; t_x = -t_x; t_y = -t_y; if (t_x < 0) t_x = 0; if (t_y < 0) t_y = 0; Repaint_Tablet(tablet_win, t_x, t_y, c_width, c_height); } /*************************************************************************** * * * Routine: Repaint_Tablet * * * * Purpose: Repaint the rectangular section of the tablet described by * * the [x,y,width,height] values in the XRectangle. * * * ***************************************************************************/ void Repaint_Tablet( Window win, int x, int y, int width, int height ) { int i, j, lx, ly; XImage *scratch_img; scratch_img = XGetImage(dpy, color_icon, 0, 0, icon_width, icon_height, AllPlanes, ZPixmap); #ifdef DEBUG if (debug) stat_out("****** Repaint_Tablet: x,y=%d,%d w,h=%d,%d\n", x,y,width,height); #endif for (i=x; i= 0) && (lx < icon_width) && (ly >= 0) && (ly < icon_height)) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, lx, ly)); XFillRectangle(dpy, tablet_win, scratch_gc, lx*MagFactor, ly*MagFactor, MagFactor, MagFactor); if (hotSpot) if ((lx == X_Hot) && (ly == Y_Hot)) { XDrawLine(dpy, tablet_win, Grid_gc, lx*MagFactor, ly*MagFactor+MagFactor, lx*MagFactor+MagFactor, ly*MagFactor); XDrawLine(dpy, tablet_win, Grid_gc, lx*MagFactor, ly*MagFactor, lx*MagFactor+MagFactor, ly*MagFactor+MagFactor); } } /* if */ } /* for */ Quantize(&x, &y, False); width += (MagFactor*2); height += (MagFactor*2); /* Draw the grid if Enabled.... */ if (GridEnabled) { for (i=x; i<=x+width+MagFactor; i+=MagFactor) XDrawLine(dpy, win, Grid_gc, i, y, i, (y+height)); for (i=y; i<=y+height+MagFactor; i+=MagFactor) XDrawLine(dpy, win, Grid_gc, x, i, (x+width), i); } XDestroyImage(scratch_img); } /*************************************************************************** * * * Routine: Paint_Tile * * * * Purpose: Paint a single rectangular tile of size MagFactor x * * MagFactor with the color supplied in the passed GC. * * The X and Y parameters are coordinates for the 1:1 * * sized icon, and not direct coordinates for the tablet. * * * ***************************************************************************/ void Paint_Tile( int x, int y, GC gc ) { XFillRectangle(dpy, tablet_win, gc, x*MagFactor, y*MagFactor, MagFactor, MagFactor); if (GridEnabled) XDrawRectangle(dpy, tablet_win, Grid_gc, x*MagFactor, y*MagFactor, MagFactor, MagFactor); if (hotSpot) if ((x == X_Hot) && (y == Y_Hot)) { XDrawLine(dpy, tablet_win, Grid_gc, x*MagFactor, y*MagFactor+MagFactor, x*MagFactor+MagFactor, y*MagFactor); XDrawLine(dpy, tablet_win, Grid_gc, x*MagFactor, y*MagFactor, x*MagFactor+MagFactor, y*MagFactor+MagFactor); } } /*************************************************************************** * * * Routine: Transfer_Back_Image * * * * Purpose: Paint a single rectangular tile of size MagFactor x * * MagFactor with the color supplied in the passed GC. * * The [x,y] coordinate pairs are both icon coordinates, * * not tablet coordinates. * * * ***************************************************************************/ void Transfer_Back_Image( int x1, int y1, int x2, int y2, Boolean tflag ) { int min_x, min_y, max_x, max_y, i, j; XImage *scratch_img; #ifdef DEBUG if (debug) { stat_out("Entering Transfer_Back_Image\n"); stat_out("Values are x1:%d, y1:%d, x2:%d, y2:%d, flag = ", x1, y1, x2, y2); stat_out(" icon size is width:%d, height:%d\n", icon_width, icon_height); switch(tflag) { case HOLLOW : stat_out("HOLLOW\n"); break; case FILL : stat_out("FILL\n"); break; default : stat_out("UNKNOWN\n"); break; } /* switch */ } #endif min_x = ((x1 < x2) ? x1 : x2); min_y = ((y1 < y2) ? y1 : y2); max_x = ((x1 > x2) ? x1 : x2); max_y = ((y1 > y2) ? y1 : y2); /*** make sure min_x and min_y are within icon ***/ if (min_x < 0) min_x = 0; if (min_y < 0) min_y = 0; /*** make sure max_x and max_y are within icon ***/ if (max_x >= icon_width) max_x = icon_width-1; if (max_y >= icon_height) max_y = icon_height-1; scratch_img = XGetImage(dpy, color_icon, 0, 0, icon_width, icon_height, AllPlanes, ZPixmap); /*** do the entire rectangular area... ***/ if (tflag == FILL) { for (i = min_x; i <= max_x; i++) for (j = min_y; j <= max_y; j++) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, j)); Paint_Tile(i, j, scratch_gc); } /* for */ } /* if */ /*** ...or just do the border of rectangle ***/ else { for (i = min_x; i <= max_x; i++) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, min_y)); Paint_Tile(i, min_y, scratch_gc); } for (i = min_x; i <= max_x; i++) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, max_y)); Paint_Tile(i, max_y, scratch_gc); } for (i = min_y; i <= max_y; i++) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, min_x, i)); Paint_Tile(min_x, i, scratch_gc); } for (i = min_y; i <= max_y; i++) { XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, max_x, i)); Paint_Tile(max_x, i, scratch_gc); } } /* else */ XDestroyImage(scratch_img); #ifdef DEBUG if (debug) stat_out("Leaving Transfer_Back_Image\n"); #endif } /*************************************************************************** * * * Routine: Init_Widget_list * * * * Purpose: Initialize all the pen color widgets into 2 widget ID * * arrays, to simplify referencing them later. * * * ***************************************************************************/ void Init_Widget_List( void ) { GraphicOpsWid[POINT] = pointButton; GraphicOpsWid[FLOOD] = floodButton; GraphicOpsWid[LINE] = lineButton; GraphicOpsWid[POLYLINE] = polylineButton; GraphicOpsWid[RECTANGLE] = rectangleButton; GraphicOpsWid[POLYGON] = polygonButton; GraphicOpsWid[CIRCLE] = circleButton; GraphicOpsWid[ELLIPSE] = ellipseButton; GraphicOpsWid[ERASER] = eraseButton; GraphicOpsWid[SELECT] = selectButton; DynamicWid[BG_COLOR-BG_COLOR] = bgColorToggle; DynamicWid[FG_COLOR-BG_COLOR] = fgColorToggle; DynamicWid[TS_COLOR-BG_COLOR] = tsColorToggle; DynamicWid[BS_COLOR-BG_COLOR] = bsColorToggle; DynamicWid[SELECT_COLOR-BG_COLOR] = selectColorToggle; DynamicWid[TRANS_COLOR-BG_COLOR] = transparentColorToggle; StaticWid[COLOR1] = color_pb1; StaticWid[COLOR2] = color_pb2; StaticWid[COLOR3] = color_pb3; StaticWid[COLOR4] = color_pb4; StaticWid[COLOR5] = color_pb5; StaticWid[COLOR6] = color_pb6; StaticWid[COLOR7] = color_pb7; StaticWid[COLOR8] = color_pb8; StaticWid[GREY1] = grey_pb1; StaticWid[GREY2] = grey_pb2; StaticWid[GREY3] = grey_pb3; StaticWid[GREY4] = grey_pb4; StaticWid[GREY5] = grey_pb5; StaticWid[GREY6] = grey_pb6; StaticWid[GREY7] = grey_pb7; StaticWid[GREY8] = grey_pb8; tablet_wid = tablet; } /*************************************************************************** * * * Routine: Init_Pen_Colors * * * * Purpose: Initialize all the pen colors (both Static and Dynamic) and * * set the appropriate fg/bg colors for each pen button widget * * to reflect this. * * * ***************************************************************************/ void Init_Pen_Colors( Widget wid ) { Window win; Pixel transFg; XColor exact_def; Arg arg[10]; int i, j, pixelTableIndex; i = 0; XtSetArg(arg[i], XmNbackground, &Background); i++; XtGetValues(wid, arg, i); XmGetColors(screen_ptr, Cmap, Background, &Foreground, &TopShadow, &BottomShadow, &Select); #ifdef DEBUG if (debug) stat_out("Return from XmGetColors()\n"); #endif /*** Set FOREGROUND Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, Foreground); i++; pixelTableIndex = PixelTableLookup (Foreground, False); if (PIXEL_TABLE_MONO(pixelTableIndex) == white_pixel) { XtSetArg(arg[i], XmNforeground, black_pixel); i++; } else { XtSetArg(arg[i], XmNforeground, white_pixel); i++; } XtSetValues(fgColorToggle, arg, i); /*** Set BACKGROUND Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, Background); i++; XtSetArg(arg[i], XmNforeground, Foreground); i++; XtSetValues(bgColorToggle, arg, i); /*** Set TOP_SHADOW Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, TopShadow); i++; if (TopShadow == Foreground) /* B & W */ { XtSetArg(arg[i], XmNforeground, Background); i++; } else { XtSetArg(arg[i], XmNforeground, Foreground); i++; } XtSetValues(tsColorToggle, arg, i); /*** Set BOTTOM_SHADOW Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, BottomShadow); i++; if (BottomShadow == Foreground) /* B & W */ { XtSetArg(arg[i], XmNforeground, Background); i++; } else { XtSetArg(arg[i], XmNforeground, Foreground); i++; } XtSetValues(bsColorToggle, arg, i); /*** Set SELECT Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, Select); i++; XtSetArg(arg[i], XmNforeground, Foreground); i++; XtSetValues(selectColorToggle, arg, i); /*** Set TRANSPARENT Button fg/bg colors ***/ i = 0; XtSetArg(arg[i], XmNbackground, &Transparent); i++; XtSetArg(arg[i], XmNforeground, &transFg); i++; XtGetValues(menu1, arg, i); i = 0; XtSetArg(arg[i], XmNbackground, Transparent); i++; XtSetArg(arg[i], XmNforeground, transFg); i++; XtSetValues(transparentColorToggle, arg, i); /*** Store the colors in the dynamic array ***/ DynamicPen[BG_COLOR-BG_COLOR] = Background; DynamicPen[FG_COLOR-BG_COLOR] = Foreground; DynamicPen[TS_COLOR-BG_COLOR] = TopShadow; DynamicPen[BS_COLOR-BG_COLOR] = BottomShadow; DynamicPen[SELECT_COLOR-BG_COLOR] = Select; DynamicPen[TRANS_COLOR-BG_COLOR] = Transparent; #ifdef DEBUG if (debug) stat_out("Backgrounds set for all 6 dynamic colors\n"); #endif /*** STUB *********************************************************/ DynamicMono[BG_COLOR-BG_COLOR] = black_pixel; DynamicMono[FG_COLOR-BG_COLOR] = white_pixel; DynamicMono[TS_COLOR-BG_COLOR] = white_pixel; DynamicMono[BS_COLOR-BG_COLOR] = black_pixel; DynamicMono[SELECT_COLOR-BG_COLOR] = white_pixel; DynamicMono[TRANS_COLOR-BG_COLOR] = Transparent; for (i=0; i 0) { colorTable[i][j] = (char *) XtMalloc(strlen(color_table[i][j])+1); if (!colorTable[i][j]) Abort(GETSTR(10,48, "No memory(5)")); strcpy(colorTable[i][j], color_table[i][j]); } /* if */ } /* for(j...) */ } /* for(i...) */ xpm_WriteAttribs.ncolors = NUM_PENS; xpm_WriteAttribs.hints_cmt = hints_cmt; xpm_WriteAttribs.colors_cmt = colors_cmt; xpm_WriteAttribs.pixels_cmt = pixels_cmt; xpm_WriteAttribs.mask_pixel = 0x80000000; #ifdef DEBUG if (debug) Dump_AttribStruct(&xpm_WriteAttribs); #endif } /*************************************************************************** * * * Routine: Size_IconForm * * * * Purpose: Given new dimensions for the Color and Mono icon widgets, * * calculate and set the new overall dimensions for the icon * * form widget (iconForm) which holds both of them and their * * labels. * * * ***************************************************************************/ void Size_IconForm( Dimension width, Dimension height ) { Arg args[10]; int i, top_offset; Dimension label1_w, label1_h, label2_w, label2_h; Dimension form_width, form_height, junk; XmString label1_str, label2_str; XmFontList label_fontlist; Position diff; #ifdef DEBUG if (debug) stat_out("Entering Size_IconForm\n"); #endif /********************************************************************* * Before re-sizing the 2 icons (up or down), make sure their parent * * form's width is at least wide enough to fully show the two label * * gadgets (iconSize and monoLabel). If the icon widths are smaller * * than this, set offsets to center them on the space provided. * *********************************************************************/ /********************************************************************* * First, get the minimum usable widths for the two label gadgets, * * and their current heights. * *********************************************************************/ i = 0; XtSetArg(args[i], XmNfontList, &label_fontlist); i++; XtSetArg(args[i], XmNlabelString, &label1_str); i++; XtGetValues(iconSize, args, i); i = 0; XtSetArg(args[i], XmNlabelString, &label2_str); i++; XtGetValues(monoLabel, args, i); XmStringExtent(label_fontlist, label1_str, &label1_w, &junk); XmStringExtent(label_fontlist, label2_str, &label2_w, &junk); i = 0; XtSetArg(args[i], XmNheight, &label1_h); i++; XtGetValues(iconSize, args, i); i = 0; XtSetArg(args[i], XmNheight, &label2_h); i++; XtGetValues(monoLabel, args, i); /********************************************************************* * If the min. width for either label gadget is greater than the * * current icon widths, use half the difference between the two * * widths as a left and right offset for the two icon (drawn button) * * widgets. * *********************************************************************/ if ((label1_w > width) || (label2_w > width)) diff = (Position) (((label1_w > label2_w) ? label1_w : label2_w) - width) / 2; else diff = 0; i = 0; XtSetArg(args[i], XmNleftOffset, diff); i++; XtSetValues(iconImage, args, i); XtSetValues(monoImage, args, i); /********************************************************************* * The overall form dimensions should be as follows: the form width * * will be the greater of the icon widths, or the widths of the two * * label gadgets. The form height will be the sum of the two icon * * heights, plus the sum of heights of the two label gadgets, plus * * the vertical offset between the bottom of the first label and the * * top of the second icon. * *********************************************************************/ i = 0; XtSetArg(args[i], XmNtopOffset, &top_offset); i++; XtGetValues(monoImage, args, i); form_width = max(width, (Dimension)max(label1_w, label2_w)); form_height = (height*2) + label1_h + label2_h + top_offset; #ifdef DEBUG if (debug) { stat_out(" form_width = %d (of %d,%d,%d)\n", form_width, width, label1_w, label2_w); stat_out(" form_height = %d\n", form_height); } #endif i = 0; XtSetArg(args[i], XmNwidth, form_width); i++; XtSetArg(args[i], XmNheight, form_height); i++; XtSetValues(iconForm, args, i); #ifdef DEBUG if (debug) stat_out("Leaving Size_IconForm\n"); #endif } /*************************************************************************** * * * Routine: Init_Icons * * * * Purpose: Initialize new color and mono icons at program start-up * * and at the following times: * * o When 'New' is selected from the 'File' pull-down menu. * * o When 'Resize Icon' is selected from the 'Edit' pull-down * * menu. * * o When 'Load' is selected from the 'File' pull-down menu, * * and a new file is read in. * * o When 'Grab Screen Image' is selected from the 'Edit' * * pull-down menu, and the image is loaded into the editor. * * * * This routine sizes the iconImage, monoImage, and tablet * * widgets to the new dimensions (*MagFactor, and +1 in the * * case of the tablet widget). It also creates the application-* * internal Pixmaps associated with the iconImage and monoImage.* * If the 'saveFlag' flag is 'True', it is assumed that the * * current icons are being resized and that there are existing * * images that need to be retained. In this case, the new * * Pixmaps are created and the old Pixmaps are copied onto the * * new ones, before the old Pixmaps are freed. * * * ***************************************************************************/ void Init_Icons( Dimension width, Dimension height, Boolean saveFlag ) { Pixmap tmpPix; Pixmap tmp_color, tmp_mono; char text[40]; Arg args[10]; int i, x_offset, y_offset; XmString local_str; #ifdef DEBUG if (debug) stat_out("Entering Init_Icons: flag=%d\n", saveFlag); stat_out(" Init_Icons: color=%x mono=%x\n", color_icon, mono_icon); #endif tmp_color = 0; tmp_mono = 0; /*** App. init or 'New Icon' ***/ if (!saveFlag) { if (color_icon) XFreePixmap(dpy, color_icon); if (mono_icon) XFreePixmap(dpy, mono_icon); } /*** Resizing the existing icon ***/ else { if (color_icon) tmp_color = color_icon; if (mono_icon) tmp_mono = mono_icon; x_offset = 0; y_offset = 0; } color_icon = XCreatePixmap(dpy, root, width, height, DefaultDepth(dpy, screen)); mono_icon = XCreatePixmap(dpy, root, width, height, DefaultDepth(dpy, screen)); if ((color_icon == 0) || (mono_icon == 0)) Abort(GETSTR(10,50, "Cannot initialize application icon storage")); XSetForeground(dpy, scratch_gc, Transparent); XFillRectangle(dpy, color_icon, scratch_gc, 0, 0, width, height); XFillRectangle(dpy, mono_icon, scratch_gc, 0, 0, width, height); sprintf(text, "%d x %d", width, height); i = 0; local_str = XmStringCreateLocalized(text); XtSetArg(args[i], XmNlabelString, local_str); i++; XtSetValues(iconSize, args, i); XmStringFree(local_str); i = 0; XtSetArg(args[i], XmNwidth, width); i++; XtSetArg(args[i], XmNheight, height); i++; XtSetValues(iconImage, args, i); XtSetValues(monoImage, args, i); /********************************************************************* * Call Size_IconForm() to re-do the layout of the iconForm widget, * * which contains the iconImage, iconSize, monoImage, and monoLabel * * widgets. * *********************************************************************/ Size_IconForm(width, height); if (saveFlag) { XCopyArea(dpy, tmp_color, color_icon, Color_gc, 0, 0, icon_width, icon_height, x_offset, y_offset); XCopyArea(dpy, tmp_mono, mono_icon, Mono_gc, 0, 0, icon_width, icon_height, x_offset, y_offset); if (tmp_color) XFreePixmap(dpy, tmp_color); if (tmp_mono) XFreePixmap(dpy, tmp_mono); } if (XtWindow(iconImage)) XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc, 0, 0, width, height, 0, 0); if (XtWindow(monoImage)) XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc, 0, 0, width, height, 0, 0); i = 0; XtSetArg(args[i], XmNwidth, ((width*MagFactor)+1)); i++; XtSetArg(args[i], XmNheight, ((height*MagFactor)+1)); i++; XtSetValues(tablet_wid, args, i); icon_width = width; icon_height = height; /* This code does not seem to be needed and since it slows down the grid drawing I'll take it out for now*/ /* if (tablet_win) Repaint_Exposed_Tablet(); */ #ifdef DEBUG if (debug) stat_out("Leaving Init_Icons\n"); #endif } static void TransferCallback( Widget w, XtPointer client_data, XtPointer call_data) { DtDndTransferCallback transferInfo = (DtDndTransferCallback) call_data; if (transferInfo->reason == DtCR_DND_TRANSFER && transferInfo->operation == XmDROP_COPY) { Process_DropCheckOp(w, client_data, call_data); } else { transferInfo->status = DtDND_FAILURE; } } static void AnimateCallback( Widget w, XtPointer client_data, XtPointer call_data) { DtDndDropAnimateCallbackStruct *animateInfo = (DtDndDropAnimateCallbackStruct *) call_data; if (animateInfo->reason == DtCR_DND_DROP_ANIMATE) { Process_DropOp(w, client_data, call_data); } } /*************************************************************************** * * * Routine: RegisterDropSites * * * * Purpose: Register the tablet as a valid drop zone. * * * ***************************************************************************/ void RegisterDropSites( void ) { static XtCallbackRec transferCB[] = { {TransferCallback, NULL}, {NULL, NULL} }; static XtCallbackRec animateCB[] = { {AnimateCallback, NULL}, {NULL, NULL} }; Arg args[3]; int n; Widget clipWin; XtSetArg(args[0], XmNclipWindow, &clipWin); XtGetValues(viewport, args, 1); /* * This code makes assumptions about the order of the arguments. * XmNanimationStyle is assumed to be first and * DtNregisterChildren is assumed to be last */ n = 0; XtSetArg(args[n], XmNanimationStyle, XmDRAG_UNDER_NONE); n++; /* first */ XtSetArg(args[n], DtNdropAnimateCallback, animateCB); n++; XtSetArg(args[n], DtNregisterChildren, True); n++; /* last */ DtDndDropRegister(clipWin, DtDND_FILENAME_TRANSFER, XmDROP_COPY, (XtCallbackList) transferCB, args, n); DtDndDropRegister(tabletBorder, DtDND_FILENAME_TRANSFER, XmDROP_COPY, (XtCallbackList) transferCB, args, n); DtDndDropRegister(tabletFrame, DtDND_FILENAME_TRANSFER, XmDROP_COPY, (XtCallbackList) transferCB, args, n); DtDndDropRegister(tablet, DtDND_FILENAME_TRANSFER, XmDROP_COPY, (XtCallbackList) transferCB, args, n - 1); /* * Once the drag and drop library is fixed, the following calls * will not be necessary. Currently the dnd library does not pass on * Motif resource values, in this case XmNanimationStyle. */ XmDropSiteUpdate(clipWin, args, 1); XmDropSiteUpdate(tabletBorder, args, 1); XmDropSiteUpdate(tabletFrame, args, 1); XmDropSiteUpdate(tablet, args, 1); } /*************************************************************************** * * * Routine: Abort * * * * Purpose: Print a fatal error message and then exit. * * * ***************************************************************************/ void Abort( char *str ) { _DtSimpleError (progName, DtError, NULL, str, NULL); exit(-1); } /*************************************************************************** * * * Routine: stat_out * * * * Purpose: Generate a debug message to stderr. Flush stdout, and then * * print the message(s) to stderr and flush stderr. By doing * * an fflush after each fprintf, we can always determin where * * in the code the process is running. The stat_out() routine * * is invoked like printf() with up to 7 arguments. It is * * source-code identical to the outl() routine used in the xwd * * and xwud utilities which are part of standard X11. * * * *X11***********************************************************************/ void stat_out( char *msg, char *arg0, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5, char *arg6 ) { /* static char str[1024]; */ fflush(stdout); fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6); fflush(stderr); /* sprintf(str, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6); _DtSimpleError ("dticon-stat_out", DtError, NULL, str, NULL);*/ } /*************************************************************************** * * * Routine: PixelTableClear * * * * Purpose: Reset the pixel table to force subsequent lookups to get * * new pixel information. Do not free up space for table. * * * *X11***********************************************************************/ void PixelTableClear(void) { pixelTable.numItems = 0; pixelTable.lastFound = 0; } /*************************************************************************** * * * Routine: PixelTableLookup * * * * Purpose: Return index into the Pixel Table for the pixel passed in. * * If the pixel passed in isn't already in the table, it will * * be added. This may require allocating a larger pixel table. * * In order to clear the Pixel Table (which should be done each * * time a new image is being processed in order to get current * * pixel data) call PixelTableClear(). * * * * For performance, save the last lookup result, and check it * * first. This should improve performance unless image is very * * "dithered". The allocNew parameter will be set if the image * * was grabbed from screen. In this case, each "screen" pixel * * will need a new pixel allocated for it. * * * *X11***********************************************************************/ int PixelTableLookup( Pixel pixelIn, Boolean allocNew ) { int i, grayValue; XColor tmpXColor; /** first, check to see if the last lookup was for the same pixel **/ if (pixelTable.lastFound < pixelTable.numItems) if (pixelTable.item[pixelTable.lastFound].xcolor.pixel == pixelIn) return pixelTable.lastFound; /** look through table to see if there is an entry for this pixel **/ for (i=0; i ---*/ /*--- The NTSC formula for converting an RGB value into the ---*/ /*--- corresponding grayscale value is: ---*/ /*--- luminosity = .299 red + .587 green + .114 blue ---*/ grayValue = ( (int)((pixelTable.item[i].xcolor.red*299) + (pixelTable.item[i].xcolor.green*587) + (pixelTable.item[i].xcolor.blue*114)) / 1000) >> 8; if (grayValue < GAMMA_CUTOFF) pixelTable.item[i].mono = black_pixel; else pixelTable.item[i].mono = white_pixel; /** Allocate new color cell if needed (use old for mono conversion) **/ if (allocNew) { tmpXColor.red = pixelTable.item[i].xcolor.red; tmpXColor.green = pixelTable.item[i].xcolor.green; tmpXColor.blue = pixelTable.item[i].xcolor.blue; if (!XAllocColor(dpy, Cmap, &tmpXColor)) { /* for lack of something better, use the old color cell */ pixelTable.item[i].newCell = pixelTable.item[i].xcolor.pixel; DoErrorDialog(GETSTR(10,62,"Operation failed.\nColormap is full")); } else pixelTable.item[i].newCell = tmpXColor.pixel; } pixelTable.lastFound = i; return i; } /*************************************************************************** * * * Routine: Switch_FillSolids * * * * Purpose: Toggles the state of the global FillSolids flag, based on * * the XmNset resource for the fillToggle widget. * * * *X11***********************************************************************/ void Switch_FillSolids( void ) { Arg args[10]; int i; i = 0; XtSetArg(args[i], XmNset, &FillSolids); i++; XtGetValues(fillToggle, args, i); if (FillSolids) Set_Gfx_Labels(FILL); else Set_Gfx_Labels(HOLLOW); #ifdef DEBUG if (debug) stat_out("Fill_Solids toggle = %s\n", (FillSolids? "True" : "False")); #endif } /*************************************************************************** * * * Routine: Select_New_Pen * * * * Purpose: Changes the fg color of the pen GC, based on the parameter * * passed in. * * * *X11***********************************************************************/ void Select_New_Pen( int n ) { int new_block, new_pen; if (n < BG_COLOR) { new_block = STATIC_COLOR; new_pen = n; } else { new_block = DYNAMIC_COLOR; new_pen = n - BG_COLOR; } #ifdef DEBUG if (debug) { stat_out("**** n = %d, new_block = %d, new_pen = %d\n", n, new_block, new_pen); } #endif /*** if the new choice is the current pen, re-set it and return ***/ if ((new_block == ColorBlock) && (new_pen == CurrentColor)) { if (new_block == STATIC_COLOR) XmToggleButtonSetState(StaticWid[new_pen], True, False); else XmToggleButtonSetState(DynamicWid[new_pen], True, False); return; } /*** un-set the previous choice ***/ if (ColorBlock == STATIC_COLOR) XmToggleButtonSetState(StaticWid[CurrentColor], False, False); else XmToggleButtonSetState(DynamicWid[CurrentColor], False, False); #ifdef DEBUG if (debug) stat_out(" New pen color = %d\n", n); #endif ColorBlock = new_block; /*** STATIC or DYNAMIC? ***/ CurrentColor = new_pen; /*** index w/i the appropriate block ***/ XSetForeground(dpy, Color_gc, (ColorBlock ? DynamicPen[CurrentColor] : StaticPen[CurrentColor])); XSetForeground(dpy, Mono_gc, (ColorBlock ? DynamicMono[CurrentColor] : StaticMono[CurrentColor])); } /*************************************************************************** * * * Routine: Backup_Icons * * * * Purpose: Copy the current contents of the color and mono icons to * * their undo storage areas, just prior to modifying them with * * the current graphics operation. * * * *X11***********************************************************************/ void Backup_Icons( void ) { /*** If we're backing up the tablet contents, it's dirty ***/ /*** and may need to be saved to file at some point. ***/ Dirty = True; /*** if the icon sizes don't match the backup sizes, or ***/ /*** either of the backup icons don't exist, create them ***/ if ((icon_width != backup_width) || (icon_height != backup_height) || (!prev_color_icon) || (!prev_mono_icon)) { if (prev_color_icon) XFreePixmap(dpy, prev_color_icon); if (prev_mono_icon) XFreePixmap(dpy, prev_mono_icon); prev_color_icon = XCreatePixmap(dpy, root, icon_width, icon_height, DefaultDepth(dpy, screen)); prev_mono_icon = XCreatePixmap(dpy, root, icon_width, icon_height, DefaultDepth(dpy, screen)); backup_width = icon_width; backup_height = icon_height; } /*** now, copy the color and mono pixmap to the backup pixmaps ***/ XCopyArea(dpy, color_icon, prev_color_icon, Color_gc, 0, 0, icon_width, icon_height, 0, 0); XCopyArea(dpy, mono_icon, prev_mono_icon, Mono_gc, 0, 0, icon_width, icon_height, 0, 0); UndoFlag = True; XtSetSensitive( editMenu_undo_pb, True); } /*************************************************************************** * * * Routine: DoErrorDialog * * * * Purpose: Some error has just occurred in the application. Pop up * * the error dialog and display the message passed in. * * * *X11***********************************************************************/ void DoErrorDialog( char *str ) { int i; Arg arg[10]; XmString local_str; i = 0; local_str = XmStringCreateLocalized(str); XtSetArg(arg[i], XmNmessageString, local_str); i++; XtSetValues(stdErrDialog, arg, i); XmStringFree(local_str); XtManageChild(stdErrDialog); } /*************************************************************************** * * * Routine: DoQueryDialog * * * * Purpose: The user should be prompted on an action they're attempting. * * Pop up the query dialog and display the message passed in. * * * *X11***********************************************************************/ void DoQueryDialog( char *str ) { int i; Arg arg[10]; XmString local_str; static Widget w=NULL; XtPopup(dtIconShell, XtGrabNone); XMapRaised(XtDisplay(dtIconShell), XtWindow(dtIconShell)); if (!w) w = XmMessageBoxGetChild(queryDialog, XmDIALOG_CANCEL_BUTTON); i = 0; local_str = XmStringCreateLocalized(str); XtSetArg(arg[i], XmNmessageString, local_str); i++; XtSetValues(queryDialog, arg, i); XmStringFree(local_str); XtManageChild(queryDialog); XmProcessTraversal(w, XmTRAVERSE_CURRENT); } /*************************************************************************** * * * Routine: Do_GrabOp * * * * Purpose: Switch to GRAB mode. Grab the server and the pointer until * * the user has made a selection from the screen. The server * * and pointer are ungrabbed in Do_ButtonOp(). * * * * Note: Moved the server grab until the mouse button is pressed * * (beginning the screen grab) in order to give the windows * * time to repaint. This was needed specifically for the * * queryDialog used when the icon image is "Dirty". * * * *X11***********************************************************************/ void Do_GrabOp( void ) { Backup_G_Op = GraphicsOp; GraphicsOp = S_GRAB; cursor = XCreateFontCursor(dpy, XC_crosshair); XGrabPointer(dpy, root, False, ButtonPressMask|PointerMotionMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); } /*************************************************************************** * * * Routine: LoadGrabbedImage * * * * Purpose: Given an [x,y] coordinate, plus width and height, grab an * * XImage from the Root window and load it into the icon * * editor. * * * *X11***********************************************************************/ int LoadGrabbedImage( int x, int y, int width, int height ) { XImage *img, *mono_img; int i, j; int pixelTableIndex; #ifdef DEBUG if (debug) stat_out("LoadGrabbedImage: [%d,%d] - width: %d, height: %d\n", x, y, width, height); #endif img = NULL; if (width > 0 && height > 0) img = XGetImage(dpy, root, x, y, width, height, AllPlanes, format); XUngrabPointer (dpy, CurrentTime); XUngrabServer (dpy); XSync (dpy, False); if (!img) { DoErrorDialog( GETSTR(10,60, "Screen image capture failed") ); return(False); } /********************************************************************* * OK, now that we've got the image, we need to convert the entire * * thing to pixels that the icon editor won't lose control over. * * To do this, we find all the pixel values in the image and request * * equivalent read-only colors in the colormap (we won't be drawing * * with any pen colors we don't already have). Once the requests to * * the Cmap have been honored, we go thru the image one more time * * and replace each old pixel with the correct new value. * * NOTE: Old code assumed 256 max colors... NOT OKAY. Added dynamic * * pixel table for color lookup, which also handles allocating * * the new read-only color. - julie * *********************************************************************/ /********************************************************************* * Dup the XImage so there'll be two identical copies: one to * * update with the new color values, and one with which to create * * a monochrome equivalent. * *********************************************************************/ mono_img = XSubImage(img, 0, 0, img->width, img->height); if (!mono_img) { DoErrorDialog( GETSTR(10,60, "Screen image capture failed") ); return(False); } /* force new pixel lookup, in case pixel data has changed */ PixelTableClear(); for (i=0; iwidth; i++) { for (j=0; jheight; j++) { pixelTableIndex = PixelTableLookup(XGetPixel(img, i, j), True); XPutPixel(img, i, j, PIXEL_TABLE_NEW_CELL(pixelTableIndex)); XPutPixel(mono_img, i, j, PIXEL_TABLE_MONO(pixelTableIndex)); } } Backup_Icons(); Init_Icons(img->width, img->height, DO_NOT_SAVE); XPutImage(dpy, color_icon, Color_gc, img, 0, 0, 0, 0, img->width, img->height); XPutImage(dpy, mono_icon, Mono_gc, mono_img, 0, 0, 0, 0, img->width, img->height); XDestroyImage(img); XDestroyImage(mono_img); return(True); } /*************************************************************************** * * * Routine: ParseAppArgs * * * * Purpose: Parse the invocation arguments, looking for '-f' and '-x'. * * This routine is invoked once by dticon. * * * * Each of the args should be accompanied by a parameter. If * * one does not exist, abort dticon with the appropriate * * error message. Otherwise, store the parameter in a global * * variable for processing by ProcessAppArgs() (called once * * from event.c). * * * *X11***********************************************************************/ void ParseAppArgs( int num, char *cmd[] ) { int i; char *cmd_arg; #ifdef DEBUG if (debug) stat_out("Entering ParseAppArgs\n"); #endif for (i=0; istate == IconicState) sprintf(bufr, "*iconic: True\n"); else sprintf(bufr, "*iconic: False\n"); write (fd, bufr, strlen(bufr)); /*** Get and write out the geometry info for our Window ***/ x = XtX(dtIconShell); y = XtY(dtIconShell); width = XtWidth(dtIconShell); height = XtHeight(dtIconShell); /* Modify x & y to take into account window mgr frames * This is pretty bogus, but I don't know a better way to do it. */ extData = _XmGetWidgetExtData(dtIconShell, XmSHELL_EXTENSION); vendorExt = (XmVendorShellExtObject)extData->widget; x -= vendorExt->vendor.xOffset; y -= vendorExt->vendor.yOffset; snprintf(bufr, sizeof(bufr), "*x: %d\n", x); write (fd, bufr, strlen(bufr)); snprintf(bufr, sizeof(bufr), "*y: %d\n", y); write (fd, bufr, strlen(bufr)); snprintf(bufr, sizeof(bufr), "*width: %d\n", width); write (fd, bufr, strlen(bufr)); snprintf(bufr, sizeof(bufr), "*height: %d\n", height); if (last_fname[0] != '\0') { write (fd, bufr, strlen(bufr)); snprintf(bufr, sizeof(bufr), "*file: %s\n", last_fname); } if(-1 == write (fd, bufr, strlen(bufr))) { fprintf(stderr, "write() to session failed\n"); XtFree ((char *)path); XtFree ((char *)name); close(fd); return; } n = 0; xa_CommandStr[n] = execName; n++; xa_CommandStr[n] = "-session"; n++; xa_CommandStr[n] = name; n++; XSetCommand(dpy, XtWindow(dtIconShell), xa_CommandStr, n); XtFree ((char *)path); XtFree ((char *)name); close(fd); /* Don't exit yet, SM needs time to get the new commandStr.*/ } /*************************************************************************** * * * Routine: GetSessionInfo * * * * Purpose: get dticon session information * **************************************************************************/ #define DEFAULT_WIDTH 536 #define DEFAULT_HEIGHT 477 void GetSessionInfo( void ) { XrmDatabase db; char *tmpStr, *tmpStr2; char *path; XrmName xrm_name[5]; XrmRepresentation rep_type; XrmValue value; #ifdef DEBUG if (debug) stat_out("GetSessionInfo\n"); #endif if (xrdb.session == NULL) { session.useSession = False; return; } else session.useSession = True; /*** Open the resource database file ***/ /* TopLevel is used because dtIconShell isn't created yet... */ /* okay because it only uses it to get a display, not a window */ if (DtSessionRestorePath(TopLevel, &path, xrdb.session) == False) path = xrdb.session; if ((db = XrmGetFileDatabase (path)) == NULL) { tmpStr = GETSTR(16,22, "Couldn't restore session from file"); tmpStr2 = (char *)XtMalloc(strlen(tmpStr) + strlen(path)+ 3); sprintf(tmpStr2, "%s: %s\n", tmpStr, path); _DtSimpleErrnoError(progName, DtError, NULL, tmpStr2, NULL); XtFree(tmpStr2); if (path != xrdb.session) XtFree(path); session.useSession = False; return; } if (path != xrdb.session) XtFree(path); /*** now get the information we want from the database ***/ /*** make sure values are at least somewhat reasonable ***/ xrm_name[1] = '\0'; /* get x position */ xrm_name[0] = XrmStringToQuark ("x"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) session.x = (Position)atoi((char *)value.addr); else session.x = 100; if (session.x < 0) session.x = 0; /* get y position */ xrm_name[0] = XrmStringToQuark ("y"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) session.y = (Position)atoi((char *)value.addr); else session.y = 100; if (session.y < 0) session.y = 0; /* get width */ xrm_name[0] = XrmStringToQuark ("width"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) session.width = (Dimension)atoi((char *)value.addr); else session.width = DEFAULT_WIDTH; if (session.width < DEFAULT_WIDTH) session.width = DEFAULT_WIDTH; /* get height */ xrm_name[0] = XrmStringToQuark ("height"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) session.height = (Dimension)atoi((char *)value.addr); else session.height = DEFAULT_HEIGHT; if (session.height < DEFAULT_HEIGHT) session.height = DEFAULT_HEIGHT; /* get iconic state */ xrm_name[0] = XrmStringToQuark ("iconic"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) { if ( value.addr!=NULL && strcmp((char *)value.addr, "True")==0 ) session.iconicState = IconicState; else session.iconicState = NormalState; } /* get file name */ xrm_name[0] = XrmStringToQuark ("file"); if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) { strncpy(start_file, value.addr, 255); } else start_file[0] = '\0'; } /*************************************************************************** * * * Routine: ChangeTitle * * * * Purpose: Put the file name in the window title... * ***************************************************************************/ void ChangeTitle(void) { static char *dialogTitle = NULL; Arg al[10]; int ac; char *name; char *title; char *tmpStr; Boolean freeName; if (!dialogTitle) { name = GETSTR(12, 1, "Icon Editor"); dialogTitle = XtMalloc (strlen(name) + 4); sprintf(dialogTitle, "%s - ", name); } if (*last_fname) { if (name = strrchr(last_fname, '/')) name++; else name = last_fname; freeName = False; } else { tmpStr = GETSTR(10, 66, "(UNTITLED)"); name = XtNewString(tmpStr); freeName = True; } title = XtMalloc (strlen(dialogTitle) + strlen(name) + 1); sprintf(title, "%s%s", dialogTitle, name); ac = 0; XtSetArg(al[ac], XmNtitle, title); ac++; XtSetArg(al[ac], XmNiconName, name); ac++; XtSetValues(dtIconShell, al, ac); if(freeName == True) XtFree(name); XtFree(title); }