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