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