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