Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2 
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from The Open Group.
     26 
     27 */
     28 
     29 /*
     30  * Author:  Davor Matic, MIT X Consortium
     31  */
     32 
     33 #ifdef HAVE_CONFIG_H
     34 # include "config.h"
     35 #endif
     36 
     37 #include <X11/IntrinsicP.h>
     38 #include <X11/StringDefs.h>
     39 #include <X11/Xaw/XawInit.h>
     40 #include <X11/Xmu/CharSet.h>
     41 #include <X11/Xmu/Drawing.h>
     42 #include <X11/Xatom.h>
     43 #include <X11/Xfuncs.h>
     44 #include <X11/Xos.h>
     45 #include "BitmapP.h"
     46 #include "Bitmap.h"
     47 
     48 #include <assert.h>
     49 #include <stdio.h>
     50 #include <math.h>
     51 
     52 #define min(x, y)                     ((((int)(x)) < (int)(y)) ? (x) : (y))
     53 #define max(x, y)                     ((((int)(x)) > (int)(y)) ? (x) : (y))
     54 
     55 Boolean DEBUG;
     56 
     57 #define DefaultGridTolerance 8
     58 #define DefaultBitmapSize    "16x16"
     59 #define FallbackBitmapWidth  16
     60 #define FallbackBitmapHeight 16
     61 #define DefaultGrid          TRUE
     62 #define DefaultDashed        TRUE
     63 #define DefaultStippled      TRUE
     64 #define DefaultProportional  TRUE
     65 #define DefaultAxes          FALSE
     66 #define DefaultMargin        16
     67 #define DefaultSquareWidth   16
     68 #define DefaultSquareHeight  16
     69 #define DefaultFilename      ""
     70 
     71 #define Offset(field) XtOffsetOf(BitmapRec, bitmap.field)
     72 
     73 static XtResource resources[] = {
     74 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
     75      Offset(foreground_pixel), XtRString, (char *)XtDefaultForeground},
     76 {XtNhighlight, XtCHighlight, XtRPixel, sizeof(Pixel),
     77      Offset(highlight_pixel), XtRString, (char *)XtDefaultForeground},
     78 {XtNframe, XtCFrame, XtRPixel, sizeof(Pixel),
     79      Offset(frame_pixel), XtRString, (char *)XtDefaultForeground},
     80 {XtNgridTolerance, XtCGridTolerance, XtRDimension, sizeof(Dimension),
     81      Offset(grid_tolerance), XtRImmediate, (XtPointer) DefaultGridTolerance},
     82 {XtNsize, XtCSize, XtRString, sizeof(String),
     83      Offset(size), XtRImmediate, (XtPointer) DefaultBitmapSize},
     84 {XtNdashed, XtCDashed, XtRBoolean, sizeof(Boolean),
     85      Offset(dashed), XtRImmediate, (XtPointer) DefaultDashed},
     86 {XtNgrid, XtCGrid, XtRBoolean, sizeof(Boolean),
     87      Offset(grid), XtRImmediate, (XtPointer) DefaultGrid},
     88 {XtNstippled, XtCStippled, XtRBoolean, sizeof(Boolean),
     89      Offset(stippled), XtRImmediate, (XtPointer) DefaultStippled},
     90 {XtNproportional, XtCProportional, XtRBoolean, sizeof(Boolean),
     91      Offset(proportional), XtRImmediate, (XtPointer) DefaultProportional},
     92 {XtNaxes, XtCAxes, XtRBoolean, sizeof(Boolean),
     93      Offset(axes), XtRImmediate, (XtPointer) DefaultAxes},
     94 {XtNsquareWidth, XtCSquareWidth, XtRDimension, sizeof(Dimension),
     95      Offset(squareW), XtRImmediate, (XtPointer) DefaultSquareWidth},
     96 {XtNsquareHeight, XtCSquareHeight, XtRDimension, sizeof(Dimension),
     97      Offset(squareH), XtRImmediate, (XtPointer) DefaultSquareHeight},
     98 {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
     99      Offset(margin), XtRImmediate, (XtPointer) DefaultMargin},
    100 {XtNxHot, XtCXHot, XtRPosition, sizeof(Position),
    101      Offset(hot.x), XtRImmediate, (XtPointer) NotSet},
    102 {XtNyHot, XtCYHot, XtRPosition, sizeof(Position),
    103      Offset(hot.y), XtRImmediate, (XtPointer) NotSet},
    104 {XtNbutton1Function, XtCButton1Function, XtRButtonFunction, sizeof(int),
    105      Offset(button_function[0]), XtRImmediate, (XtPointer) Set},
    106 {XtNbutton2Function, XtCButton2Function, XtRButtonFunction, sizeof(int),
    107      Offset(button_function[1]), XtRImmediate, (XtPointer) Invert},
    108 {XtNbutton3Function, XtCButton3Function, XtRButtonFunction, sizeof(int),
    109      Offset(button_function[2]), XtRImmediate, (XtPointer) Clear},
    110 {XtNbutton4Function, XtCButton4Function, XtRButtonFunction, sizeof(int),
    111      Offset(button_function[3]), XtRImmediate, (XtPointer) Clear},
    112 {XtNbutton5Function, XtCButton5Function, XtRButtonFunction, sizeof(int),
    113      Offset(button_function[4]), XtRImmediate, (XtPointer) Clear},
    114 {XtNfilename, XtCFilename, XtRString, sizeof(String),
    115      Offset(filename), XtRImmediate, (XtPointer) DefaultFilename},
    116 {XtNbasename, XtCBasename, XtRString, sizeof(String),
    117      Offset(basename), XtRImmediate, (XtPointer) DefaultFilename},
    118 {XtNdashes, XtCDashes, XtRBitmap, sizeof(Pixmap),
    119      Offset(dashes), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
    120 {XtNstipple, XtCStipple, XtRBitmap, sizeof(Pixmap),
    121      Offset(stipple), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
    122 };
    123 #undef Offset
    124 
    125 static XtActionsRec actions[] =
    126 {
    127 {"mark",               BWTMark},
    128 {"mark-all",           BWTMarkAll},
    129 {"unmark",             BWTUnmark},
    130 {"paste",              BWTPaste},
    131 {"bw-debug",           BWDebug},
    132 {"abort",              BWAbort},
    133 {"store-to-buffer",    BWStoreToBufferAction},
    134 {"change-notify",      BWChangeNotifyAction},
    135 {"set-changed",        BWSetChangedAction},
    136 {"up",                 BWUpAction},
    137 {"down",               BWDownAction},
    138 {"left",               BWLeftAction},
    139 {"right",              BWRightAction},
    140 {"fold",               BWFoldAction},
    141 {"flip-horiz",         BWFlipHorizAction},
    142 {"flip-vert",          BWFlipVertAction},
    143 {"rotate-right",       BWRotateRightAction},
    144 {"rotate-left",        BWRotateLeftAction},
    145 {"set",                BWSetAction},
    146 {"clear",              BWClearAction},
    147 {"invert",             BWInvertAction},
    148 {"undo",               BWUndoAction},
    149 {"redraw",             BWRedraw},
    150 };
    151 
    152 static char translations1[] =
    153 "\
    154 Shift<Btn1Down>: mark()\n\
    155 Shift<Btn2Down>: mark-all()\n\
    156 Shift<Btn3Down>: unmark()\n\
    157 Ctrl<BtnDown>:   paste()\n\
    158 Ctrl<Key>l: redraw()\n\
    159 <Key>d:     bw-debug()\n\
    160 <Key>a:     abort()\n\
    161 <Key>Up:    store-to-buffer()\
    162             up()\
    163             change-notify()\
    164             set-changed()\n\
    165 <Key>KP_Up: store-to-buffer()\
    166             up()\
    167             change-notify()\
    168             set-changed()\n\
    169 <Key>Down:  store-to-buffer()\
    170             down()\
    171             change-notify()\
    172             set-changed()\n\
    173 <Key>KP_Down: store-to-buffer()\
    174             down()\
    175             change-notify()\
    176             set-changed()\n\
    177 <Key>Left:  store-to-buffer()\
    178             left()\
    179             change-notify()\
    180             set-changed()\n\
    181 <Key>KP_Left: store-to-buffer()\
    182             left()\
    183             change-notify()\
    184             set-changed()\n\
    185 <Key>Right: store-to-buffer()\
    186             right()\
    187             change-notify()\
    188             set-changed()\n\
    189 <Key>KP_Right: store-to-buffer()\
    190             right()\
    191             change-notify()\
    192             set-changed()\n\
    193 <Key>f:     store-to-buffer()\
    194             fold()\
    195             change-notify()\
    196             set-changed()\n\
    197 <Key>h:     store-to-buffer()\
    198             flip-horiz()\
    199             change-notify()\
    200             set-changed()\n\
    201 ";
    202 
    203 static char translations2[] =
    204 "<Key>v:     store-to-buffer()\
    205             flip-vert()\
    206             change-notify()\
    207             set-changed()\n\
    208 <Key>r:     store-to-buffer()\
    209             rotate-right()\
    210             change-notify()\
    211             set-changed()\n\
    212 <Key>l:     store-to-buffer()\
    213             rotate-left()\
    214             change-notify()\
    215             set-changed()\n\
    216 <Key>s:     store-to-buffer()\
    217             set()\
    218             change-notify()\
    219             set-changed()\n\
    220 <Key>c:     store-to-buffer()\
    221             clear()\
    222             change-notify()\
    223             set-changed()\n\
    224 <Key>i:     store-to-buffer()\
    225             invert()\
    226             change-notify()\
    227             set-changed()\n\
    228 <Key>u:     undo()\
    229             change-notify()\
    230             set-changed()\n\
    231 ";
    232 
    233 static Atom targets[] = {
    234     XA_BITMAP,
    235     XA_PIXMAP
    236 };
    237 
    238 #include "Requests.h"
    239 
    240 
    241 static BWRequestRec requests[] =
    242 {
    243 {MarkRequest, sizeof(BWStatus),
    244      TwoPointsEngage, (XtPointer) BWDrawRectangle,
    245      TwoPointsTerminateTimed, (XtPointer) BWSelect,
    246      NULL, (XtPointer) NULL},
    247 {RestoreRequest, sizeof(BWStatus),
    248      OnePointEngage, (XtPointer) BWDragStored,
    249      OnePointTerminate, (XtPointer) BWRestore,
    250      NULL, (XtPointer) NULL},
    251 {ImmediateCopyRequest, sizeof(BWStatus),
    252      OnePointEngage, (XtPointer) BWDragMarked,
    253      OnePointTerminate, (XtPointer) BWCopy,
    254      NULL, (XtPointer) NULL},
    255 {ImmediateMoveRequest, sizeof(BWStatus),
    256      OnePointEngage, (XtPointer) BWDragMarked,
    257      OnePointTerminate, (XtPointer) BWMove,
    258      NULL, (XtPointer) NULL},
    259 {CopyRequest, sizeof(BWStatus),
    260      DragOnePointEngage, (XtPointer) Paste,
    261      DragOnePointTerminate, (XtPointer) ImmediateCopyRequest,
    262      Interface, (XtPointer) BWUnmark},
    263 {MoveRequest, sizeof(BWStatus),
    264      DragOnePointEngage, (XtPointer) Paste,
    265      DragOnePointTerminate, (XtPointer) ImmediateMoveRequest,
    266      Interface, (XtPointer) BWUnmark},
    267 {PointRequest, sizeof(BWStatus),
    268      DragOnePointEngage, (XtPointer) BWDrawPoint,
    269      DragOnePointTerminate, (XtPointer) BWDrawPoint,
    270      NULL, (XtPointer) NULL},
    271 {CurveRequest, sizeof(BWStatus),
    272      DragTwoPointsEngage, (XtPointer) BWBlindLine,
    273      DragTwoPointsTerminate, (XtPointer) BWBlindLine,
    274      NULL, (XtPointer) NULL},
    275 {LineRequest, sizeof(BWStatus),
    276      TwoPointsEngage, (XtPointer) BWDrawLine,
    277      TwoPointsTerminate, (XtPointer) BWDrawLine,
    278      NULL, (XtPointer) NULL},
    279 {RectangleRequest, sizeof(BWStatus),
    280      TwoPointsEngage, (XtPointer) BWDrawRectangle,
    281      TwoPointsTerminate, (XtPointer) BWDrawRectangle,
    282      NULL, (XtPointer) NULL},
    283 {FilledRectangleRequest, sizeof(BWStatus),
    284      TwoPointsEngage, (XtPointer) BWDrawRectangle,
    285      TwoPointsTerminate, (XtPointer) BWDrawFilledRectangle,
    286      NULL, (XtPointer) NULL},
    287 {CircleRequest, sizeof(BWStatus),
    288      TwoPointsEngage, (XtPointer) BWDrawCircle,
    289      TwoPointsTerminate, (XtPointer) BWDrawCircle,
    290      NULL, (XtPointer) NULL},
    291 {FilledCircleRequest, sizeof(BWStatus),
    292      TwoPointsEngage, (XtPointer) BWDrawCircle,
    293      TwoPointsTerminate, (XtPointer) BWDrawFilledCircle,
    294      NULL, (XtPointer) NULL},
    295 {FloodFillRequest, sizeof(BWStatus),
    296      OnePointEngage, (XtPointer) NULL,
    297      OnePointTerminate, (XtPointer) BWFloodFill,
    298      NULL, (XtPointer) NULL},
    299 {HotSpotRequest, sizeof(BWStatus),
    300      OnePointEngage, (XtPointer) BWDrawHotSpot,
    301      OnePointTerminate, (XtPointer) BWDrawHotSpot,
    302      NULL, (XtPointer) NULL},
    303 {ZoomInRequest, sizeof(BWStatus),
    304      TwoPointsEngage, (XtPointer) BWDrawRectangle,
    305      TwoPointsTerminate, (XtPointer) BWZoomIn,
    306      NULL, (XtPointer) NULL},
    307 };
    308 
    309 static void ClassInitialize(void);
    310 static void Initialize(Widget wrequest, Widget wnew,
    311 		       ArgList argv, Cardinal *argc);
    312 static void Redisplay(Widget w, XEvent *event, Region region);
    313 static void Resize(Widget w);
    314 static void Destroy(Widget w);
    315 static void Refresh(BitmapWidget BW, Position x, Position y,
    316 		    Dimension width, Dimension height);
    317 static Boolean SetValues(Widget old, Widget request, Widget new,
    318 			 ArgList args, Cardinal *num_args);
    319 
    320 BitmapClassRec bitmapClassRec = {
    321 {   /* core fields */
    322     /* superclass		*/	(WidgetClass) &simpleClassRec,
    323     /* class_name		*/	"Bitmap",
    324     /* widget_size		*/	sizeof(BitmapRec),
    325     /* class_initialize		*/	ClassInitialize,
    326     /* class_part_initialize	*/	NULL,
    327     /* class_inited		*/	FALSE,
    328     /* initialize		*/	Initialize,
    329     /* initialize_hook		*/	NULL,
    330     /* realize			*/	XtInheritRealize,
    331     /* actions			*/	actions,
    332     /* num_actions		*/	XtNumber(actions),
    333     /* resources		*/	resources,
    334     /* num_resources		*/	XtNumber(resources),
    335     /* xrm_class		*/	NULLQUARK,
    336     /* compress_motion		*/	TRUE,
    337     /* compress_exposure	*/	FALSE,
    338     /* compress_enterleave	*/	TRUE,
    339     /* visible_interest		*/	TRUE,
    340     /* destroy			*/	Destroy,
    341     /* resize			*/	Resize,
    342     /* expose			*/	Redisplay,
    343     /* set_values		*/	SetValues,
    344     /* set_values_hook		*/	NULL,
    345     /* set_values_almost	*/	XtInheritSetValuesAlmost,
    346     /* get_values_hook		*/	NULL,
    347     /* accept_focus		*/	NULL,
    348     /* version			*/	XtVersion,
    349     /* callback_private		*/	NULL,
    350     /* tm_table			*/	NULL , /* set in code */
    351     /* query_geometry		*/	XtInheritQueryGeometry,
    352     /* display_accelerator	*/	XtInheritDisplayAccelerator,
    353     /* extension		*/	NULL,
    354   },
    355   {
    356     /* empty			*/	XtInheritChangeSensitive,
    357   },
    358   {
    359     /* targets                  */      targets,
    360     /* num_trets                */      XtNumber(targets),
    361     /* requests                 */      requests,
    362     /* num_requests             */      XtNumber(requests),
    363   }
    364 };
    365 
    366 WidgetClass bitmapWidgetClass = (WidgetClass) &bitmapClassRec;
    367 
    368 /* ARGSUSED */
    369 
    370 void
    371 BWDebug(Widget w, XEvent *event, String *params, Cardinal *num_params)
    372 {
    373     DEBUG ^= True;
    374 }
    375 
    376 Pixmap
    377 BWGetPixmap(Widget w)
    378 {
    379     BitmapWidget BW = (BitmapWidget) w;
    380 
    381     return GetPixmap(BW, BW->bitmap.zoom.image);
    382 }
    383 
    384 Pixmap
    385 BWGetUnzoomedPixmap(Widget w)
    386 {
    387     BitmapWidget BW = (BitmapWidget) w;
    388     GC gc;
    389     Pixmap pix;
    390 
    391     if (BW->bitmap.zooming) {
    392 	pix = XCreatePixmap(XtDisplay(w), XtWindow(w),
    393 			    BW->bitmap.zoom.image->width,
    394 			    BW->bitmap.zoom.image->height, 1);
    395 	if (!(gc = XCreateGC(XtDisplay(w), pix,
    396 			     (unsigned long) 0, (XGCValues *) 0))) {
    397 	    XFreePixmap(XtDisplay(w), pix);
    398 	    return (Pixmap) None;
    399 	}
    400 
    401 	XPutImage(XtDisplay(w), pix, gc,
    402 		  BW->bitmap.zoom.image,
    403 		  0, 0, 0, 0,
    404 		  BW->bitmap.zoom.image->width,
    405 		  BW->bitmap.zoom.image->height);
    406 	XPutImage(XtDisplay(w), pix, gc,
    407 		  BW->bitmap.image,
    408 		  0, 0,
    409 		  BW->bitmap.zoom.at_x,
    410 		  BW->bitmap.zoom.at_y,
    411 		  BW->bitmap.image->width,
    412 		  BW->bitmap.image->height);
    413     }
    414     else {
    415 	pix = XCreatePixmap(XtDisplay(w), XtWindow(w),
    416 			    BW->bitmap.image->width,
    417 			    BW->bitmap.image->height, 1);
    418 	if (! (gc = XCreateGC(XtDisplay(w), pix,
    419 			      (unsigned long) 0, (XGCValues *) 0))){
    420 	    XFreePixmap(XtDisplay(w), pix);
    421 	    return (Pixmap) None;
    422 	}
    423 
    424 	XPutImage(XtDisplay(w), pix, gc,
    425 		  BW->bitmap.image,
    426 		  0, 0, 0, 0,
    427 		  BW->bitmap.image->width,
    428 		  BW->bitmap.image->height);
    429     }
    430     XFreeGC(XtDisplay(w), gc);
    431     return(pix);
    432 }
    433 
    434 
    435 XImage *
    436 GetImage(BitmapWidget BW, Pixmap pixmap)
    437 {
    438     Window root;
    439     int x, y;
    440     unsigned int width, height, border_width, depth;
    441     XImage *source, *image;
    442 
    443     XGetGeometry(XtDisplay(BW), pixmap, &root, &x, &y,
    444 		 &width, &height, &border_width, &depth);
    445 
    446     source = XGetImage(XtDisplay(BW), pixmap, x, y, width, height,
    447 		     1, XYPixmap);
    448 
    449     image = ConvertToBitmapImage(BW, source);
    450 
    451     return image;
    452 }
    453 
    454 XImage *
    455 CreateBitmapImage(BitmapWidget BW, char *data,
    456 		  Dimension width, Dimension height)
    457 {
    458     XImage *image = XCreateImage(XtDisplay(BW),
    459 				 DefaultVisual(XtDisplay(BW),
    460 					       DefaultScreen(XtDisplay(BW))),
    461 				 1, XYBitmap, 0,
    462 				 data, width, height,
    463 				 8, ((int)width + 7) / 8);
    464 
    465     image->height = height;
    466     image->width = width;
    467     image->depth = 1;
    468     image->xoffset = 0;
    469     image->format = XYBitmap;
    470     image->data = (char *)data;
    471     image->byte_order = LSBFirst;
    472     image->bitmap_unit = 8;
    473     image->bitmap_bit_order = LSBFirst;
    474     image->bitmap_pad = 8;
    475     image->bytes_per_line = ((int)width + 7) / 8;
    476 
    477     return image;
    478 }
    479 
    480 void
    481 DestroyBitmapImage(XImage **image)
    482 {
    483     /*XDestroyImage(*image);*/
    484     if (image) {
    485 	if (*image) {
    486 	    if ((*image)->data)
    487 		XtFree((*image)->data);
    488 	    XtFree((char *)*image);
    489 	}
    490 	*image = NULL;
    491     }
    492 }
    493 
    494 #if 0
    495 XImage *
    496 BWGetImage(Widget w, XEvent *event, String *params, Cardinal *num_params)
    497 {
    498     BitmapWidget BW = (BitmapWidget) w;
    499 
    500     return BW->bitmap.image;
    501 }
    502 #endif
    503 
    504 void
    505 BWChangeNotifyAction(Widget w, _X_UNUSED XEvent *event,
    506                      _X_UNUSED String *params, _X_UNUSED Cardinal *num_params)
    507 {
    508     BWChangeNotify(w);
    509 }
    510 
    511 void
    512 BWChangeNotify(Widget w)
    513 {
    514     BitmapWidget BW = (BitmapWidget) w;
    515 
    516     if (BW->bitmap.notify)
    517 	(*BW->bitmap.notify)(w, NULL, NULL, NULL);
    518 }
    519 
    520 void
    521 BWNotify(Widget w, XtActionProc proc)
    522 {
    523     BitmapWidget BW = (BitmapWidget) w;
    524 
    525     BW->bitmap.notify = proc;
    526 }
    527 
    528 void
    529 BWSetChangedAction(Widget w, _X_UNUSED XEvent *event,
    530                    _X_UNUSED String *params, _X_UNUSED Cardinal *num_params)
    531 {
    532     BWSetChanged(w);
    533 }
    534 
    535 void
    536 BWSetChanged(Widget w)
    537 {
    538     BitmapWidget BW = (BitmapWidget) w;
    539 
    540     BW->bitmap.changed = True;
    541 }
    542 
    543 Boolean
    544 BWQueryChanged(Widget w)
    545 {
    546     BitmapWidget BW = (BitmapWidget) w;
    547 
    548     return BW->bitmap.changed;
    549 }
    550 
    551 void
    552 BWClearChanged(Widget w)
    553 {
    554     BitmapWidget BW = (BitmapWidget) w;
    555 
    556     BW->bitmap.changed = False;
    557 }
    558 
    559 Boolean
    560 BWQueryStored(Widget w)
    561 {
    562     BitmapWidget BW = (BitmapWidget) w;
    563 
    564     return (BW->bitmap.storage != NULL);
    565 }
    566 
    567 Boolean
    568 BWQueryStippled(Widget w)
    569 {
    570     BitmapWidget BW = (BitmapWidget) w;
    571 
    572     return BW->bitmap.stippled;
    573 }
    574 
    575 static void
    576 RedrawStippled(BitmapWidget BW)
    577 {
    578   XExposeEvent event;
    579 
    580   event.type = Expose;
    581   event.display = XtDisplay((Widget)BW);
    582   event.window = XtWindow((Widget)BW);
    583   event.x = 0;
    584   event.y = 0;
    585   event.width = BW->core.width;
    586   event.height = BW->core.height;
    587   event.count = 0;
    588 
    589   BWRedrawMark((Widget)BW);
    590 
    591   BW->bitmap.stipple_change_expose_event = True;
    592 
    593   XtDispatchEvent((XEvent *)&event);
    594 
    595   BW->bitmap.stipple_change_expose_event = False;
    596 }
    597 
    598 void
    599 BWSwitchStippled(Widget w)
    600 {
    601     BitmapWidget BW = (BitmapWidget) w;
    602 
    603     RedrawStippled(BW);
    604 
    605     BW->bitmap.stippled ^= True;
    606     XSetFillStyle(XtDisplay(BW), BW->bitmap.highlighting_gc,
    607 		  (BW->bitmap.stippled ? FillStippled : FillSolid));
    608 
    609     RedrawStippled(BW);
    610 }
    611 
    612 void
    613 BWSelect(Widget w, Position from_x, Position from_y,
    614 	 Position to_x, Position to_y, Time btime)
    615 {
    616     BWMark(w, from_x, from_y, to_x, to_y);
    617 
    618     BWGrabSelection(w, btime);
    619 }
    620 
    621 Boolean
    622 BWQueryAxes(Widget w)
    623 {
    624     BitmapWidget BW = (BitmapWidget) w;
    625 
    626     return BW->bitmap.axes;
    627 }
    628 
    629 void
    630 BWSwitchAxes(Widget w)
    631 {
    632     BitmapWidget BW = (BitmapWidget) w;
    633 
    634     BW->bitmap.axes ^= True;
    635     BWHighlightAxes(w);
    636 }
    637 
    638 void
    639 BWAxes(Widget w, Boolean _switch)
    640 {
    641     BitmapWidget BW = (BitmapWidget) w;
    642 
    643     if (BW->bitmap.axes != _switch)
    644 	BWSwitchAxes(w);
    645 }
    646 
    647 void
    648 BWRedrawAxes(Widget w)
    649 {
    650     BitmapWidget BW = (BitmapWidget) w;
    651 
    652     if (BW->bitmap.axes)
    653 	BWHighlightAxes(w);
    654 }
    655 
    656 #if 0
    657 void
    658 BWPutImage(BitmapWidget w, Display *display, Drawable drawable, GC gc,
    659 	   Position x, Position y)
    660 {
    661     BitmapWidget BW = (BitmapWidget) w;
    662 
    663   XPutImage(display, drawable, gc, BW->bitmap.image,
    664 	    0, 0, x, y, BW->bitmap.image->width, BW->bitmap.image->height);
    665 }
    666 #endif
    667 
    668 static char *
    669 StripFilename(_Xconst _XtString filename)
    670 {
    671     if (filename) {
    672 	const char *begin = strrchr(filename, '/');
    673 	const char *end;
    674 	char *result;
    675 	int length;
    676 
    677 	begin = (begin ? begin + 1 : filename);
    678 	end = strchr(begin, '.'); /* change to strrchr to allow longer names */
    679 	length = (end ? (end - begin) : strlen (begin));
    680 	result = (char *) XtMalloc (length + 1);
    681 	strncpy (result, begin, length);
    682 	result [length] = '\0';
    683 	return (result);
    684     }
    685     else
    686 	return (NULL);
    687 }
    688 
    689 static int
    690 XmuWriteBitmapDataToFile(_Xconst _XtString filename,
    691 			 _Xconst _XtString basename,
    692 			 int width, int height, char *datap,
    693 			 int x_hot, int y_hot)
    694 {
    695     FILE *file;
    696     int i, data_length;
    697 
    698     data_length = Length(width, height);
    699 
    700     if(!filename || !strcmp(filename, "") || !strcmp(filename, "-")) {
    701 	file = stdout;
    702 	filename = "dummy";
    703 	}
    704     else
    705     	file = fopen(filename, "w+");
    706 
    707     if (file) {
    708 	char *new_basename;
    709 
    710 	if (!basename || !strcmp(basename, "") || !strcmp(basename, "-"))
    711 	    basename = new_basename = StripFilename(filename);
    712 	else
    713 	    new_basename = NULL;
    714 
    715 	fprintf(file, "#define %s_width %d\n", basename, width);
    716 	fprintf(file, "#define %s_height %d\n", basename, height);
    717 	if (QuerySet(x_hot, y_hot)) {
    718 	    fprintf(file, "#define %s_x_hot %d\n", basename, x_hot);
    719 	    fprintf(file, "#define %s_y_hot %d\n", basename, y_hot);
    720 	}
    721 	fprintf(file, "static unsigned char %s_bits[] = {\n   0x%02x",
    722 		basename, (unsigned char) datap[0]);
    723 	for(i = 1; i < data_length; i++) {
    724 	    fprintf(file, ",");
    725 	    fprintf(file, (i % 12) ? " " : "\n   ");
    726 	    fprintf(file, "0x%02x", (unsigned char) datap[i]);
    727 	}
    728 	fprintf(file, "};\n");
    729 
    730 	if (file != stdout)
    731 	    fclose(file);
    732 
    733 	XtFree(new_basename);
    734 	return BitmapSuccess;
    735     }
    736 
    737     return 1;
    738 }
    739 
    740 /*
    741  *
    742  */
    743 
    744 				/* ARGSUSED */
    745 static void
    746 CvtStringToButtonFunction(XrmValuePtr args, /* not used */
    747 			  Cardinal *num_args, /* not used */
    748 			  XrmValuePtr from_val,
    749 			  XrmValuePtr to_val)
    750 {
    751   static int button_function;
    752   char lower_name[80];
    753 
    754   XmuCopyISOLatin1Lowered (lower_name, (char*)from_val->addr);
    755 
    756   if (!strcmp(lower_name, XtClear)) {
    757     button_function = Clear;
    758     to_val->addr = (XPointer) &button_function;
    759     to_val->size = sizeof(button_function);
    760     return;
    761   }
    762 
    763   if (!strcmp(lower_name, XtSet)) {
    764     button_function = Set;
    765     to_val->addr = (XPointer) &button_function;
    766     to_val->size = sizeof(button_function);
    767     return;
    768   }
    769 
    770   if (!strcmp(lower_name, XtInvert)) {
    771     button_function = Invert;
    772     to_val->addr = (XPointer) &button_function;
    773     to_val->size = sizeof(button_function);
    774     return;
    775   }
    776 
    777   XtStringConversionWarning(from_val->addr, XtRButtonFunction);
    778   button_function = Clear;
    779   to_val->addr = (XPointer) &button_function;
    780   to_val->size = sizeof(button_function);
    781 
    782 }
    783 
    784 static void
    785 ClassInitialize(void)
    786 {
    787   char *tm_table = XtMalloc(strlen(translations1) + strlen(translations2) + 1);
    788   strcpy(tm_table, translations1);
    789   strcat(tm_table, translations2);
    790   bitmapClassRec.core_class.tm_table = tm_table;
    791 
    792   XawInitializeWidgetSet();
    793   XtAddConverter(XtRString, XtRButtonFunction, CvtStringToButtonFunction,
    794 		 NULL, 0);
    795   DEBUG = False;
    796 }
    797 
    798 static void
    799 SetSizeFromSizeResource(BitmapWidget bw)
    800 {
    801   if (BWParseSize(bw->bitmap.size,
    802 		  &bw->bitmap.width,
    803 		  &bw->bitmap.height)
    804       ==
    805       False) {
    806     bw->bitmap.width = FallbackBitmapWidth;
    807     bw->bitmap.height = FallbackBitmapHeight;
    808     XtWarning("Cannot parse the size resource.  BitmapWidget");
    809   }
    810 }
    811 
    812 
    813 /* ARGSUSED */
    814 static void
    815 Initialize(Widget wrequest, Widget wnew, ArgList argv, Cardinal *argc)
    816 {
    817     BitmapWidget new = (BitmapWidget) wnew;
    818 
    819     XGCValues  values;
    820     XtGCMask   mask;
    821     char *image_data, *buffer_data;
    822 
    823     new->bitmap.stipple_change_expose_event = False;
    824     new->bitmap.notify = NULL;
    825     new->bitmap.cardinal = 0;
    826     new->bitmap.current = 0;
    827     new->bitmap.fold = False;
    828     new->bitmap.changed = False;
    829     new->bitmap.zooming = False;
    830     new->bitmap.selection.own = False;
    831     new->bitmap.selection.limbo = False;
    832 
    833     new->bitmap.request_stack = (BWRequestStack *)
    834 	XtMalloc(sizeof(BWRequestStack));
    835 
    836     new->bitmap.request_stack[0].request = NULL;
    837     new->bitmap.request_stack[0].call_data = NULL;
    838     new->bitmap.request_stack[0].trap = False;
    839 
    840     SetSizeFromSizeResource(new);
    841 
    842     new->core.width = new->bitmap.width * new->bitmap.squareW +
    843 	2 * new->bitmap.margin;
    844     new->core.height = new->bitmap.height * new->bitmap.squareH +
    845 	2 * new->bitmap.margin;
    846 
    847     new->bitmap.hot.x = new->bitmap.hot.y = NotSet;
    848     new->bitmap.buffer_hot.x = new->bitmap.buffer_hot.y = NotSet;
    849 
    850     new->bitmap.mark.from_x = new->bitmap.mark.from_y = NotSet;
    851     new->bitmap.mark.to_x = new->bitmap.mark.to_y = NotSet;
    852     new->bitmap.buffer_mark.from_x = new->bitmap.buffer_mark.from_y = NotSet;
    853     new->bitmap.buffer_mark.to_x = new->bitmap.buffer_mark.to_y = NotSet;
    854 
    855     values.foreground = new->bitmap.foreground_pixel;
    856     values.background = new->core.background_pixel;
    857     values.foreground ^= values.background;
    858     values.function = GXxor;
    859     mask = GCForeground | GCBackground | GCFunction;
    860     new->bitmap.drawing_gc = XCreateGC(XtDisplay(new),
    861 				       RootWindow(XtDisplay(new),
    862 				       DefaultScreen(XtDisplay(new))),
    863 				       mask, &values);
    864 
    865     values.foreground = new->bitmap.highlight_pixel;
    866     values.background = new->core.background_pixel;
    867     values.foreground ^= values.background;
    868     values.function = GXxor;
    869     mask = GCForeground | GCBackground | GCFunction;
    870     if (new->bitmap.stipple != XtUnspecifiedPixmap)
    871     {
    872 	values.stipple = new->bitmap.stipple;
    873 	mask |= GCStipple | GCFillStyle;
    874     }
    875     values.fill_style = (new->bitmap.stippled ? FillStippled : FillSolid);
    876 
    877     new->bitmap.highlighting_gc = XCreateGC(XtDisplay(new),
    878 					    RootWindow(XtDisplay(new),
    879 					       DefaultScreen(XtDisplay(new))),
    880 					    mask, &values);
    881 
    882 
    883     values.foreground = new->bitmap.frame_pixel;
    884     values.background = new->core.background_pixel;
    885     values.foreground ^= values.background;
    886     mask = GCForeground | GCBackground | GCFunction;
    887     if (new->bitmap.dashes != XtUnspecifiedPixmap)
    888     {
    889 	values.stipple = new->bitmap.dashes;
    890 	mask |= GCStipple | GCFillStyle;
    891     }
    892     values.fill_style = (new->bitmap.dashed ? FillStippled : FillSolid);
    893 
    894     new->bitmap.frame_gc = XCreateGC(XtDisplay(new),
    895 				     RootWindow(XtDisplay(new),
    896 						DefaultScreen(XtDisplay(new))),
    897 				     mask, &values);
    898 
    899     values.foreground = new->bitmap.highlight_pixel;
    900     values.background = new->core.background_pixel;
    901     values.foreground ^= values.background;
    902     mask = GCForeground | GCBackground | GCFunction;
    903     new->bitmap.axes_gc = XCreateGC(XtDisplay(new),
    904 				     RootWindow(XtDisplay(new),
    905 						DefaultScreen(XtDisplay(new))),
    906 				     mask, &values);
    907 
    908     image_data = CreateCleanData(Length(new->bitmap.width,
    909 					new->bitmap.height));
    910     buffer_data = CreateCleanData(Length(new->bitmap.width,
    911 					 new->bitmap.height));
    912 
    913     new->bitmap.storage = NULL;
    914 
    915     new->bitmap.image = CreateBitmapImage(new,
    916 					  image_data,
    917 					  new->bitmap.width,
    918 					  new->bitmap.height);
    919     new->bitmap.buffer = CreateBitmapImage(new,
    920 					   buffer_data,
    921 					   new->bitmap.width,
    922 					   new->bitmap.height);
    923 
    924     /* Read file */
    925     {
    926 	int status;
    927 	XImage *image, *buffer;
    928 	unsigned char *image_data2;
    929 	char *buffer_data2;
    930 	unsigned int width, height;
    931 	int x_hot, y_hot;
    932 
    933 	status = XmuReadBitmapDataFromFile(new->bitmap.filename,
    934 					   &width, &height, &image_data2,
    935 					   &x_hot, &y_hot);
    936 	if (status == BitmapSuccess) {
    937 
    938 	    buffer_data2 = CreateCleanData(Length(width, height));
    939 
    940 	    image = CreateBitmapImage(new, (char *)image_data2, width, height);
    941 	    buffer = CreateBitmapImage(new, buffer_data2, width, height);
    942 
    943 	    TransferImageData(new->bitmap.image, buffer);
    944 
    945 	    DestroyBitmapImage(&new->bitmap.image);
    946 	    DestroyBitmapImage(&new->bitmap.buffer);
    947 
    948 	    new->bitmap.image = image;
    949 	    new->bitmap.buffer = buffer;
    950 	    new->bitmap.width = width;
    951 	    new->bitmap.height = height;
    952 
    953 	    new->bitmap.hot.x = x_hot;
    954 	    new->bitmap.hot.y = y_hot;
    955 
    956 	    new->bitmap.changed = False;
    957 	    new->bitmap.zooming = False;
    958 	}
    959 
    960 	new->bitmap.filename = XtNewString(new->bitmap.filename);
    961 
    962 	if (!strcmp(new->bitmap.basename, "")) {
    963 	    new->bitmap.basename = StripFilename(new->bitmap.filename);
    964 	}
    965 	else
    966 	  new->bitmap.basename = XtNewString(new->bitmap.basename);
    967     }
    968 
    969     Resize((Widget)new);
    970 }
    971 
    972 
    973 /* returns False if the format is wrong */
    974 Boolean
    975 BWParseSize(String size, Dimension *width, Dimension *height)
    976 {
    977   int x, y;
    978   unsigned int w, h;
    979   int status;
    980 
    981   status = XParseGeometry(size, &x, &y, &w, &h);
    982 
    983   if (status & WidthValue) {
    984     *width = (Dimension) w;
    985     if (status & HeightValue) {
    986       *height = (Dimension) h;
    987       return True;
    988     }
    989   }
    990   return False;
    991 
    992 }
    993 
    994 
    995 Boolean
    996 BWQueryMarked(Widget w)
    997 {
    998     BitmapWidget BW = (BitmapWidget) w;
    999 
   1000     return QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y);
   1001 }
   1002 
   1003 static void
   1004 FixMark(BitmapWidget BW)
   1005 {
   1006     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
   1007 	BW->bitmap.mark.from_x = min(BW->bitmap.mark.from_x,
   1008 				     BW->bitmap.image->width);
   1009 	BW->bitmap.mark.from_y = min(BW->bitmap.mark.from_y,
   1010 				     BW->bitmap.image->height);
   1011 	BW->bitmap.mark.to_x = min(BW->bitmap.mark.to_x,
   1012 				   BW->bitmap.image->width);
   1013 	BW->bitmap.mark.to_y = min(BW->bitmap.mark.to_y,
   1014 				   BW->bitmap.image->height);
   1015 
   1016 	if((BW->bitmap.mark.from_x == BW->bitmap.mark.from_y) &&
   1017 	   (BW->bitmap.mark.to_x   == BW->bitmap.mark.to_y))
   1018 	    BW->bitmap.mark.from_x =
   1019 		BW->bitmap.mark.from_y =
   1020 		    BW->bitmap.mark.to_x =
   1021 			BW->bitmap.mark.to_y = NotSet;
   1022     }
   1023 }
   1024 
   1025 /* ARGSUSED */
   1026 int
   1027 BWStoreFile(Widget w, _Xconst _XtString filename, _Xconst _XtString *basename)
   1028 {
   1029     BitmapWidget BW = (BitmapWidget) w;
   1030     int status;
   1031     unsigned char *storage_data;
   1032     unsigned int width, height;
   1033     int x_hot, y_hot;
   1034 
   1035     status = XmuReadBitmapDataFromFile(filename, &width, &height,
   1036 				       &storage_data, &x_hot, &y_hot);
   1037     if (status == BitmapSuccess) {
   1038 
   1039 	DestroyBitmapImage(&BW->bitmap.storage);
   1040 
   1041 	BW->bitmap.storage = CreateBitmapImage(BW, (char *)storage_data, width, height);
   1042 
   1043 	return BitmapSuccess;
   1044     }
   1045     else
   1046 	XtWarning(" read file failed.  BitmapWidget");
   1047 
   1048     return status;
   1049 }
   1050 
   1051 String
   1052 BWUnparseStatus(Widget w)
   1053 {
   1054     BitmapWidget BW = (BitmapWidget) w;
   1055 
   1056     snprintf(BW->bitmap.status, sizeof(BW->bitmap.status),
   1057 	    "Filename: %s  Basename: %s  Size: %dx%d",
   1058 	    (strcmp(BW->bitmap.filename, "") ? BW->bitmap.filename : "<none>"),
   1059 	    (strcmp(BW->bitmap.basename, "") ? BW->bitmap.basename : "<none>"),
   1060 	    BW->bitmap.width, BW->bitmap.height);
   1061 
   1062     return BW->bitmap.status;
   1063 }
   1064 
   1065 void
   1066 BWChangeFilename(Widget w, _Xconst _XtString str)
   1067 {
   1068   BitmapWidget BW = (BitmapWidget) w;
   1069 
   1070   if (str) {
   1071     XtFree(BW->bitmap.filename);
   1072     BW->bitmap.filename = XtNewString( str);
   1073   }
   1074 }
   1075 
   1076 void
   1077 BWChangeBasename(Widget w, _Xconst _XtString str)
   1078 {
   1079   BitmapWidget BW = (BitmapWidget) w;
   1080 
   1081   if (str) {
   1082     XtFree(BW->bitmap.basename);
   1083     BW->bitmap.basename = XtNewString(str);
   1084   }
   1085 }
   1086 
   1087 
   1088 int
   1089 BWReadFile(Widget w, _Xconst _XtString filename, _Xconst _XtString basename) /* ARGSUSED */
   1090 {
   1091     BitmapWidget BW = (BitmapWidget) w;
   1092     int status;
   1093     XImage *image, *buffer;
   1094     unsigned char *image_data;
   1095     char *buffer_data;
   1096     unsigned int width, height;
   1097     int x_hot, y_hot;
   1098 
   1099     if (!filename)
   1100 	filename = BW->bitmap.filename;
   1101 
   1102     status = XmuReadBitmapDataFromFile(filename, &width, &height, &image_data,
   1103 				       &x_hot, &y_hot);
   1104     if (status == BitmapSuccess) {
   1105 
   1106 	buffer_data = CreateCleanData(Length(width, height));
   1107 
   1108 	image = CreateBitmapImage(BW, (char *)image_data, width, height);
   1109 	buffer = CreateBitmapImage(BW, buffer_data, width, height);
   1110 
   1111 	TransferImageData(BW->bitmap.image, buffer);
   1112 
   1113 	DestroyBitmapImage(&BW->bitmap.image);
   1114 	DestroyBitmapImage(&BW->bitmap.buffer);
   1115 
   1116 	BW->bitmap.image = image;
   1117 	BW->bitmap.buffer = buffer;
   1118 	BW->bitmap.width = width;
   1119 	BW->bitmap.height = height;
   1120 
   1121 	BW->bitmap.hot.x = x_hot;
   1122 	BW->bitmap.hot.y = y_hot;
   1123 
   1124 	BW->bitmap.changed = False;
   1125 	BW->bitmap.zooming = False;
   1126 
   1127 	XtFree(BW->bitmap.filename);
   1128 	BW->bitmap.filename = XtNewString(filename);
   1129 	XtFree(BW->bitmap.basename);
   1130 	BW->bitmap.basename = StripFilename(filename);
   1131 
   1132 	BWUnmark(w);
   1133 
   1134 	Resize((Widget)BW);
   1135 
   1136 	if (BW->core.visible) {
   1137 	    XClearArea(XtDisplay(BW), XtWindow(BW),
   1138 		       0, 0,
   1139 		       BW->core.width, BW->core.height,
   1140 		       True);
   1141 	}
   1142 
   1143 	return BitmapSuccess;
   1144     }
   1145     else
   1146 	XtWarning(" read file failed.  BitmapWidget");
   1147 
   1148     return status;
   1149 }
   1150 
   1151 #if 0
   1152 void
   1153 BWSetImage(Widget w, XImage *image)
   1154 {
   1155     BitmapWidget BW = (BitmapWidget) w;
   1156     XImage *buffer;
   1157     char *buffer_data;
   1158 
   1159     buffer_data = CreateCleanData(Length(image->width, image->height));
   1160     buffer = CreateBitmapImage(BW, buffer_data,
   1161 			       (Dimension) image->width,
   1162 			       (Dimension) image->height);
   1163 
   1164     TransferImageData(BW->bitmap.image, buffer);
   1165 
   1166     DestroyBitmapImage(&BW->bitmap.image);
   1167     DestroyBitmapImage(&BW->bitmap.buffer);
   1168 
   1169     BW->bitmap.image = image;
   1170     BW->bitmap.buffer = buffer;
   1171     BW->bitmap.width = image->width;
   1172     BW->bitmap.height = image->height;
   1173 
   1174     Resize((Widget)BW);
   1175 
   1176     if (BW->core.visible) {
   1177 	XClearArea(XtDisplay(BW), XtWindow(BW),
   1178 		   0, 0,
   1179 		   BW->core.width, BW->core.height,
   1180 		   True);
   1181     }
   1182 }
   1183 #endif
   1184 
   1185 int
   1186 BWWriteFile(Widget w, _Xconst _XtString filename, _Xconst _XtString basename)
   1187 {
   1188     BitmapWidget BW = (BitmapWidget) w;
   1189     char *data;
   1190     XImage *image;
   1191     XPoint hot;
   1192     int status;
   1193 
   1194     if (BW->bitmap.zooming) {
   1195         data = XtMalloc(Length(BW->bitmap.zoom.image->width,
   1196 			       BW->bitmap.zoom.image->height));
   1197 	memmove( data, BW->bitmap.zoom.image->data,
   1198 	      Length(BW->bitmap.zoom.image->width,
   1199 		     BW->bitmap.zoom.image->height));
   1200 	image = CreateBitmapImage(BW, data,
   1201 				  (Dimension) BW->bitmap.zoom.image->width,
   1202 				  (Dimension) BW->bitmap.zoom.image->height);
   1203 	CopyImageData(BW->bitmap.image, image,
   1204 		      0, 0,
   1205 		      BW->bitmap.image->width - 1,
   1206 		      BW->bitmap.image->height - 1,
   1207 		      BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y);
   1208 
   1209 	if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
   1210 	    hot.x = BW->bitmap.hot.x + BW->bitmap.zoom.at_x;
   1211 	    hot.y = BW->bitmap.hot.y + BW->bitmap.zoom.at_y;
   1212 	}
   1213 	else
   1214 	    hot = BW->bitmap.zoom.hot;
   1215     }
   1216     else {
   1217 	image = BW->bitmap.image;
   1218 	hot = BW->bitmap.hot;
   1219     }
   1220 
   1221     if (!filename) filename = BW->bitmap.filename;
   1222     else {
   1223 	XtFree(BW->bitmap.filename);
   1224 	BW->bitmap.filename = XtNewString(filename);
   1225 	XtFree(BW->bitmap.basename);
   1226 	BW->bitmap.basename = StripFilename(filename);
   1227     }
   1228     if (!basename) basename = BW->bitmap.basename;
   1229     else {
   1230 	XtFree(BW->bitmap.basename);
   1231 	BW->bitmap.basename = XtNewString(basename);
   1232     }
   1233 
   1234     if (DEBUG)
   1235 	fprintf(stderr, "Saving filename: %s %s\n", filename, basename);
   1236 
   1237     status = XmuWriteBitmapDataToFile(filename, basename,
   1238 				      image->width, image->height, image->data,
   1239 				      hot.x, hot.y);
   1240     if (BW->bitmap.zooming)
   1241 	DestroyBitmapImage(&image);
   1242 
   1243     if (status == BitmapSuccess)
   1244 	BW->bitmap.changed = False;
   1245 
   1246     return status;
   1247 }
   1248 
   1249 _XtString
   1250 BWGetFilename(Widget w, _XtString *str)
   1251 {
   1252     BitmapWidget BW = (BitmapWidget) w;
   1253 
   1254     *str = XtNewString(BW->bitmap.filename);
   1255 
   1256     return *str;
   1257 }
   1258 
   1259 _XtString
   1260 BWGetFilepath(Widget w, _XtString *str)
   1261 {
   1262     BitmapWidget BW = (BitmapWidget) w;
   1263     _XtString end;
   1264 
   1265     *str = XtNewString(BW->bitmap.filename);
   1266     assert(*str);
   1267 
   1268     end = strrchr(*str, '/');
   1269 
   1270     if (end)
   1271 	*(end + 1) = '\0';
   1272     else
   1273 	**str = '\0';
   1274 
   1275     return *str;
   1276 }
   1277 
   1278 
   1279 _XtString
   1280 BWGetBasename(Widget w, _XtString *str)
   1281 {
   1282     BitmapWidget BW = (BitmapWidget) w;
   1283 
   1284     *str = XtNewString(BW->bitmap.basename);
   1285 
   1286     return *str;
   1287 }
   1288 
   1289 static void
   1290 FixHotSpot(BitmapWidget BW)
   1291 {
   1292     if (!QueryInBitmap(BW, BW->bitmap.hot.x, BW->bitmap.hot.y))
   1293 	BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet;
   1294 }
   1295 
   1296 static void
   1297 ZoomOut(BitmapWidget BW)
   1298 {
   1299     CopyImageData(BW->bitmap.image, BW->bitmap.zoom.image,
   1300 		  0, 0,
   1301 		  BW->bitmap.image->width - 1,
   1302 		  BW->bitmap.image->height - 1,
   1303 		  BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y);
   1304 
   1305     DestroyBitmapImage(&BW->bitmap.image);
   1306     DestroyBitmapImage(&BW->bitmap.buffer);
   1307 
   1308     BW->bitmap.image = BW->bitmap.zoom.image;
   1309     BW->bitmap.buffer = BW->bitmap.zoom.buffer;
   1310     BW->bitmap.width = BW->bitmap.image->width;
   1311     BW->bitmap.height = BW->bitmap.image->height;
   1312     BW->bitmap.fold = BW->bitmap.zoom.fold;
   1313     BW->bitmap.changed |= BW->bitmap.zoom.changed;
   1314     BW->bitmap.grid = BW->bitmap.zoom.grid;
   1315 
   1316     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
   1317 	BW->bitmap.hot.x += BW->bitmap.zoom.at_x;
   1318 	BW->bitmap.hot.y += BW->bitmap.zoom.at_y;
   1319     }
   1320     else
   1321 	BW->bitmap.hot = BW->bitmap.zoom.hot;
   1322 
   1323     BW->bitmap.mark.from_x = NotSet;
   1324     BW->bitmap.mark.from_y = NotSet;
   1325     BW->bitmap.mark.to_x = NotSet;
   1326     BW->bitmap.mark.to_y = NotSet;
   1327     BW->bitmap.zooming = False;
   1328 }
   1329 
   1330 void
   1331 BWZoomOut(Widget w)
   1332 {
   1333     BitmapWidget BW = (BitmapWidget) w;
   1334 
   1335     if (BW->bitmap.zooming) {
   1336 	ZoomOut(BW);
   1337 
   1338 	Resize((Widget)BW);
   1339 	if (BW->core.visible)
   1340 	    XClearArea(XtDisplay(BW), XtWindow(BW),
   1341 		       0, 0,
   1342 		       BW->core.width, BW->core.height,
   1343 		       True);
   1344     }
   1345 }
   1346 
   1347 
   1348 void
   1349 BWZoomMarked(Widget w)
   1350 {
   1351     BitmapWidget BW = (BitmapWidget) w;
   1352 
   1353     BWZoomIn(w,
   1354 	     BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
   1355 	     BW->bitmap.mark.to_x,   BW->bitmap.mark.to_y);
   1356 }
   1357 
   1358 void
   1359 BWZoomIn(Widget w,
   1360 	 Position from_x, Position from_y,
   1361 	 Position to_x, Position to_y)
   1362 {
   1363     BitmapWidget BW = (BitmapWidget) w;
   1364     XImage *image, *buffer;
   1365     Dimension width, height;
   1366     char *image_data, *buffer_data;
   1367 
   1368     if (BW->bitmap.zooming)
   1369 	ZoomOut(BW);
   1370 
   1371     QuerySwap(from_x, to_x);
   1372     QuerySwap(from_y, to_y);
   1373     from_x = max(0, from_x);
   1374     from_y = max(0, from_y);
   1375     to_x = min(BW->bitmap.width - 1, to_x);
   1376     to_y = min(BW->bitmap.height - 1, to_y);
   1377 
   1378     width = to_x - from_x + 1;
   1379     height = to_y - from_y + 1;
   1380 
   1381     image_data = CreateCleanData(Length(width, height));
   1382     buffer_data = CreateCleanData(Length(width, height));
   1383 
   1384     image = CreateBitmapImage(BW, image_data, width, height);
   1385     buffer = CreateBitmapImage(BW, buffer_data, width, height);
   1386 
   1387     CopyImageData(BW->bitmap.image, image, from_x, from_y, to_x, to_y, 0, 0);
   1388     CopyImageData(BW->bitmap.buffer, buffer, from_x, from_y, to_x, to_y, 0, 0);
   1389 
   1390     BW->bitmap.zoom.image = BW->bitmap.image;
   1391     BW->bitmap.zoom.buffer = BW->bitmap.buffer;
   1392     BW->bitmap.zoom.at_x = from_x;
   1393     BW->bitmap.zoom.at_y = from_y;
   1394     BW->bitmap.zoom.fold = BW->bitmap.fold;
   1395     BW->bitmap.zoom.changed = BW->bitmap.changed;
   1396     BW->bitmap.zoom.hot = BW->bitmap.hot;
   1397     BW->bitmap.zoom.grid = BW->bitmap.grid;
   1398 
   1399     BW->bitmap.image = image;
   1400     BW->bitmap.buffer = buffer;
   1401     BW->bitmap.width = width;
   1402     BW->bitmap.height = height;
   1403     BW->bitmap.changed = False;
   1404     BW->bitmap.hot.x -= from_x;
   1405     BW->bitmap.hot.y -= from_y;
   1406     BW->bitmap.mark.from_x = NotSet;
   1407     BW->bitmap.mark.from_y = NotSet;
   1408     BW->bitmap.mark.to_x = NotSet;
   1409     BW->bitmap.mark.to_y = NotSet;
   1410     BW->bitmap.zooming = True;
   1411     BW->bitmap.grid = True; /* potentially true, could use a resource here */
   1412 
   1413     FixHotSpot(BW);
   1414 
   1415     Resize((Widget)BW);
   1416     if (BW->core.visible)
   1417 	XClearArea(XtDisplay(BW), XtWindow(BW),
   1418 		   0, 0,
   1419 		   BW->core.width, BW->core.height,
   1420 		   True);
   1421 }
   1422 
   1423 
   1424 void
   1425 BWRescale(Widget w, Dimension width, Dimension height)
   1426 {
   1427     BitmapWidget BW = (BitmapWidget) w;
   1428     XImage *image, *buffer;
   1429     char *buffer_data;
   1430 
   1431     if (BW->bitmap.zooming)
   1432 	ZoomOut(BW);
   1433 
   1434     image = ScaleBitmapImage(BW, BW->bitmap.image,
   1435 		       (double) width / (double) BW->bitmap.image->width,
   1436 		       (double) height / (double) BW->bitmap.image->height);
   1437 
   1438     buffer_data = CreateCleanData(Length(image->width, image->height));
   1439     buffer = CreateBitmapImage(BW, buffer_data,
   1440 			       (Dimension) image->width,
   1441 			       (Dimension) image->height);
   1442 
   1443     TransferImageData(BW->bitmap.buffer, buffer);
   1444 
   1445     DestroyBitmapImage(&BW->bitmap.image);
   1446     DestroyBitmapImage(&BW->bitmap.buffer);
   1447 
   1448     BW->bitmap.image = image;
   1449     BW->bitmap.buffer = buffer;
   1450     BW->bitmap.width = image->width;
   1451     BW->bitmap.height = image->height;
   1452 
   1453     FixHotSpot(BW);
   1454     FixMark(BW);
   1455 
   1456     Resize((Widget)BW);
   1457     if (BW->core.visible)
   1458 	XClearArea(XtDisplay(BW), XtWindow(BW),
   1459 		   0, 0,
   1460 		   BW->core.width, BW->core.height,
   1461 		   True);
   1462 }
   1463 
   1464 Boolean
   1465 BWQueryZooming(Widget w)
   1466 {
   1467     BitmapWidget BW = (BitmapWidget) w;
   1468 
   1469     return BW->bitmap.zooming;
   1470 }
   1471 
   1472 
   1473 static void
   1474 ResizeGrid(BitmapWidget BW, Dimension width, Dimension height)
   1475 {
   1476   XImage *image, *buffer;
   1477   char *image_data, *buffer_data;
   1478 
   1479   if (BW->bitmap.zooming)
   1480     ZoomOut(BW);
   1481 
   1482   image_data = CreateCleanData(Length(width, height));
   1483   buffer_data = CreateCleanData(Length(width, height));
   1484 
   1485   image = CreateBitmapImage(BW, image_data, width, height);
   1486   buffer = CreateBitmapImage(BW, buffer_data, width, height);
   1487 
   1488   TransferImageData(BW->bitmap.image, image);
   1489   TransferImageData(BW->bitmap.buffer, buffer);
   1490 
   1491   DestroyBitmapImage(&BW->bitmap.image);
   1492   DestroyBitmapImage(&BW->bitmap.buffer);
   1493 
   1494   BW->bitmap.image = image;
   1495   BW->bitmap.buffer = buffer;
   1496   BW->bitmap.width = width;
   1497   BW->bitmap.height = height;
   1498 
   1499   FixHotSpot(BW);
   1500   FixMark(BW);
   1501 }
   1502 
   1503 void
   1504 BWResize(Widget w, Dimension width, Dimension height)
   1505 {
   1506     BitmapWidget BW = (BitmapWidget) w;
   1507 
   1508     ResizeGrid(BW, width, height);
   1509 
   1510     Resize((Widget)BW);
   1511     if (BW->core.visible)
   1512 	XClearArea(XtDisplay(BW), XtWindow(BW),
   1513 		   0, 0,
   1514 		   BW->core.width, BW->core.height,
   1515 		   True);
   1516 }
   1517 
   1518 static void
   1519 Destroy(Widget w)
   1520 {
   1521     BitmapWidget BW = (BitmapWidget) w;
   1522 
   1523     XFreeGC(XtDisplay(w), BW->bitmap.drawing_gc);
   1524     XFreeGC(XtDisplay(w), BW->bitmap.highlighting_gc);
   1525     XFreeGC(XtDisplay(w), BW->bitmap.frame_gc);
   1526     XFreeGC(XtDisplay(w), BW->bitmap.axes_gc);
   1527     BWRemoveAllRequests(w);
   1528 
   1529     XtFree(BW->bitmap.filename);
   1530     XtFree(BW->bitmap.basename);
   1531 }
   1532 
   1533 
   1534 static void
   1535 Resize(Widget w)
   1536 {
   1537     BitmapWidget BW = (BitmapWidget) w;
   1538 
   1539     Dimension squareW, squareH;
   1540 
   1541     squareW = max(1, ((int)BW->core.width - 2 * (int)BW->bitmap.margin) /
   1542 		  (int)BW->bitmap.width);
   1543     squareH = max(1, ((int)BW->core.height - 2 * (int)BW->bitmap.margin) /
   1544 		  (int)BW->bitmap.height);
   1545 
   1546     if (BW->bitmap.proportional)
   1547 	BW->bitmap.squareW = BW->bitmap.squareH = min(squareW, squareH);
   1548     else {
   1549 	BW->bitmap.squareW = squareW;
   1550 	BW->bitmap.squareH = squareH;
   1551     }
   1552 
   1553     BW->bitmap.horizOffset = max((Position)BW->bitmap.margin,
   1554 				 (Position)(BW->core.width -
   1555 					    BW->bitmap.width *
   1556 					    BW->bitmap.squareW) / 2);
   1557     BW->bitmap.vertOffset = max((Position)BW->bitmap.margin,
   1558 				(Position)(BW->core.height -
   1559 					   BW->bitmap.height *
   1560 					   BW->bitmap.squareH) / 2);
   1561 
   1562     BW->bitmap.grid &= ((BW->bitmap.squareW > BW->bitmap.grid_tolerance) &&
   1563 			(BW->bitmap.squareH > BW->bitmap.grid_tolerance));
   1564 }
   1565 
   1566 /* ARGSUSED */
   1567 static void
   1568 Redisplay(Widget w, XEvent *event, Region region)
   1569 {
   1570      BitmapWidget BW = (BitmapWidget) w;
   1571 
   1572   if(event->type == Expose
   1573      &&
   1574      BW->core.visible)
   1575     if (BW->bitmap.stipple_change_expose_event == False)
   1576       Refresh(BW,
   1577 	      event->xexpose.x, event->xexpose.y,
   1578 	      event->xexpose.width, event->xexpose.height);
   1579 }
   1580 
   1581 void
   1582 BWClip(Widget w, Position x, Position y, Dimension width, Dimension height)
   1583 {
   1584     Position      from_x, from_y,
   1585                   to_x, to_y;
   1586     BitmapWidget BW = (BitmapWidget) w;
   1587     XRectangle rectangle;
   1588 
   1589     from_x = InBitmapX(BW, x);
   1590     from_y = InBitmapY(BW, y);
   1591     to_x = InBitmapX(BW, x + width);
   1592     to_y = InBitmapY(BW, y + height);
   1593     QuerySwap(from_x, to_x);
   1594     QuerySwap(from_y, to_y);
   1595     from_x = max(0, from_x);
   1596     from_y = max(0, from_y);
   1597     to_x = min(BW->bitmap.width - 1, to_x);
   1598     to_y = min(BW->bitmap.height - 1, to_y);
   1599 
   1600     rectangle.x = InWindowX(BW, from_x);
   1601     rectangle.y = InWindowY(BW, from_y);
   1602     rectangle.width = InWindowX(BW, to_x  + 1) - InWindowX(BW, from_x);
   1603     rectangle.height = InWindowY(BW, to_y + 1) - InWindowY(BW, from_y);
   1604     XSetClipRectangles(XtDisplay(BW),
   1605 		       BW->bitmap.highlighting_gc,
   1606 		       0, 0,
   1607 		       &rectangle, 1,
   1608 		       Unsorted);
   1609     XSetClipRectangles(XtDisplay(BW),
   1610 		       BW->bitmap.drawing_gc,
   1611 		       0, 0,
   1612 		       &rectangle, 1,
   1613 		       Unsorted);
   1614     XSetClipRectangles(XtDisplay(BW),
   1615 		       BW->bitmap.frame_gc,
   1616 		       0, 0,
   1617 		       &rectangle, 1,
   1618 		       Unsorted);
   1619     XSetClipRectangles(XtDisplay(BW),
   1620 		       BW->bitmap.axes_gc,
   1621 		       0, 0,
   1622 		       &rectangle, 1,
   1623 		       Unsorted);
   1624 }
   1625 
   1626 void
   1627 BWUnclip(Widget w)
   1628 {
   1629     BitmapWidget BW = (BitmapWidget) w;
   1630     XRectangle rectangle;
   1631 
   1632     rectangle.x = InWindowX(BW, 0);
   1633     rectangle.y = InWindowY(BW, 0);
   1634     rectangle.width = InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0);
   1635     rectangle.height = InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0);
   1636     XSetClipRectangles(XtDisplay(BW),
   1637 		       BW->bitmap.highlighting_gc,
   1638 		       0, 0,
   1639 		       &rectangle, 1,
   1640 		       Unsorted);
   1641     XSetClipRectangles(XtDisplay(BW),
   1642 		       BW->bitmap.drawing_gc,
   1643 		       0, 0,
   1644 		       &rectangle, 1,
   1645 		       Unsorted);
   1646     XSetClipRectangles(XtDisplay(BW),
   1647 		       BW->bitmap.frame_gc,
   1648 		       0, 0,
   1649 		       &rectangle, 1,
   1650 		       Unsorted);
   1651     XSetClipRectangles(XtDisplay(BW),
   1652 		       BW->bitmap.axes_gc,
   1653 		       0, 0,
   1654 		       &rectangle, 1,
   1655 		       Unsorted);
   1656 }
   1657 
   1658 static void
   1659 Refresh(BitmapWidget BW, Position x, Position y,
   1660 	Dimension width, Dimension height)
   1661 {
   1662     XRectangle rectangle;
   1663 
   1664     rectangle.x = min(x, InWindowX(BW, InBitmapX(BW, x)));
   1665     rectangle.y = min(y, InWindowY(BW, InBitmapY(BW, y)));
   1666     rectangle.width = max(x + width,
   1667 		     InWindowX(BW, InBitmapX(BW, x + width)+1)) - rectangle.x;
   1668     rectangle.height = max(y + height,
   1669 		     InWindowY(BW, InBitmapY(BW, y + height)+1)) - rectangle.y;
   1670 
   1671     XClearArea(XtDisplay(BW), XtWindow(BW),
   1672 	       rectangle.x, rectangle.y,
   1673 	       rectangle.width, rectangle.height,
   1674 	       False);
   1675 
   1676     XSetClipRectangles(XtDisplay(BW),
   1677 		       BW->bitmap.frame_gc,
   1678 		       0, 0,
   1679 		       &rectangle, 1,
   1680 		       Unsorted);
   1681 
   1682     XDrawRectangle(XtDisplay(BW), XtWindow(BW),
   1683 		   BW->bitmap.frame_gc,
   1684 		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
   1685 		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
   1686 		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
   1687 
   1688     BWClip((Widget) BW, x, y, width, height);
   1689 
   1690     BWRedrawGrid((Widget) BW, x, y, width, height);
   1691 
   1692     BWRedrawSquares((Widget) BW, x, y, width, height);
   1693 
   1694     BWRedrawMark((Widget) BW);
   1695     BWRedrawHotSpot((Widget) BW);
   1696     BWRedrawAxes((Widget) BW);
   1697     BWUnclip((Widget) BW);
   1698 }
   1699 
   1700 Boolean
   1701 BWQueryGrid(Widget w)
   1702 {
   1703     BitmapWidget BW = (BitmapWidget) w;
   1704 
   1705     return BW->bitmap.grid;
   1706 }
   1707 
   1708 void
   1709 BWSwitchGrid(Widget w)
   1710 {
   1711     BitmapWidget BW = (BitmapWidget) w;
   1712     BW->bitmap.grid ^= TRUE;
   1713     BWDrawGrid(w,
   1714 	       0, 0,
   1715 	       BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
   1716 }
   1717 
   1718 void
   1719 BWGrid(Widget w, Boolean _switch)
   1720 {
   1721     BitmapWidget BW = (BitmapWidget) w;
   1722 
   1723     if (BW->bitmap.grid != _switch)
   1724 	BWSwitchGrid(w);
   1725 }
   1726 
   1727 Boolean
   1728 BWQueryDashed(Widget w)
   1729 {
   1730     BitmapWidget BW = (BitmapWidget) w;
   1731 
   1732     return (BW->bitmap.dashed);
   1733 }
   1734 
   1735 void
   1736 BWSwitchDashed(Widget w)
   1737 {
   1738     BitmapWidget BW = (BitmapWidget) w;
   1739     XRectangle rectangle;
   1740 
   1741     BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1);
   1742 
   1743     rectangle.x = 0;
   1744     rectangle.y = 0;
   1745     rectangle.width = BW->core.width;
   1746     rectangle.height = BW->core.height;
   1747 
   1748     XSetClipRectangles(XtDisplay(BW),
   1749 		       BW->bitmap.frame_gc,
   1750 		       0, 0,
   1751 		       &rectangle, 1,
   1752 		       Unsorted);
   1753 
   1754     XDrawRectangle(XtDisplay(BW), XtWindow(BW),
   1755 		   BW->bitmap.frame_gc,
   1756 		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
   1757 		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
   1758 		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
   1759 
   1760     BW->bitmap.dashed ^= True;
   1761     XSetFillStyle(XtDisplay(BW), BW->bitmap.frame_gc,
   1762 		  (BW->bitmap.dashed ? FillStippled : FillSolid));
   1763 
   1764     XDrawRectangle(XtDisplay(BW), XtWindow(BW),
   1765 		   BW->bitmap.frame_gc,
   1766 		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
   1767 		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
   1768 		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
   1769 
   1770     BWUnclip(w);
   1771 
   1772     BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1);
   1773 }
   1774 
   1775 void
   1776 BWDashed(Widget w, Boolean _switch)
   1777 {
   1778     BitmapWidget BW = (BitmapWidget) w;
   1779 
   1780     if (BW->bitmap.dashed != _switch)
   1781 	BWSwitchDashed(w);
   1782 }
   1783 
   1784 static Boolean
   1785 SetValues(Widget old, Widget request, Widget new,
   1786 	  ArgList args, Cardinal *num_args) /* ARGSUSED */
   1787 {
   1788   BitmapWidget oldbw = (BitmapWidget) old;
   1789   BitmapWidget newbw = (BitmapWidget) new;
   1790   Boolean resize = False;
   1791   Boolean redisplay = False;
   1792 
   1793 #define NE(field) (oldbw->field != newbw->field)
   1794 
   1795   if (NE(bitmap.grid))
   1796     BWSwitchGrid(old);
   1797 
   1798   if (NE(bitmap.dashed))
   1799     BWSwitchDashed(old);
   1800 
   1801   if (NE(bitmap.axes))
   1802     BWSwitchAxes(old);
   1803 
   1804   if (NE(bitmap.stippled))
   1805     BWSwitchStippled(old);
   1806 
   1807   if (NE(bitmap.proportional))
   1808     resize = True;
   1809 
   1810   if (NE(bitmap.filename) || NE(bitmap.basename)  || NE(bitmap.size))
   1811     BWChangeNotify(old);
   1812 
   1813   if (NE(bitmap.filename)) {
   1814     if (newbw->bitmap.filename) {
   1815       XtFree(oldbw->bitmap.filename);
   1816       newbw->bitmap.filename = XtNewString(newbw->bitmap.filename);
   1817     }
   1818     else
   1819       newbw->bitmap.filename = oldbw->bitmap.filename;
   1820   }
   1821 
   1822   if (NE(bitmap.basename)) {
   1823     if (newbw->bitmap.basename) {
   1824       XtFree(oldbw->bitmap.basename);
   1825       newbw->bitmap.basename = XtNewString(newbw->bitmap.basename);
   1826     }
   1827     else
   1828       newbw->bitmap.basename = oldbw->bitmap.basename;
   1829   }
   1830 
   1831   if (NE(bitmap.size)) {
   1832     Dimension width, height;
   1833 
   1834     if (BWParseSize(newbw->bitmap.size, &width, &height)) {
   1835       ResizeGrid(newbw, width, height);
   1836       resize = True;
   1837     }
   1838   }
   1839 
   1840   if (NE(bitmap.margin) ||
   1841       NE(bitmap.grid_tolerance) ||
   1842       NE(bitmap.squareW) ||
   1843       NE(bitmap.squareH) ||
   1844       NE(core.height) ||
   1845       NE(core.width))
   1846     resize = True;
   1847 
   1848   if (NE(bitmap.hot.x) || NE(bitmap.hot.y))
   1849     BWSetHotSpot(old, newbw->bitmap.hot.x, newbw->bitmap.hot.y);
   1850 
   1851   if (NE(bitmap.foreground_pixel) || NE(core.background_pixel)) {
   1852     XSetForeground(XtDisplay(new),
   1853 		   newbw->bitmap.drawing_gc,
   1854 		   newbw->bitmap.foreground_pixel
   1855 		   ^
   1856 		   newbw->core.background_pixel);
   1857     redisplay = True;
   1858   }
   1859 
   1860   if (NE(bitmap.frame_pixel) || NE(core.background_pixel)) {
   1861     XSetForeground(XtDisplay(new),
   1862 		   newbw->bitmap.frame_gc,
   1863 		   newbw->bitmap.frame_pixel
   1864 		   ^
   1865 		   newbw->core.background_pixel);
   1866     redisplay = True;
   1867   }
   1868 
   1869   if (NE(bitmap.dashes)) {
   1870     XSetStipple(XtDisplay(new),
   1871 		newbw->bitmap.frame_gc,
   1872 		newbw->bitmap.dashes);
   1873     redisplay = True;
   1874   }
   1875 
   1876   if (NE(bitmap.highlight_pixel) || NE(core.background_pixel)) {
   1877     RedrawStippled(newbw);
   1878     XSetForeground(XtDisplay(new),
   1879 		   newbw->bitmap.highlighting_gc,
   1880 		   newbw->bitmap.highlight_pixel
   1881 		   ^
   1882 		   newbw->core.background_pixel);
   1883     RedrawStippled(newbw);
   1884   }
   1885 
   1886   if (NE(bitmap.stipple)) {
   1887     RedrawStippled(newbw);
   1888     XSetStipple(XtDisplay(new),
   1889 		newbw->bitmap.highlighting_gc,
   1890 		newbw->bitmap.stipple);
   1891     RedrawStippled(newbw);
   1892   }
   1893 
   1894   if (resize) Resize((Widget)newbw);
   1895 
   1896     return (redisplay || resize);
   1897 
   1898 #undef NE
   1899 }
   1900 
   1901 Boolean
   1902 BWQueryProportional(Widget w)
   1903 {
   1904     BitmapWidget BW = (BitmapWidget) w;
   1905 
   1906     return (BW->bitmap.proportional);
   1907 }
   1908 
   1909 void
   1910 BWSwitchProportional(Widget w)
   1911 {
   1912     BitmapWidget BW = (BitmapWidget) w;
   1913 
   1914     BW->bitmap.proportional ^= True;
   1915 
   1916     Resize((Widget)BW);
   1917     if (BW->core.visible)
   1918 	XClearArea(XtDisplay(BW), XtWindow(BW),
   1919 		   0, 0,
   1920 		   BW->core.width, BW->core.height,
   1921 		   True);
   1922 }
   1923 
   1924 #if 0
   1925 void
   1926 BWProportional(Widget w, Boolean _switch)
   1927 {
   1928     BitmapWidget BW = (BitmapWidget) w;
   1929 
   1930     if (BW->bitmap.proportional != _switch)
   1931 	BWSwitchProportional(w);
   1932 }
   1933 #endif
   1934 
   1935 void
   1936 BWTPaste(Widget w, XEvent *event, String *params, Cardinal *num_params)
   1937 {
   1938     BitmapWidget BW = (BitmapWidget) w;
   1939 
   1940     BWRequestSelection(w, event->xbutton.time, TRUE);
   1941 
   1942     if (!BWQueryStored(w))
   1943 	return;
   1944 
   1945     BWEngageRequest(w, RestoreRequest, False,
   1946 		    (char *)&(event->xbutton.state), sizeof(int));
   1947 
   1948     OnePointHandler(w,
   1949 	       (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status,
   1950 	       event, NULL);
   1951 }
   1952 
   1953 void
   1954 BWTMark(Widget w, XEvent *event, String *params, Cardinal *num_params)
   1955 {
   1956     BitmapWidget BW = (BitmapWidget) w;
   1957 
   1958     BWEngageRequest(w, MarkRequest, False,
   1959 		    (char *)&(event->xbutton.state), sizeof(int));
   1960     TwoPointsHandler(w,
   1961             (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status,
   1962 	     event, NULL);
   1963 
   1964 }
   1965 
   1966 void
   1967 BWTMarkAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
   1968 {
   1969     BWMarkAll(w);
   1970 
   1971     BWGrabSelection(w, event->xkey.time);
   1972 }
   1973 
   1974 void
   1975 BWTUnmark(Widget w, XEvent *event, String *params, Cardinal *num_params)
   1976 {
   1977     BWUnmark(w);
   1978 }
   1979 
   1980 /*****************************************************************************/
   1981