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