1 /* $TOG: utils.c /main/9 1998/09/24 12:32:05 samborn $ */
2 /*********************************************************************
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
6 * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
8 **********************************************************************/
9 /******************************************************************************
12 ** Description: X11-based multi-color icon editor
14 ** File: utils.c, which contains the following subroutines or
16 ** Create_Gfx_Labels()
23 ** Repaint_Exposed_Tablet()
26 ** Transfer_Back_Image()
34 ** Switch_FillSolids()
47 ******************************************************************************
49 ** Copyright 1991 by Hewlett-Packard Company, 1990, 1991, 1992.
50 ** All rights are reserved. Copying or reproduction of this program,
51 ** except for archival purposes, is prohibited without prior written
52 ** consent of Hewlett-Packard Company.
54 ** Hewlett-Packard makes no representations about the suitibility of this
55 ** software for any purpose. It is provided "as is" without express or
58 ******************************************************************************/
61 #include <X11/cursorfont.h>
62 #include <Xm/Protocols.h>
65 #include <Xm/MessageB.h>
66 #include <Xm/VendorSEP.h>
67 #include <Dt/UserMsg.h>
70 #include "externals.h"
72 /* Copied from Xm/BaseClassI.h */
73 extern XmWidgetExtData _XmGetWidgetExtData(
75 #if NeedWidePrototypes
76 unsigned int extType) ;
78 unsigned char extType) ;
79 #endif /* NeedWidePrototypes */
81 #include "pixmaps/Circle.pm"
82 #include "pixmaps/CircleSolid.pm"
83 #include "pixmaps/Connected.pm"
84 #include "pixmaps/ConnectedClosed.pm"
85 #include "pixmaps/ConnecClosedSolid.pm"
86 #include "pixmaps/Ellipse.pm"
87 #include "pixmaps/EllipseSolid.pm"
88 #include "pixmaps/Eraser.pm"
89 #include "pixmaps/Rectangle.pm"
90 #include "pixmaps/RectangleSolid.pm"
91 #include "pixmaps/PaintBucket.pm"
92 #include "pixmaps/Pencil.pm"
93 #include "pixmaps/Line.pm"
94 #include "pixmaps/SelectArea.pm"
96 #include "bitmaps/q_mark.xbm"
98 extern Widget color_pb1, color_pb2, color_pb3, color_pb4,
99 color_pb5, color_pb6, color_pb7, color_pb8;
100 extern Widget grey_pb1, grey_pb2, grey_pb3, grey_pb4,
101 grey_pb5, grey_pb6, grey_pb7, grey_pb8;
102 extern Widget fgColorToggle, bgColorToggle, tsColorToggle,
103 bsColorToggle, selectColorToggle,
104 transparentColorToggle;
105 extern Widget pointButton, floodButton, lineButton, polylineButton,
106 rectangleButton, polygonButton, circleButton,
107 ellipseButton, eraseButton, selectButton;
108 extern Widget viewport, tablet, tabletBorder, tabletFrame;
109 extern Widget iconForm, iconSize, monoLabel;
110 extern Widget fillToggle, magMenu_8x_tb;
111 extern Widget formatMenu_xbm_tb, formatMenu_xpm_tb;
112 extern Widget optionsMenu_grid, menu1, queryDialog, stdErrDialog;
113 extern Widget tablet_wid;
114 extern Window tablet_win;
116 static int jskXerrorDebug();
117 static int jskXerrorIODebug();
119 Widget editMenu_undo_pb;
121 void GetSessionInfo( void );
122 void Set_Gfx_Labels( Boolean );
127 int PixelTableLookup(
130 extern void *Process_DropCheckOp(
134 extern void *Process_DropOp(
138 extern void Repaint_Tablet(Window, int, int, int, int);
139 extern void Init_Widget_List(void);
140 extern void Init_Pen_Colors(Widget);
141 extern void Init_Color_Table(void);
142 extern void RegisterDropSites(void);
143 extern void Abort(char *);
144 extern void DoErrorDialog(char *);
146 char dash_list[2] = {1,1};
148 char start_file[256];
152 Position x_margin, y_margin;
153 Pixmap pointPix, floodPix, linePix, polylinePix, rectPix;
154 Pixmap polygonPix, circlePix, ellipsePix, eraserPix, selectPix;
155 Pixmap rectSolidPix, circleSolidPix, polygonSolidPix, ellipseSolidPix;
156 extern int successFormat, x_hot, y_hot;
157 extern unsigned int width_ret, height_ret;
159 /* Structure used on a save session to see if a dt is iconic */
166 /***************************************************************************
168 * Routine: Create_Gfx_Labels *
170 * Purpose: Initialize all the global variables used by the icon editor. *
172 ***************************************************************************/
181 Pixmap q_markPix, mask;
183 depth = XDefaultDepth(dpy, screen);
186 pointPix = XCreatePixmapFromBitmapData(dpy, root,
187 point_bits, point_width, point_height,
189 floodPix = XCreatePixmapFromBitmapData(dpy, root,
190 flood_bits, flood_width, flood_height,
192 linePix = XCreatePixmapFromBitmapData(dpy, root,
193 line_bits, line_width, line_height,
195 polylinePix = XCreatePixmapFromBitmapData(dpy, root,
196 polyline_bits, polyline_width, polyline_height,
198 rectPix = XCreatePixmapFromBitmapData(dpy, root,
199 rectangle_bits, rectangle_width, rectangle_height,
201 polygonPix = XCreatePixmapFromBitmapData(dpy, root,
202 polygon_bits, polygon_width, polygon_height,
204 circlePix = XCreatePixmapFromBitmapData(dpy, root,
205 circle_bits, circle_width, circle_height,
207 ellipsePix = XCreatePixmapFromBitmapData(dpy, root,
208 ellipse_bits, ellipse_width, ellipse_height,
210 eraserPix = XCreatePixmapFromBitmapData(dpy, root,
211 eraser_bits, eraser_width, eraser_height,
213 selectPix = XCreatePixmapFromBitmapData(dpy, root,
214 select_bits, select_width, select_height,
218 xpm_ReadAttribs.valuemask = READ_FLAGS;
219 xpm_ReadAttribs.colorsymbols = colorSymbols;
220 xpm_ReadAttribs.numsymbols = NUM_PENS;
222 status = _DtXpmCreatePixmapFromData(dpy, root, Circle, &circlePix, &mask,
224 if (status != XpmSuccess) Abort(GETSTR(10,2, "Cannot initialize button icon for circle"));
225 status = _DtXpmCreatePixmapFromData(dpy, root, CircleSolid, &circleSolidPix,
226 &mask, &xpm_ReadAttribs);
227 if (status != XpmSuccess) Abort(GETSTR(10,4, "Cannot initialize button icon for solid circle"));
228 status = _DtXpmCreatePixmapFromData(dpy, root, Connected, &polylinePix, &mask,
230 if (status != XpmSuccess) Abort(GETSTR(10,6, "Cannot initialize button icon for polyline"));
231 status = _DtXpmCreatePixmapFromData(dpy, root, ConnectedClosed, &polygonPix,
232 &mask, &xpm_ReadAttribs);
233 if (status != XpmSuccess) Abort(GETSTR(10,8, "Cannot initialize button icon for polygon"));
234 status = _DtXpmCreatePixmapFromData(dpy, root, ConnecClosedSolid,
235 &polygonSolidPix, &mask, &xpm_ReadAttribs);
236 if (status != XpmSuccess) Abort(GETSTR(10,10, "Cannot initialize button icon for solid polygon"));
237 status = _DtXpmCreatePixmapFromData(dpy, root, Ellipse, &ellipsePix, &mask,
239 if (status != XpmSuccess) Abort(GETSTR(10,12, "Cannot initialize button icon for ellipse"));
240 status = _DtXpmCreatePixmapFromData(dpy, root, EllipseSolid, &ellipseSolidPix,
241 &mask, &xpm_ReadAttribs);
242 if (status != XpmSuccess) Abort(GETSTR(10,14, "Cannot initialize button icon for solid ellipse"));
243 status = _DtXpmCreatePixmapFromData(dpy, root, Eraser, &eraserPix, &mask,
245 if (status != XpmSuccess) Abort(GETSTR(10,16, "Cannot initialize button icon for eraser"));
246 status = _DtXpmCreatePixmapFromData(dpy, root, Line, &linePix, &mask,
248 if (status != XpmSuccess) Abort(GETSTR(10,18, "Cannot initialize button icon for line"));
249 status = _DtXpmCreatePixmapFromData(dpy, root, PaintBucket, &floodPix, &mask,
251 if (status != XpmSuccess) Abort(GETSTR(10,20, "Cannot initialize button icon for flood"));
252 status = _DtXpmCreatePixmapFromData(dpy, root, Pencil, &pointPix, &mask,
254 if (status != XpmSuccess) Abort(GETSTR(10,22, "Cannot initialize button icon for point"));
255 status = _DtXpmCreatePixmapFromData(dpy, root, Rectangle, &rectPix, &mask,
257 if (status != XpmSuccess) Abort(GETSTR(10,24, "Cannot initialize button icon for rectangle"));
258 status = _DtXpmCreatePixmapFromData(dpy, root, RectangleSolid, &rectSolidPix,
259 &mask, &xpm_ReadAttribs);
260 if (status != XpmSuccess) Abort(GETSTR(10,26, "Cannot initialize button icon for solid rectangle"));
261 status = _DtXpmCreatePixmapFromData(dpy, root, SelectArea, &selectPix, &mask,
263 if (status != XpmSuccess) Abort(GETSTR(10,28, "Cannot initialize button icon for select"));
265 q_markPix = XCreatePixmapFromBitmapData(dpy, root,
266 (char*)q_mark_bits, q_mark_width, q_mark_height,
270 XtSetArg(args[i], XmNlabelPixmap, pointPix); i++;
271 XtSetValues(pointButton, args, i);
273 XtSetArg(args[i], XmNlabelPixmap, linePix); i++;
274 XtSetValues(lineButton, args, i);
276 XtSetArg(args[i], XmNlabelPixmap, eraserPix); i++;
277 XtSetValues(eraseButton, args, i);
279 XtSetArg(args[i], XmNlabelPixmap, floodPix); i++;
280 XtSetValues(floodButton, args, i);
282 XtSetArg(args[i], XmNlabelPixmap, polylinePix); i++;
283 XtSetValues(polylineButton, args, i);
285 XtSetArg(args[i], XmNlabelPixmap, selectPix); i++;
286 XtSetValues(selectButton, args, i);
288 XtSetArg(args[i], XmNlabelPixmap, q_markPix); i++;
289 XtSetValues(queryDialog, args, i);
291 Set_Gfx_Labels(HOLLOW);
294 /***************************************************************************
296 * Routine: Init_Editor *
298 * Purpose: Initialize all the global variables, states, widgets, etc, *
299 * for the icon editor. This is a long, messy, somewhat *
300 * rambling routine. *
302 ***************************************************************************/
313 /*** window ID of tablet ***/
316 /*** Nothing needs to be saved, yet ***/
319 /*** Initial Graphics states, pen color, etc. ***/
321 CurrentColor = COLOR1;
322 ColorBlock = STATIC_COLOR;
327 /*** file I/O related globals ***/
328 last_fname[0] = NULL;
332 XSetErrorHandler(jskXerrorDebug);
333 XSetIOErrorHandler(jskXerrorIODebug);
335 /*** Xlib-related globals ***/
336 dpy = XtDisplay(wid);
338 root = DefaultRootWindow(dpy);
339 screen = DefaultScreen(dpy);
340 screen_ptr = XtScreen(wid);
341 black_pixel = BlackPixel(dpy, screen);
342 white_pixel = WhitePixel(dpy, screen);
343 Cmap = DefaultColormap(dpy, screen);
345 /*** initialize global pixel table data ***/
346 pixelTable.pixelTableSize = 0;
347 pixelTable.numItems = 0;
348 pixelTable.lastFound = 0;
349 pixelTable.item = NULL;
351 /*** Initialize the GCs used by the app. ***/
352 Color_gc = XCreateGC(dpy, root, 0, 0);
353 Mono_gc = XCreateGC(dpy, root, 0, 0);
354 Grid_gc = XCreateGC(dpy, root, 0, 0);
355 Erase_gc = XCreateGC(dpy, root, 0, 0);
356 Flicker_gc = XCreateGC(dpy, root, 0, 0);
357 scratch_gc = XCreateGC(dpy, root, 0, 0);
358 XSetState(dpy, Flicker_gc, black_pixel, white_pixel, GXinvert, 0x1);
359 XSetSubwindowMode(dpy, Flicker_gc, IncludeInferiors);
360 XSetDashes(dpy, Grid_gc, 0, dash_list, 2);
361 XSetLineAttributes(dpy, Grid_gc, 0, LineDoubleDash, CapButt, JoinMiter);
363 /*** Initialize the widget variables ***/
366 /*** Initialize the pen colors and the internal color table ***/
367 Init_Pen_Colors(wid);
369 XSetForeground(dpy, Erase_gc, Transparent);
371 /*** configure the color and mono icons to their initial size ***/
372 Init_Icons(icon_width, icon_height, DO_NOT_SAVE);
375 DtInitialize (dpy, wid, progName, progName);
377 /*** Drop site registration must occur after DtInitialize() ***/
381 multiClickTime = XtGetMultiClickTime(dpy);
383 /*** Now, do all the tedious widget initialization ***/
385 XtSetArg(args[i], XmNset, True); i++;
386 XtSetValues(StaticWid[CurrentColor], args, i);
387 XtSetValues(GraphicOpsWid[GraphicsOp], args, i);
388 XtSetValues(magMenu_8x_tb, args, i);
389 XtSetValues(optionsMenu_grid, args, i);
390 XtSetValues(formatMenu_xpm_tb, args, i);
392 XtSetArg(args[i], XmNbackground, Transparent); i++;
393 XtSetValues(tablet_wid, args, i);
394 XtSetValues(tabletBorder, args, i);
395 XSetForeground(dpy, Color_gc, StaticPen[0]);
396 XSetForeground(dpy, Mono_gc, StaticMono[0]);
398 XtSetArg(args[i], XmNset, FillSolids); i++;
399 XtSetValues(fillToggle, args, i);
401 XtSetArg(args[i], XmNclipWindow, &clip_wid); i++;
402 XtGetValues(viewport, args, i);
409 stat_out("DEFAULT TIME-OUT VALUE IS %d MILLISECONDS\n", multiClickTime);
410 stat_out("****CLIP WINDOW WIDGET = %d\n", clip_wid);
411 stat_out(" TABLET OFFSETS [x,y] = [%d,%d]\n", x_margin, y_margin);
416 XtSetArg(args[i], XmNbackground, Transparent); i++;
417 XtSetValues(clip_wid, args, i);
419 XtSetArg(args[i], XmNset, False); i++;
420 XtSetValues(floodButton, args, i);
421 XtSetValues(lineButton, args, i);
422 XtSetValues(polylineButton, args, i);
423 XtSetValues(rectangleButton, args, i);
424 XtSetValues(polygonButton, args, i);
425 XtSetValues(circleButton, args, i);
426 XtSetValues(ellipseButton, args, i);
427 XtSetValues(eraseButton, args, i);
428 XtSetValues(selectButton, args, i);
430 XtSetArg(args[i], XmNset, True); i++;
431 XtSetValues(pointButton, args, i);
435 /***************************************************************************
437 * Routine: GetMarginData *
439 * Purpose: We need to get margin data AFTER these widgets are realized *
440 * in order to get valid data... so do it here *
442 ***************************************************************************/
445 GetMarginData( void )
454 stat_out("****** Getting margin data: x=%d y=%d\n", x_margin, y_margin);
458 XtSetArg(args[i], XmNx, &lx); i++;
459 XtSetArg(args[i], XmNy, &ly); i++;
460 XtGetValues(tabletFrame, args, i);
464 XtSetArg(args[i], XmNx, &lx); i++;
465 XtSetArg(args[i], XmNy, &ly); i++;
466 XtGetValues(tablet_wid, args, i);
472 stat_out("****** margin data: x=%d y=%d\n", x_margin, y_margin);
478 /***************************************************************************
480 * Routine: New_MagFactor *
482 * Purpose: The user has just selected a new magnification factor for *
483 * the fat pixels on the tablet. Update the MagFactor global *
484 * variable and reapaint the visible portion of the tablet to *
485 * reflect the change. *
487 ***************************************************************************/
498 stat_out("****** Changing MagFactor to %d\n", new_value);
501 MagFactor = new_value;
503 XtSetArg(args[i], XmNwidth, (icon_width*MagFactor)); i++;
504 XtSetArg(args[i], XmNheight, (icon_height*MagFactor)); i++;
505 XtSetValues(tablet_wid, args, i);
508 /* This code does not seem to be needed and since it slows down
509 the grid drawing I'll take it out */
510 /*Repaint_Exposed_Tablet();*/
514 /***************************************************************************
516 * Routine: New_FileFormat *
518 * Purpose: Update the fileFormat value to reflect the user's current *
519 * choice of default file output formats. *
521 ***************************************************************************/
530 stat_out("****** Changing Output File Format to ");
532 case FORMAT_XPM : stat_out("XPM\n");
534 case FORMAT_XBM : stat_out("XBM\n");
536 default : stat_out("UNKNOWN\n");
542 fileFormat = new_value;
547 /***************************************************************************
549 * Routine: Icon_Coords *
551 * Purpose: Convert a set of [x,y] values (acquired from the tablet) *
552 * into the equivalent [x,y] values they represent on the *
553 * actual icon being created/modified. *
555 ***************************************************************************/
564 *fat_x = normal_x / MagFactor;
565 *fat_y = normal_y / MagFactor;
569 /***************************************************************************
571 * Routine: Tablet_Coords *
573 * Purpose: Convert a set of fat [x,y] values back into raw [x,y] values *
574 * which map to the top-left corner of the fat pixel value. *
576 ***************************************************************************/
585 *raw_x = fat_x * MagFactor;
586 *raw_y = fat_y * MagFactor;
590 /***************************************************************************
592 * Routine: Quantize *
594 * Purpose: Adjust a set of [x,] values so that they mark the top-left *
595 * corner (or the middle, depending on the 'center' flag) of *
596 * whatever 'fat' pixel they map onto. This will insure that *
597 * any operation involving rubberband lines leaps from fat *
598 * pixel center to fat pixel center, providing a clear visual *
599 * indicator of which pixel currently contains the line/point. *
601 ***************************************************************************/
614 if ((lx%MagFactor) != 0)
615 lx = (lx / MagFactor) * MagFactor;
616 if ((ly%MagFactor) != 0)
617 ly = (ly / MagFactor) * MagFactor;
627 /***************************************************************************
629 * Routine: Repaint_Exposed_Tablet *
631 * Purpose: Repaint the rectangular section of the tablet currently *
632 * visible in the clipping area widget of the scrolled window *
633 * widget. To do this, we get the current width and height *
634 * of the clipping area widget, the current width and height *
635 * of the drawing area manager widget (the clipping area *
636 * widget's immediate child), and the x and y position of the *
637 * drawing area manager widget. This will allow us to cal- *
638 * culate what portion of the tablet (drawn button widget) is *
639 * currently visible in the clipping area widget. We then *
640 * request th Repaint_Tablet() routine to repaint that portion *
641 * of the drawn button. *
643 ***************************************************************************/
646 Repaint_Exposed_Tablet( void )
651 Dimension c_width, c_height, t_width, t_height;
654 XtSetArg(args[i], XmNwidth, &c_width); i++;
655 XtSetArg(args[i], XmNheight, &c_height); i++;
656 XtGetValues(clip_wid, args, i);
658 XtSetArg(args[i], XmNx, &t_x); i++;
659 XtSetArg(args[i], XmNy, &t_y); i++;
660 XtSetArg(args[i], XmNwidth, &t_width); i++;
661 XtSetArg(args[i], XmNheight, &t_height); i++;
662 XtGetValues(tabletBorder, args, i);
668 if (t_x < 0) t_x = 0;
669 if (t_y < 0) t_y = 0;
671 Repaint_Tablet(tablet_win, t_x, t_y, c_width, c_height);
675 /***************************************************************************
677 * Routine: Repaint_Tablet *
679 * Purpose: Repaint the rectangular section of the tablet described by *
680 * the [x,y,width,height] values in the XRectangle. *
682 ***************************************************************************/
695 scratch_img = XGetImage(dpy, color_icon, 0, 0, icon_width, icon_height,
699 stat_out("****** Repaint_Tablet: x,y=%d,%d w,h=%d,%d\n", x,y,width,height);
702 for (i=x; i<x+width+MagFactor; i+=MagFactor)
703 for (j=y; j<y+height+MagFactor; j+=MagFactor) {
704 Icon_Coords(i, j, &lx, &ly);
705 if ((lx >= 0) && (lx < icon_width) &&
706 (ly >= 0) && (ly < icon_height)) {
707 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, lx, ly));
708 XFillRectangle(dpy, tablet_win, scratch_gc,
709 lx*MagFactor, ly*MagFactor, MagFactor, MagFactor);
711 if ((lx == X_Hot) && (ly == Y_Hot)) {
712 XDrawLine(dpy, tablet_win, Grid_gc,
713 lx*MagFactor, ly*MagFactor+MagFactor, lx*MagFactor+MagFactor, ly*MagFactor);
714 XDrawLine(dpy, tablet_win, Grid_gc,
715 lx*MagFactor, ly*MagFactor, lx*MagFactor+MagFactor, ly*MagFactor+MagFactor);
720 Quantize(&x, &y, False);
721 width += (MagFactor*2);
722 height += (MagFactor*2);
725 Draw the grid if Enabled....
728 for (i=x; i<=x+width+MagFactor; i+=MagFactor)
729 XDrawLine(dpy, win, Grid_gc, i, y, i, (y+height));
730 for (i=y; i<=y+height+MagFactor; i+=MagFactor)
731 XDrawLine(dpy, win, Grid_gc, x, i, (x+width), i);
735 XDestroyImage(scratch_img);
739 /***************************************************************************
741 * Routine: Paint_Tile *
743 * Purpose: Paint a single rectangular tile of size MagFactor x *
744 * MagFactor with the color supplied in the passed GC. *
745 * The X and Y parameters are coordinates for the 1:1 *
746 * sized icon, and not direct coordinates for the tablet. *
748 ***************************************************************************/
756 XFillRectangle(dpy, tablet_win, gc,
757 x*MagFactor, y*MagFactor, MagFactor, MagFactor);
760 XDrawRectangle(dpy, tablet_win, Grid_gc,
761 x*MagFactor, y*MagFactor, MagFactor, MagFactor);
764 if ((x == X_Hot) && (y == Y_Hot)) {
765 XDrawLine(dpy, tablet_win, Grid_gc,
766 x*MagFactor, y*MagFactor+MagFactor, x*MagFactor+MagFactor, y*MagFactor);
767 XDrawLine(dpy, tablet_win, Grid_gc,
768 x*MagFactor, y*MagFactor, x*MagFactor+MagFactor, y*MagFactor+MagFactor);
773 /***************************************************************************
775 * Routine: Transfer_Back_Image *
777 * Purpose: Paint a single rectangular tile of size MagFactor x *
778 * MagFactor with the color supplied in the passed GC. *
779 * The [x,y] coordinate pairs are both icon coordinates, *
780 * not tablet coordinates. *
782 ***************************************************************************/
792 int min_x, min_y, max_x, max_y, i, j;
797 stat_out("Entering Transfer_Back_Image\n");
798 stat_out("Values are x1:%d, y1:%d, x2:%d, y2:%d, flag = ",
800 stat_out(" icon size is width:%d, height:%d\n", icon_width, icon_height);
802 case HOLLOW : stat_out("HOLLOW\n");
804 case FILL : stat_out("FILL\n");
806 default : stat_out("UNKNOWN\n");
812 min_x = ((x1 < x2) ? x1 : x2);
813 min_y = ((y1 < y2) ? y1 : y2);
814 max_x = ((x1 > x2) ? x1 : x2);
815 max_y = ((y1 > y2) ? y1 : y2);
817 /*** make sure max_x and max_y are within icon ***/
818 if (max_x >= icon_width)
819 max_x = icon_width-1;
820 if (max_y >= icon_height)
821 max_y = icon_height-1;
823 scratch_img = XGetImage(dpy, color_icon, 0, 0, icon_width, icon_height,
825 /*** do the entire rectangular area... ***/
827 for (i = min_x; i <= max_x; i++)
828 for (j = min_y; j <= max_y; j++) {
829 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, j));
830 Paint_Tile(i, j, scratch_gc);
833 /*** ...or just do the border of rectangle ***/
835 for (i = min_x; i <= max_x; i++) {
836 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, min_y));
837 Paint_Tile(i, min_y, scratch_gc);
839 for (i = min_x; i <= max_x; i++) {
840 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, i, max_y));
841 Paint_Tile(i, max_y, scratch_gc);
843 for (i = min_y; i <= max_y; i++) {
844 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, min_x, i));
845 Paint_Tile(min_x, i, scratch_gc);
847 for (i = min_y; i <= max_y; i++) {
848 XSetForeground(dpy, scratch_gc, XGetPixel(scratch_img, max_x, i));
849 Paint_Tile(max_x, i, scratch_gc);
852 XDestroyImage(scratch_img);
856 stat_out("Leaving Transfer_Back_Image\n");
862 /***************************************************************************
864 * Routine: Init_Widget_list *
866 * Purpose: Initialize all the pen color widgets into 2 widget ID *
867 * arrays, to simplify referencing them later. *
869 ***************************************************************************/
872 Init_Widget_List( void )
876 GraphicOpsWid[POINT] = pointButton;
877 GraphicOpsWid[FLOOD] = floodButton;
878 GraphicOpsWid[LINE] = lineButton;
879 GraphicOpsWid[POLYLINE] = polylineButton;
880 GraphicOpsWid[RECTANGLE] = rectangleButton;
881 GraphicOpsWid[POLYGON] = polygonButton;
882 GraphicOpsWid[CIRCLE] = circleButton;
883 GraphicOpsWid[ELLIPSE] = ellipseButton;
884 GraphicOpsWid[ERASER] = eraseButton;
885 GraphicOpsWid[SELECT] = selectButton;
887 DynamicWid[BG_COLOR-BG_COLOR] = bgColorToggle;
888 DynamicWid[FG_COLOR-BG_COLOR] = fgColorToggle;
889 DynamicWid[TS_COLOR-BG_COLOR] = tsColorToggle;
890 DynamicWid[BS_COLOR-BG_COLOR] = bsColorToggle;
891 DynamicWid[SELECT_COLOR-BG_COLOR] = selectColorToggle;
892 DynamicWid[TRANS_COLOR-BG_COLOR] = transparentColorToggle;
894 StaticWid[COLOR1] = color_pb1;
895 StaticWid[COLOR2] = color_pb2;
896 StaticWid[COLOR3] = color_pb3;
897 StaticWid[COLOR4] = color_pb4;
898 StaticWid[COLOR5] = color_pb5;
899 StaticWid[COLOR6] = color_pb6;
900 StaticWid[COLOR7] = color_pb7;
901 StaticWid[COLOR8] = color_pb8;
902 StaticWid[GREY1] = grey_pb1;
903 StaticWid[GREY2] = grey_pb2;
904 StaticWid[GREY3] = grey_pb3;
905 StaticWid[GREY4] = grey_pb4;
906 StaticWid[GREY5] = grey_pb5;
907 StaticWid[GREY6] = grey_pb6;
908 StaticWid[GREY7] = grey_pb7;
909 StaticWid[GREY8] = grey_pb8;
915 /***************************************************************************
917 * Routine: Init_Pen_Colors *
919 * Purpose: Initialize all the pen colors (both Static and Dynamic) and *
920 * set the appropriate fg/bg colors for each pen button widget *
923 ***************************************************************************/
933 int i, j, pixelTableIndex;
936 XtSetArg(arg[i], XmNbackground, &Background); i++;
937 XtGetValues(wid, arg, i);
938 XmGetColors(screen_ptr, Cmap, Background, &Foreground, &TopShadow,
939 &BottomShadow, &Select);
943 stat_out("Return from XmGetColors()\n");
946 /*** Set FOREGROUND Button fg/bg colors ***/
948 XtSetArg(arg[i], XmNbackground, Foreground); i++;
949 pixelTableIndex = PixelTableLookup (Foreground, False);
950 if (PIXEL_TABLE_MONO(pixelTableIndex) == white_pixel) {
951 XtSetArg(arg[i], XmNforeground, black_pixel); i++;
954 XtSetArg(arg[i], XmNforeground, white_pixel); i++;
956 XtSetValues(fgColorToggle, arg, i);
958 /*** Set BACKGROUND Button fg/bg colors ***/
960 XtSetArg(arg[i], XmNbackground, Background); i++;
961 XtSetArg(arg[i], XmNforeground, Foreground); i++;
962 XtSetValues(bgColorToggle, arg, i);
964 /*** Set TOP_SHADOW Button fg/bg colors ***/
966 XtSetArg(arg[i], XmNbackground, TopShadow); i++;
967 if (TopShadow == Foreground) /* B & W */
968 { XtSetArg(arg[i], XmNforeground, Background); i++; }
970 { XtSetArg(arg[i], XmNforeground, Foreground); i++; }
971 XtSetValues(tsColorToggle, arg, i);
973 /*** Set BOTTOM_SHADOW Button fg/bg colors ***/
975 XtSetArg(arg[i], XmNbackground, BottomShadow); i++;
976 if (BottomShadow == Foreground) /* B & W */
977 { XtSetArg(arg[i], XmNforeground, Background); i++; }
979 { XtSetArg(arg[i], XmNforeground, Foreground); i++; }
980 XtSetValues(bsColorToggle, arg, i);
982 /*** Set SELECT Button fg/bg colors ***/
984 XtSetArg(arg[i], XmNbackground, Select); i++;
985 XtSetArg(arg[i], XmNforeground, Foreground); i++;
986 XtSetValues(selectColorToggle, arg, i);
988 /*** Set TRANSPARENT Button fg/bg colors ***/
990 XtSetArg(arg[i], XmNbackground, &Transparent); i++;
991 XtSetArg(arg[i], XmNforeground, &transFg); i++;
992 XtGetValues(menu1, arg, i);
994 XtSetArg(arg[i], XmNbackground, Transparent); i++;
995 XtSetArg(arg[i], XmNforeground, transFg); i++;
996 XtSetValues(transparentColorToggle, arg, i);
998 /*** Store the colors in the dynamic array ***/
1000 DynamicPen[BG_COLOR-BG_COLOR] = Background;
1001 DynamicPen[FG_COLOR-BG_COLOR] = Foreground;
1002 DynamicPen[TS_COLOR-BG_COLOR] = TopShadow;
1003 DynamicPen[BS_COLOR-BG_COLOR] = BottomShadow;
1004 DynamicPen[SELECT_COLOR-BG_COLOR] = Select;
1005 DynamicPen[TRANS_COLOR-BG_COLOR] = Transparent;
1009 stat_out("Backgrounds set for all 6 dynamic colors\n");
1012 /*** STUB *********************************************************/
1013 DynamicMono[BG_COLOR-BG_COLOR] = black_pixel;
1014 DynamicMono[FG_COLOR-BG_COLOR] = white_pixel;
1015 DynamicMono[TS_COLOR-BG_COLOR] = white_pixel;
1016 DynamicMono[BS_COLOR-BG_COLOR] = black_pixel;
1017 DynamicMono[SELECT_COLOR-BG_COLOR] = white_pixel;
1018 DynamicMono[TRANS_COLOR-BG_COLOR] = Transparent;
1020 for (i=0; i<NUM_STATICS; i++) {
1021 /*** Init the 16 color values ***/
1022 status = XParseColor(dpy, Cmap, color_table[i][5], &exact_def);
1024 sprintf(err_str, "%s %d",
1025 GETSTR(10,30, "Unable to parse static color no."), i+1);
1028 status = XAllocColor(dpy, Cmap, &exact_def);
1030 sprintf(err_str, "%s %d",
1031 GETSTR(10,32, "Unable to allocate static color no."), i+1);
1034 StaticPen[i] = exact_def.pixel;
1036 XtSetArg(arg[j], XmNbackground, StaticPen[i]); j++;
1037 XtSetValues(StaticWid[i], arg, j);
1038 /*** Init the 16 monochrome values ***/
1039 status = XParseColor(dpy, Cmap, color_table[i][2], &exact_def);
1041 sprintf(err_str, "%s %d",
1042 GETSTR(10,30, "Unable to parse static color no."), i+1);
1045 status = XAllocColor(dpy, Cmap, &exact_def);
1047 sprintf(err_str, "%s %d",
1048 GETSTR(10,32, "Unable to allocate static color no."), i+1);
1051 StaticMono[i] = exact_def.pixel;
1053 /******************************************************************/
1057 /***************************************************************************
1059 * Routine: Init_Color_Table *
1061 * Purpose: Complete initialization of the color_table used to specify *
1062 * color naming conventions when writing out XPM files. Then *
1063 * initialize the name and pixel fields for all the elements *
1064 * of the global array colorSymbols. *
1066 ***************************************************************************/
1069 Init_Color_Table( void )
1075 cmap_size = XDisplayCells(dpy, screen);
1078 for (i=NUM_STATICS; i<NUM_STATICS+5; i++) {
1079 if (DynamicMono[i-NUM_STATICS] == black_pixel)
1080 color_table[i][2] = black_string;
1082 color_table[i][2] = white_string;
1083 cval.pixel = DynamicPen[i-NUM_STATICS];
1084 XQueryColor(dpy, Cmap, &cval);
1085 sprintf(dynamic_c_str[i-NUM_STATICS], "#%04X%04X%04X",
1086 cval.red, cval.green, cval.blue);
1087 color_table[i][5] = dynamic_c_str[i-NUM_STATICS];
1089 color_table[NUM_PENS-1][2] = none_string;
1091 cval.pixel = DynamicPen[TRANS_COLOR-BG_COLOR];
1092 XQueryColor(dpy, Cmap, &cval);
1093 sprintf(dynamic_c_str[NUM_DYNAMICS-1], "#%04X%04X%04X",
1094 cval.red, cval.green, cval.blue);
1095 color_table[NUM_PENS-1][5] = dynamic_c_str[NUM_DYNAMICS-1];
1100 stat_out("XPM Color Table initialized:\n");
1101 for (i=0; i<(NUM_PENS); i++)
1102 stat_out(" %s %18s %18s\n", color_table[i][0], color_table[i][1],
1107 colorSymbols = (XpmColorSymbol *) XtMalloc(NUM_PENS * sizeof(XpmColorSymbol));
1109 Abort(GETSTR(10,38, "No memory(0)"));
1110 for (i=0; i<NUM_STATICS; i++) {
1111 colorSymbols[i].name = (char *) XtMalloc(strlen(color_table[i][1]) +1);
1112 if (!colorSymbols[i].name)
1113 Abort(GETSTR(10,40, "No memory(1)"));
1114 strcpy(colorSymbols[i].name, color_table[i][1]);
1115 colorSymbols[i].value = "";
1116 colorSymbols[i].pixel = StaticPen[i];
1118 for (i=NUM_STATICS; i<NUM_STATICS+NUM_DYNAMICS; i++) {
1119 colorSymbols[i].name = (char *) XtMalloc(strlen(color_table[i][1]) +1);
1120 if (!colorSymbols[i].name)
1121 Abort(GETSTR(10,42, "No memory(2)"));
1122 strcpy(colorSymbols[i].name, color_table[i][1]);
1123 colorSymbols[i].value = "";
1124 colorSymbols[i].pixel = DynamicPen[i-NUM_STATICS];
1129 stat_out("%d Color Symbols installed:\n", NUM_PENS);
1130 for (i=0; i<NUM_PENS; i++) {
1131 stat_out(" %d - %s | %s | %d\n", (i+1), colorSymbols[i].name,
1132 colorSymbols[i].value, colorSymbols[i].pixel);
1137 /*** now comes the ugly part, initialize the .colorTable field ***/
1138 /*** in xpm_WriteAttribs. This should remain constant for the ***/
1139 /*** life of the executable, and so only needs to be initialized ***/
1142 colorTable = (char ***) calloc(NUM_PENS, sizeof(char **));
1143 xpm_WriteAttribs.colorTable = (XpmColor*)colorTable;
1144 xpm_WriteAttribs.pixels = (Pixel *) calloc(NUM_PENS, sizeof(Pixel));
1145 if (!xpm_WriteAttribs.colorTable)
1146 Abort(GETSTR(10,44, "No memory(3)"));
1147 for (i=0; i<NUM_PENS; i++) {
1148 colorTable[i] = (char **) calloc(6, sizeof(char *));
1150 Abort(GETSTR(10,46, "No memory(4)"));
1152 for (i=0; i<NUM_PENS; i++) {
1153 xpm_WriteAttribs.pixels[i] = colorSymbols[i].pixel;
1154 for (j=0; j<6; j++) {
1155 if (color_table[i][j] && strlen(color_table[i][j]) > 0) {
1156 colorTable[i][j] = (char *) XtMalloc(strlen(color_table[i][j])+1);
1157 if (!colorTable[i][j])
1158 Abort(GETSTR(10,48, "No memory(5)"));
1159 strcpy(colorTable[i][j], color_table[i][j]);
1163 xpm_WriteAttribs.ncolors = NUM_PENS;
1164 xpm_WriteAttribs.hints_cmt = hints_cmt;
1165 xpm_WriteAttribs.colors_cmt = colors_cmt;
1166 xpm_WriteAttribs.pixels_cmt = pixels_cmt;
1167 xpm_WriteAttribs.mask_pixel = 0x80000000;
1171 Dump_AttribStruct(&xpm_WriteAttribs);
1176 /***************************************************************************
1178 * Routine: Size_IconForm *
1180 * Purpose: Given new dimensions for the Color and Mono icon widgets, *
1181 * calculate and set the new overall dimensions for the icon *
1182 * form widget (iconForm) which holds both of them and their *
1185 ***************************************************************************/
1194 Dimension label1_w, label1_h, label2_w, label2_h;
1195 Dimension form_width, form_height, junk;
1196 XmString label1_str, label2_str;
1197 XmFontList label_fontlist;
1202 stat_out("Entering Size_IconForm\n");
1205 /*********************************************************************
1206 * Before re-sizing the 2 icons (up or down), make sure their parent *
1207 * form's width is at least wide enough to fully show the two label *
1208 * gadgets (iconSize and monoLabel). If the icon widths are smaller *
1209 * than this, set offsets to center them on the space provided. *
1210 *********************************************************************/
1212 /*********************************************************************
1213 * First, get the minimum usable widths for the two label gadgets, *
1214 * and their current heights. *
1215 *********************************************************************/
1217 XtSetArg(args[i], XmNfontList, &label_fontlist); i++;
1218 XtSetArg(args[i], XmNlabelString, &label1_str); i++;
1219 XtGetValues(iconSize, args, i);
1221 XtSetArg(args[i], XmNlabelString, &label2_str); i++;
1222 XtGetValues(monoLabel, args, i);
1224 XmStringExtent(label_fontlist, label1_str, &label1_w, &junk);
1225 XmStringExtent(label_fontlist, label2_str, &label2_w, &junk);
1227 XtSetArg(args[i], XmNheight, &label1_h); i++;
1228 XtGetValues(iconSize, args, i);
1230 XtSetArg(args[i], XmNheight, &label2_h); i++;
1231 XtGetValues(monoLabel, args, i);
1233 /*********************************************************************
1234 * If the min. width for either label gadget is greater than the *
1235 * current icon widths, use half the difference between the two *
1236 * widths as a left and right offset for the two icon (drawn button) *
1238 *********************************************************************/
1239 if ((label1_w > width) || (label2_w > width))
1240 diff = (Position) (((label1_w > label2_w) ? label1_w : label2_w)
1246 XtSetArg(args[i], XmNleftOffset, diff); i++;
1247 XtSetValues(iconImage, args, i);
1248 XtSetValues(monoImage, args, i);
1250 /*********************************************************************
1251 * The overall form dimensions should be as follows: the form width *
1252 * will be the greater of the icon widths, or the widths of the two *
1253 * label gadgets. The form height will be the sum of the two icon *
1254 * heights, plus the sum of heights of the two label gadgets, plus *
1255 * the vertical offset between the bottom of the first label and the *
1256 * top of the second icon. *
1257 *********************************************************************/
1259 XtSetArg(args[i], XmNtopOffset, &top_offset); i++;
1260 XtGetValues(monoImage, args, i);
1261 form_width = max(width, (Dimension)max(label1_w, label2_w));
1262 form_height = (height*2) + label1_h + label2_h + top_offset;
1265 stat_out(" form_width = %d (of %d,%d,%d)\n", form_width, width, label1_w,
1267 stat_out(" form_height = %d\n", form_height);
1271 XtSetArg(args[i], XmNwidth, form_width); i++;
1272 XtSetArg(args[i], XmNheight, form_height); i++;
1273 XtSetValues(iconForm, args, i);
1277 stat_out("Leaving Size_IconForm\n");
1282 /***************************************************************************
1284 * Routine: Init_Icons *
1286 * Purpose: Initialize new color and mono icons at program start-up *
1287 * and at the following times: *
1288 * o When 'New' is selected from the 'File' pull-down menu. *
1289 * o When 'Resize Icon' is selected from the 'Edit' pull-down *
1291 * o When 'Load' is selected from the 'File' pull-down menu, *
1292 * and a new file is read in. *
1293 * o When 'Grab Screen Image' is selected from the 'Edit' *
1294 * pull-down menu, and the image is loaded into the editor. *
1296 * This routine sizes the iconImage, monoImage, and tablet *
1297 * widgets to the new dimensions (*MagFactor, and +1 in the *
1298 * case of the tablet widget). It also creates the application-*
1299 * internal Pixmaps associated with the iconImage and monoImage.*
1300 * If the 'saveFlag' flag is 'True', it is assumed that the *
1301 * current icons are being resized and that there are existing *
1302 * images that need to be retained. In this case, the new *
1303 * Pixmaps are created and the old Pixmaps are copied onto the *
1304 * new ones, before the old Pixmaps are freed. *
1306 ***************************************************************************/
1315 Pixmap tmp_color, tmp_mono;
1318 int i, x_offset, y_offset;
1323 stat_out("Entering Init_Icons: flag=%d\n", saveFlag);
1324 stat_out(" Init_Icons: color=%x mono=%x\n", color_icon, mono_icon);
1330 /*** App. init or 'New Icon' ***/
1333 XFreePixmap(dpy, color_icon);
1335 XFreePixmap(dpy, mono_icon);
1337 /*** Resizing the existing icon ***/
1340 tmp_color = color_icon;
1342 tmp_mono = mono_icon;
1347 color_icon = XCreatePixmap(dpy, root, width, height,
1348 DefaultDepth(dpy, screen));
1349 mono_icon = XCreatePixmap(dpy, root, width, height,
1350 DefaultDepth(dpy, screen));
1352 if ((color_icon == NULL) || (mono_icon == NULL))
1353 Abort(GETSTR(10,50, "Cannot initialize application icon storage"));
1355 XSetForeground(dpy, scratch_gc, Transparent);
1356 XFillRectangle(dpy, color_icon, scratch_gc, 0, 0, width, height);
1357 XFillRectangle(dpy, mono_icon, scratch_gc, 0, 0, width, height);
1359 sprintf(text, "%d x %d", width, height);
1361 local_str = XmStringCreateLocalized(text);
1362 XtSetArg(args[i], XmNlabelString, local_str); i++;
1363 XtSetValues(iconSize, args, i);
1364 XmStringFree(local_str);
1367 XtSetArg(args[i], XmNwidth, width); i++;
1368 XtSetArg(args[i], XmNheight, height); i++;
1369 XtSetValues(iconImage, args, i);
1370 XtSetValues(monoImage, args, i);
1372 /*********************************************************************
1373 * Call Size_IconForm() to re-do the layout of the iconForm widget, *
1374 * which contains the iconImage, iconSize, monoImage, and monoLabel *
1376 *********************************************************************/
1378 Size_IconForm(width, height);
1381 XCopyArea(dpy, tmp_color, color_icon, Color_gc, 0, 0,
1382 icon_width, icon_height, x_offset, y_offset);
1383 XCopyArea(dpy, tmp_mono, mono_icon, Mono_gc, 0, 0,
1384 icon_width, icon_height, x_offset, y_offset);
1386 XFreePixmap(dpy, tmp_color);
1388 XFreePixmap(dpy, tmp_mono);
1391 if (XtWindow(iconImage))
1392 XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc,
1393 0, 0, width, height, 0, 0);
1394 if (XtWindow(monoImage))
1395 XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc,
1396 0, 0, width, height, 0, 0);
1398 XtSetArg(args[i], XmNwidth, ((width*MagFactor)+1)); i++;
1399 XtSetArg(args[i], XmNheight, ((height*MagFactor)+1)); i++;
1400 XtSetValues(tablet_wid, args, i);
1403 icon_height = height;
1405 /* This code does not seem to be needed and since it slows down
1406 the grid drawing I'll take it out for now*/
1409 Repaint_Exposed_Tablet();
1414 stat_out("Leaving Init_Icons\n");
1421 XtPointer client_data,
1422 XtPointer call_data)
1424 DtDndTransferCallback transferInfo = (DtDndTransferCallback) call_data;
1426 if (transferInfo->reason == DtCR_DND_TRANSFER &&
1427 transferInfo->operation == XmDROP_COPY) {
1429 Process_DropCheckOp(w, client_data, call_data);
1431 transferInfo->status = DtDND_FAILURE;
1438 XtPointer client_data,
1439 XtPointer call_data)
1441 DtDndDropAnimateCallbackStruct *animateInfo =
1442 (DtDndDropAnimateCallbackStruct *) call_data;
1444 if (animateInfo->reason == DtCR_DND_DROP_ANIMATE) {
1446 Process_DropOp(w, client_data, call_data);
1450 /***************************************************************************
1452 * Routine: RegisterDropSites *
1454 * Purpose: Register the tablet as a valid drop zone. *
1456 ***************************************************************************/
1459 RegisterDropSites( void )
1461 static XtCallbackRec transferCB[] = { {TransferCallback, NULL},
1463 static XtCallbackRec animateCB[] = { {AnimateCallback, NULL},
1469 XtSetArg(args[0], XmNclipWindow, &clipWin);
1470 XtGetValues(viewport, args, 1);
1473 * This code makes assumptions about the order of the arguments.
1474 * XmNanimationStyle is assumed to be first and
1475 * DtNregisterChildren is assumed to be last
1478 XtSetArg(args[n], XmNanimationStyle, XmDRAG_UNDER_NONE); n++; /* first */
1479 XtSetArg(args[n], DtNdropAnimateCallback, animateCB); n++;
1480 XtSetArg(args[n], DtNregisterChildren, True); n++; /* last */
1482 DtDndDropRegister(clipWin, DtDND_FILENAME_TRANSFER, XmDROP_COPY,
1483 (XtCallbackList) transferCB, args, n);
1485 DtDndDropRegister(tabletBorder, DtDND_FILENAME_TRANSFER, XmDROP_COPY,
1486 (XtCallbackList) transferCB, args, n);
1488 DtDndDropRegister(tabletFrame, DtDND_FILENAME_TRANSFER, XmDROP_COPY,
1489 (XtCallbackList) transferCB, args, n);
1491 DtDndDropRegister(tablet, DtDND_FILENAME_TRANSFER, XmDROP_COPY,
1492 (XtCallbackList) transferCB, args, n - 1);
1495 * Once the drag and drop library is fixed, the following calls
1496 * will not be necessary. Currently the dnd library does not pass on
1497 * Motif resource values, in this case XmNanimationStyle.
1500 XmDropSiteUpdate(clipWin, args, 1);
1501 XmDropSiteUpdate(tabletBorder, args, 1);
1502 XmDropSiteUpdate(tabletFrame, args, 1);
1503 XmDropSiteUpdate(tablet, args, 1);
1506 /***************************************************************************
1510 * Purpose: Print a fatal error message and then exit. *
1512 ***************************************************************************/
1519 _DtSimpleError (progName, DtError, NULL, str, NULL);
1524 /***************************************************************************
1526 * Routine: stat_out *
1528 * Purpose: Generate a debug message to stderr. Flush stdout, and then *
1529 * print the message(s) to stderr and flush stderr. By doing *
1530 * an fflush after each fprintf, we can always determin where *
1531 * in the code the process is running. The stat_out() routine *
1532 * is invoked like printf() with up to 7 arguments. It is *
1533 * source-code identical to the outl() routine used in the xwd *
1534 * and xwud utilities which are part of standard X11. *
1536 *X11***********************************************************************/
1549 /* static char str[1024]; */
1552 fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
1555 /* sprintf(str, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
1556 _DtSimpleError ("dticon-stat_out", DtError, NULL, str, NULL);*/
1559 /***************************************************************************
1561 * Routine: PixelTableClear *
1563 * Purpose: Reset the pixel table to force subsequent lookups to get *
1564 * new pixel information. Do not free up space for table. *
1566 *X11***********************************************************************/
1570 pixelTable.numItems = 0;
1571 pixelTable.lastFound = 0;
1574 /***************************************************************************
1576 * Routine: PixelTableLookup *
1578 * Purpose: Return index into the Pixel Table for the pixel passed in. *
1579 * If the pixel passed in isn't already in the table, it will *
1580 * be added. This may require allocating a larger pixel table. *
1581 * In order to clear the Pixel Table (which should be done each *
1582 * time a new image is being processed in order to get current *
1583 * pixel data) call PixelTableClear(). *
1585 * For performance, save the last lookup result, and check it *
1586 * first. This should improve performance unless image is very *
1587 * "dithered". The allocNew parameter will be set if the image *
1588 * was grabbed from screen. In this case, each "screen" pixel *
1589 * will need a new pixel allocated for it. *
1591 *X11***********************************************************************/
1600 /** first, check to see if the last lookup was for the same pixel **/
1601 if (pixelTable.lastFound < pixelTable.numItems)
1602 if (pixelTable.item[pixelTable.lastFound].xcolor.pixel == pixelIn)
1603 return pixelTable.lastFound;
1605 /** look through table to see if there is an entry for this pixel **/
1606 for (i=0; i<pixelTable.numItems; i++)
1608 if (pixelTable.item[i].xcolor.pixel == pixelIn)
1610 pixelTable.lastFound = i;
1616 /** No entry for this pixel, create one **/
1619 /** Allocate larger table if needed **/
1620 if (pixelTable.numItems == pixelTable.pixelTableSize)
1622 pixelTable.pixelTableSize += PIXEL_TABLE_INC;
1623 pixelTable.item = (PixelTableItem *)XtRealloc((char *)pixelTable.item,
1624 sizeof(PixelTableItem)*pixelTable.pixelTableSize);
1627 /** Get color information for pixelIn **/
1628 i = pixelTable.numItems;
1629 pixelTable.numItems++;
1631 pixelTable.item[i].xcolor.pixel = pixelIn;
1632 XQueryColor(dpy, Cmap, &(pixelTable.item[i].xcolor));
1634 /*--- < ESTABLISH THE GREYSCALE IMAGE > ---*/
1635 /*--- The NTSC formula for converting an RGB value into the ---*/
1636 /*--- corresponding grayscale value is: ---*/
1637 /*--- luminosity = .299 red + .587 green + .114 blue ---*/
1639 grayValue = ( (int)((pixelTable.item[i].xcolor.red*299) +
1640 (pixelTable.item[i].xcolor.green*587) +
1641 (pixelTable.item[i].xcolor.blue*114)) / 1000) >> 8;
1643 if (grayValue < GAMMA_CUTOFF)
1644 pixelTable.item[i].mono = black_pixel;
1646 pixelTable.item[i].mono = white_pixel;
1648 /** Allocate new color cell if needed (use old for mono conversion) **/
1651 tmpXColor.red = pixelTable.item[i].xcolor.red;
1652 tmpXColor.green = pixelTable.item[i].xcolor.green;
1653 tmpXColor.blue = pixelTable.item[i].xcolor.blue;
1655 if (!XAllocColor(dpy, Cmap, &tmpXColor))
1657 /* for lack of something better, use the old color cell */
1658 pixelTable.item[i].newCell = pixelTable.item[i].xcolor.pixel;
1659 DoErrorDialog(GETSTR(10,62,"Operation failed.\nColormap is full"));
1662 pixelTable.item[i].newCell = tmpXColor.pixel;
1665 pixelTable.lastFound = i;
1670 /***************************************************************************
1672 * Routine: Switch_FillSolids *
1674 * Purpose: Toggles the state of the global FillSolids flag, based on *
1675 * the XmNset resource for the fillToggle widget. *
1677 *X11***********************************************************************/
1680 Switch_FillSolids( void )
1686 XtSetArg(args[i], XmNset, &FillSolids); i++;
1687 XtGetValues(fillToggle, args, i);
1689 Set_Gfx_Labels(FILL);
1691 Set_Gfx_Labels(HOLLOW);
1694 stat_out("Fill_Solids toggle = %s\n", (FillSolids? "True" : "False"));
1699 /***************************************************************************
1701 * Routine: Select_New_Pen *
1703 * Purpose: Changes the fg color of the pen GC, based on the parameter *
1706 *X11***********************************************************************/
1712 int new_block, new_pen;
1715 new_block = STATIC_COLOR;
1719 new_block = DYNAMIC_COLOR;
1720 new_pen = n - BG_COLOR;
1724 stat_out("**** n = %d, new_block = %d, new_pen = %d\n", n,
1725 new_block, new_pen);
1729 /*** if the new choice is the current pen, re-set it and return ***/
1730 if ((new_block == ColorBlock) && (new_pen == CurrentColor)) {
1731 if (new_block == STATIC_COLOR)
1732 XmToggleButtonSetState(StaticWid[new_pen], True, False);
1734 XmToggleButtonSetState(DynamicWid[new_pen], True, False);
1738 /*** un-set the previous choice ***/
1739 if (ColorBlock == STATIC_COLOR)
1740 XmToggleButtonSetState(StaticWid[CurrentColor], False, False);
1742 XmToggleButtonSetState(DynamicWid[CurrentColor], False, False);
1746 stat_out(" New pen color = %d\n", n);
1749 ColorBlock = new_block; /*** STATIC or DYNAMIC? ***/
1750 CurrentColor = new_pen; /*** index w/i the appropriate block ***/
1752 XSetForeground(dpy, Color_gc,
1753 (ColorBlock ? DynamicPen[CurrentColor] : StaticPen[CurrentColor]));
1754 XSetForeground(dpy, Mono_gc,
1755 (ColorBlock ? DynamicMono[CurrentColor] : StaticMono[CurrentColor]));
1759 /***************************************************************************
1761 * Routine: Backup_Icons *
1763 * Purpose: Copy the current contents of the color and mono icons to *
1764 * their undo storage areas, just prior to modifying them with *
1765 * the current graphics operation. *
1767 *X11***********************************************************************/
1770 Backup_Icons( void )
1772 /*** If we're backing up the tablet contents, it's dirty ***/
1773 /*** and may need to be saved to file at some point. ***/
1777 /*** if the icon sizes don't match the backup sizes, or ***/
1778 /*** either of the backup icons don't exist, create them ***/
1780 if ((icon_width != backup_width) ||
1781 (icon_height != backup_height) ||
1782 (!prev_color_icon) ||
1783 (!prev_mono_icon)) {
1784 if (prev_color_icon)
1785 XFreePixmap(dpy, prev_color_icon);
1787 XFreePixmap(dpy, prev_mono_icon);
1788 prev_color_icon = XCreatePixmap(dpy, root, icon_width, icon_height,
1789 DefaultDepth(dpy, screen));
1790 prev_mono_icon = XCreatePixmap(dpy, root, icon_width, icon_height,
1791 DefaultDepth(dpy, screen));
1792 backup_width = icon_width;
1793 backup_height = icon_height;
1796 /*** now, copy the color and mono pixmap to the backup pixmaps ***/
1798 XCopyArea(dpy, color_icon, prev_color_icon,
1799 Color_gc, 0, 0, icon_width, icon_height, 0, 0);
1800 XCopyArea(dpy, mono_icon, prev_mono_icon,
1801 Mono_gc, 0, 0, icon_width, icon_height, 0, 0);
1803 XtSetSensitive( editMenu_undo_pb, True);
1807 /***************************************************************************
1809 * Routine: DoErrorDialog *
1811 * Purpose: Some error has just occurred in the application. Pop up *
1812 * the error dialog and display the message passed in. *
1814 *X11***********************************************************************/
1825 local_str = XmStringCreateLocalized(str);
1826 XtSetArg(arg[i], XmNmessageString, local_str);
1828 XtSetValues(stdErrDialog, arg, i);
1829 XmStringFree(local_str);
1830 XtManageChild(stdErrDialog);
1834 /***************************************************************************
1836 * Routine: DoQueryDialog *
1838 * Purpose: The user should be prompted on an action they're attempting. *
1839 * Pop up the query dialog and display the message passed in. *
1841 *X11***********************************************************************/
1850 static Widget w=NULL;
1852 XtPopup(dtIconShell, XtGrabNone);
1853 XMapRaised(XtDisplay(dtIconShell), XtWindow(dtIconShell));
1856 w = XmMessageBoxGetChild(queryDialog, XmDIALOG_CANCEL_BUTTON);
1859 local_str = XmStringCreateLocalized(str);
1860 XtSetArg(arg[i], XmNmessageString, local_str); i++;
1861 XtSetValues(queryDialog, arg, i);
1862 XmStringFree(local_str);
1863 XtManageChild(queryDialog);
1865 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
1869 /***************************************************************************
1871 * Routine: Do_GrabOp *
1873 * Purpose: Switch to GRAB mode. Grab the server and the pointer until *
1874 * the user has made a selection from the screen. The server *
1875 * and pointer are ungrabbed in Do_ButtonOp(). *
1877 * Note: Moved the server grab until the mouse button is pressed *
1878 * (beginning the screen grab) in order to give the windows *
1879 * time to repaint. This was needed specifically for the *
1880 * queryDialog used when the icon image is "Dirty". *
1882 *X11***********************************************************************/
1887 Backup_G_Op = GraphicsOp;
1888 GraphicsOp = S_GRAB;
1889 cursor = XCreateFontCursor(dpy, XC_crosshair);
1890 XGrabPointer(dpy, root, False,
1891 ButtonPressMask|PointerMotionMask|ButtonReleaseMask,
1892 GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
1896 /***************************************************************************
1898 * Routine: LoadGrabbedImage *
1900 * Purpose: Given an [x,y] coordinate, plus width and height, grab an *
1901 * XImage from the Root window and load it into the icon *
1904 *X11***********************************************************************/
1912 XImage *img, *mono_img;
1914 int pixelTableIndex;
1918 stat_out("LoadGrabbedImage: [%d,%d] - width: %d, height: %d\n",
1919 x, y, width, height);
1924 if (width > 0 && height > 0)
1925 img = XGetImage(dpy, root, x, y, width, height, AllPlanes, format);
1927 XUngrabPointer (dpy, CurrentTime);
1928 XUngrabServer (dpy);
1932 DoErrorDialog( GETSTR(10,60, "Screen image capture failed") );
1936 /*********************************************************************
1937 * OK, now that we've got the image, we need to convert the entire *
1938 * thing to pixels that the icon editor won't lose control over. *
1939 * To do this, we find all the pixel values in the image and request *
1940 * equivalent read-only colors in the colormap (we won't be drawing *
1941 * with any pen colors we don't already have). Once the requests to *
1942 * the Cmap have been honored, we go thru the image one more time *
1943 * and replace each old pixel with the correct new value. *
1944 * NOTE: Old code assumed 256 max colors... NOT OKAY. Added dynamic *
1945 * pixel table for color lookup, which also handles allocating *
1946 * the new read-only color. - julie *
1947 *********************************************************************/
1949 /*********************************************************************
1950 * Dup the XImage so there'll be two identical copies: one to *
1951 * update with the new color values, and one with which to create *
1952 * a monochrome equivalent. *
1953 *********************************************************************/
1954 mono_img = XSubImage(img, 0, 0, img->width, img->height);
1956 DoErrorDialog( GETSTR(10,60, "Screen image capture failed") );
1960 /* force new pixel lookup, in case pixel data has changed */
1962 for (i=0; i<img->width; i++)
1964 for (j=0; j<img->height; j++)
1966 pixelTableIndex = PixelTableLookup(XGetPixel(img, i, j), True);
1967 XPutPixel(img, i, j, PIXEL_TABLE_NEW_CELL(pixelTableIndex));
1968 XPutPixel(mono_img, i, j, PIXEL_TABLE_MONO(pixelTableIndex));
1973 Init_Icons(img->width, img->height, DO_NOT_SAVE);
1974 XPutImage(dpy, color_icon, Color_gc, img, 0, 0, 0, 0,
1975 img->width, img->height);
1976 XPutImage(dpy, mono_icon, Mono_gc, mono_img, 0, 0, 0, 0,
1977 img->width, img->height);
1980 XDestroyImage(mono_img);
1986 /***************************************************************************
1988 * Routine: ParseAppArgs *
1990 * Purpose: Parse the invocation arguments, looking for '-f' and '-x'. *
1991 * This routine is invoked once by dticon. *
1993 * Each of the args should be accompanied by a parameter. If *
1994 * one does not exist, abort dticon with the appropriate *
1995 * error message. Otherwise, store the parameter in a global *
1996 * variable for processing by ProcessAppArgs() (called once *
1999 *X11***********************************************************************/
2011 stat_out("Entering ParseAppArgs\n");
2014 for (i=0; i<NUM_PARAMS; i++)
2015 param_flag[i] = False;
2016 argsNeedProcessed = False;
2018 /*** First, figure out which arguments get used ***/
2020 /* don't process command line args if restoring from a session file */
2021 if (xrdb.session != NULL)
2022 argsNeedProcessed = True;
2025 for (i=1; i<num; i++)
2029 if (cmd_arg[0] == '-') /* process command line switches */
2035 if (strncpy(start_file, cmd[i], 255)) {
2036 param_flag[AUTO_FILE] = True;
2037 argsNeedProcessed = True;
2040 Abort(GETSTR(10,52, "Invalid use of the '-f' parameter"));
2043 Abort(GETSTR(10,52, "Invalid use of the '-f' parameter"));
2045 case 'x': if (++i < num)
2047 if (strcpy(start_size, cmd[i])) {
2048 param_flag[AUTO_SIZE] = True;
2049 argsNeedProcessed = True;
2052 Abort(GETSTR(10,54, "Invalid use of the '-x' parameter"));
2055 Abort(GETSTR(10,54, "Invalid use of the '-x' parameter"));
2065 for (i=0; i<NUM_PARAMS; i++)
2066 stat_out(" param_flag = %s\n", (param_flag[i] ? "True" : "False"));
2067 stat_out("Leaving ParseAppArgs\n");
2074 /***************************************************************************
2076 * Routine: ProcessAppArgs *
2078 * Purpose: Process the invocation arguments, '-f'and '-x' *
2080 * If '-f' exists, the following parameter should be the name *
2081 * of a file to load at application start-up. Invoke the *
2082 * Read_File() routine with that parameter. *
2084 * If '-x' exists, the following parameter should be the *
2085 * initial geometry for the icon tablet (work area). Parse *
2086 * the string with XParseGeometry and pass the results (if *
2087 * valid) to Eval_NewSize(). *
2089 *X11***********************************************************************/
2091 #define MASK (WidthValue & HeightValue)
2094 ProcessAppArgs( void )
2101 stat_out("Entering ProcessAppArgs\n");
2104 argsNeedProcessed = False;
2106 /*** Attempt to honor the arguments, in order of priority ***/
2107 /*** ('-session', '-f', '-x', in that order). ***/
2109 /*** GetSessionInfo() will already set start_file if needed **/
2111 if ( param_flag[AUTO_FILE] || (session.useSession && start_file[0] != '\0') )
2113 fileIOMode = FILE_READ;
2114 if (!Read_File(start_file))
2115 DoErrorDialog( GETSTR(16,2,
2116 "The file cannot be accessed\nor contains invalid data") );
2118 if (successFormat == FORMAT_XPM) {
2119 X_Hot = xpm_ReadAttribs.x_hotspot;
2120 Y_Hot = xpm_ReadAttribs.y_hotspot;
2121 Display_XPMFile(xpm_ReadAttribs.width, xpm_ReadAttribs.height);
2123 else if (successFormat == FORMAT_XBM) {
2126 Display_XBMFile(width_ret, height_ret);
2130 else if(param_flag[AUTO_SIZE]) {
2131 result = XParseGeometry(start_size, &x_ret, &y_ret,
2132 &width_ret, &height_ret);
2133 if ((!MASK) & result)
2134 Abort(GETSTR(10,64, "Invalid dimension parameter"));
2136 Eval_NewSize(width_ret, height_ret);
2141 stat_out("Leaving ProcessAppArgs\n");
2147 /***************************************************************************
2149 * Routine: Set_Gfx_Labels *
2151 * Purpose: Set the label pixmaps of the 'Rectangle', 'Polygon', *
2152 * 'Circle', and 'Ellipse' graphics tool toggle to either *
2153 * Solid or Hollow, depending on the flag passed in. *
2155 *X11***********************************************************************/
2164 if (flag == HOLLOW) {
2166 XtSetArg(args[i], XmNlabelPixmap, rectPix); i++;
2167 XtSetValues(rectangleButton, args, i);
2169 XtSetArg(args[i], XmNlabelPixmap, circlePix); i++;
2170 XtSetValues(circleButton, args, i);
2172 XtSetArg(args[i], XmNlabelPixmap, polygonPix); i++;
2173 XtSetValues(polygonButton, args, i);
2175 XtSetArg(args[i], XmNlabelPixmap, ellipsePix); i++;
2176 XtSetValues(ellipseButton, args, i);
2180 XtSetArg(args[i], XmNlabelPixmap, rectSolidPix); i++;
2181 XtSetValues(rectangleButton, args, i);
2183 XtSetArg(args[i], XmNlabelPixmap, circleSolidPix); i++;
2184 XtSetValues(circleButton, args, i);
2186 XtSetArg(args[i], XmNlabelPixmap, polygonSolidPix); i++;
2187 XtSetValues(polygonButton, args, i);
2189 XtSetArg(args[i], XmNlabelPixmap, ellipseSolidPix); i++;
2190 XtSetValues(ellipseButton, args, i);
2195 /***************************************************************************
2197 * Routine: jskXerrorDebug *
2199 * Purpose: This routine takes the place of the default non-fatal error *
2200 * handler normally used by the X server. If an error occurs, *
2201 * this routine simply stores the error_code in the global *
2202 * variable XErrorFlag (making it available to other sections *
2203 * of the application). Then it returns. *
2205 ***************************************************************************/
2206 #define MAX_MSG_STR 1024
2208 static int jskXerrorDebug(disp, error_event)
2210 XErrorEvent *error_event;
2212 char error_msg[MAX_MSG_STR];
2216 stat_out("\n\nX Protocol Error:\n");
2218 _DtPrintDefaultErrorSafe(disp, error_event, error_msg, MAX_MSG_STR);
2219 _DtSimpleError (progName, DtWarning, NULL, error_msg, NULL);
2226 /***************************************************************************
2228 * Routine: jskXerrorIODebug *
2230 * Purpose: This routine is needed in order to get good bfa (bba) stats *
2231 **************************************************************************/
2232 static int jskXerrorIODebug(disp)
2240 /***************************************************************************
2242 * Routine: SaveSession *
2244 * Purpose: save state information for session management *
2245 **************************************************************************/
2251 char *xa_CommandStr[3];
2252 char *tmpStr, *tmpStr2;
2254 Dimension width, height;
2255 char bufr[1024]; /* make bigger if needed */
2256 XmVendorShellExtObject vendorExt;
2257 XmWidgetExtData extData;
2259 Atom wmStateAtom, actualType;
2261 unsigned long nitems, leftover;
2266 stat_out("SaveSession\n");
2269 DtSessionSavePath(dtIconShell, &path, &name);
2271 /* Create the session file */
2272 if ((fd = creat(path, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP)) == -1)
2274 tmpStr = GETSTR(16,24, "Couldn't save session to file");
2275 tmpStr2 = (char *)XtMalloc(strlen(tmpStr) + strlen(path)+ 3);
2276 sprintf(tmpStr2, "%s: %s\n", tmpStr, path);
2277 _DtSimpleErrnoError(progName, DtError, NULL, tmpStr2, NULL);
2279 XtFree ((char *)path);
2280 XtFree ((char *)name);
2285 /* Getting the WM_STATE property to see if iconified or not */
2287 wmStateAtom = XInternAtom(dpy, "WM_STATE", False);
2289 XGetWindowProperty (dpy, XtWindow(dtIconShell), wmStateAtom, 0L,
2290 (long)BUFSIZ, False, wmStateAtom, &actualType,
2291 &actualFormat, &nitems, &leftover,
2292 (unsigned char **) &wmState);
2294 if (wmState->state == IconicState)
2295 sprintf(bufr, "*iconic: True\n");
2297 sprintf(bufr, "*iconic: False\n");
2299 /*** Get and write out the geometry info for our Window ***/
2301 x = XtX(dtIconShell);
2302 y = XtY(dtIconShell);
2303 width = XtWidth(dtIconShell);
2304 height = XtHeight(dtIconShell);
2306 /* Modify x & y to take into account window mgr frames
2307 * This is pretty bogus, but I don't know a better way to do it.
2309 extData = _XmGetWidgetExtData(dtIconShell, XmSHELL_EXTENSION);
2310 vendorExt = (XmVendorShellExtObject)extData->widget;
2311 x -= vendorExt->vendor.xOffset;
2312 y -= vendorExt->vendor.yOffset;
2314 sprintf(bufr, "%s*x: %d\n", bufr, x);
2315 sprintf(bufr, "%s*y: %d\n", bufr, y);
2316 sprintf(bufr, "%s*width: %d\n", bufr, width);
2317 sprintf(bufr, "%s*height: %d\n", bufr, height);
2318 if (last_fname[0] != NULL)
2319 sprintf(bufr, "%s*file: %s\n", bufr, last_fname);
2321 write (fd, bufr, strlen(bufr));
2325 xa_CommandStr[n] = execName; n++;
2326 xa_CommandStr[n] = "-session"; n++;
2327 xa_CommandStr[n] = name; n++;
2329 XSetCommand(dpy, XtWindow(dtIconShell), xa_CommandStr, n);
2330 XtFree ((char *)path);
2331 XtFree ((char *)name);
2333 /* Don't exit yet, SM needs time to get the new commandStr.*/
2337 /***************************************************************************
2339 * Routine: GetSessionInfo *
2341 * Purpose: get dticon session information *
2342 **************************************************************************/
2343 #define DEFAULT_WIDTH 536
2344 #define DEFAULT_HEIGHT 477
2347 GetSessionInfo( void )
2350 char *tmpStr, *tmpStr2;
2352 XrmName xrm_name[5];
2353 XrmRepresentation rep_type;
2358 stat_out("GetSessionInfo\n");
2361 if (xrdb.session == NULL)
2363 session.useSession = False;
2367 session.useSession = True;
2369 /*** Open the resource database file ***/
2371 /* TopLevel is used because dtIconShell isn't created yet... */
2372 /* okay because it only uses it to get a display, not a window */
2373 if (DtSessionRestorePath(TopLevel, &path, xrdb.session) == False)
2374 path = xrdb.session;
2376 if ((db = XrmGetFileDatabase (path)) == NULL)
2378 tmpStr = GETSTR(16,22, "Couldn't restore session from file");
2379 tmpStr2 = (char *)XtMalloc(strlen(tmpStr) + strlen(path)+ 3);
2380 sprintf(tmpStr2, "%s: %s\n", tmpStr, path);
2381 _DtSimpleErrnoError(progName, DtError, NULL, tmpStr2, NULL);
2383 if (path != xrdb.session)
2385 session.useSession = False;
2388 if (path != xrdb.session)
2392 /*** now get the information we want from the database ***/
2393 /*** make sure values are at least somewhat reasonable ***/
2397 /* get x position */
2398 xrm_name[0] = XrmStringToQuark ("x");
2399 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2400 session.x = (Position)atoi((char *)value.addr);
2403 if (session.x < 0) session.x = 0;
2405 /* get y position */
2406 xrm_name[0] = XrmStringToQuark ("y");
2407 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2408 session.y = (Position)atoi((char *)value.addr);
2411 if (session.y < 0) session.y = 0;
2414 xrm_name[0] = XrmStringToQuark ("width");
2415 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2416 session.width = (Dimension)atoi((char *)value.addr);
2418 session.width = DEFAULT_WIDTH;
2419 if (session.width < DEFAULT_WIDTH) session.width = DEFAULT_WIDTH;
2422 xrm_name[0] = XrmStringToQuark ("height");
2423 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2424 session.height = (Dimension)atoi((char *)value.addr);
2426 session.height = DEFAULT_HEIGHT;
2427 if (session.height < DEFAULT_HEIGHT) session.height = DEFAULT_HEIGHT;
2429 /* get iconic state */
2430 xrm_name[0] = XrmStringToQuark ("iconic");
2431 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2433 if ( value.addr!=NULL && strcmp((char *)value.addr, "True")==0 )
2434 session.iconicState = IconicState;
2436 session.iconicState = NormalState;
2440 xrm_name[0] = XrmStringToQuark ("file");
2441 if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value))
2443 strncpy(start_file, value.addr, 255);
2446 start_file[0] = '\0';
2450 /***************************************************************************
2452 * Routine: ChangeTitle *
2454 * Purpose: Put the file name in the window title... *
2455 ***************************************************************************/
2460 static char *dialogTitle = NULL;
2470 name = GETSTR(12, 1, "Icon Editor");
2471 dialogTitle = XtMalloc (strlen(name) + 4);
2472 sprintf(dialogTitle, "%s - ", name);
2475 if (last_fname && *last_fname)
2477 if (name = strrchr(last_fname, '/'))
2485 tmpStr = GETSTR(10, 66, "(UNTITLED)");
2486 name = XtNewString(tmpStr);
2490 title = XtMalloc (strlen(dialogTitle) + strlen(name) + 1);
2491 sprintf(title, "%s%s", dialogTitle, name);
2494 XtSetArg(al[ac], XmNtitle, title); ac++;
2495 XtSetArg(al[ac], XmNiconName, name); ac++;
2496 XtSetValues(dtIconShell, al, ac);
2497 if(freeName == True)