Bitmap.c revision 2b32c8f7
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/Xmu/SysUtil.h>
39eaef79e5Smrg#include <X11/Xatom.h>
40eaef79e5Smrg#include <X11/Xfuncs.h>
41eaef79e5Smrg#include <X11/Xos.h>
42eaef79e5Smrg#include "BitmapP.h"
43eaef79e5Smrg#include "Bitmap.h"
44eaef79e5Smrg
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
238eaef79e5Smrgstatic 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},
272eaef79e5Smrg{LineRequest, sizeof(BWStatus),
273eaef79e5Smrg     TwoPointsEngage, (XtPointer) BWDrawLine,
274eaef79e5Smrg     TwoPointsTerminate, (XtPointer) BWDrawLine,
275eaef79e5Smrg     NULL, (XtPointer) NULL},
276eaef79e5Smrg{RectangleRequest, sizeof(BWStatus),
277eaef79e5Smrg     TwoPointsEngage, (XtPointer) BWDrawRectangle,
278eaef79e5Smrg     TwoPointsTerminate, (XtPointer) BWDrawRectangle,
279eaef79e5Smrg     NULL, (XtPointer) NULL},
280eaef79e5Smrg{FilledRectangleRequest, sizeof(BWStatus),
281eaef79e5Smrg     TwoPointsEngage, (XtPointer) BWDrawRectangle,
282eaef79e5Smrg     TwoPointsTerminate, (XtPointer) BWDrawFilledRectangle,
283eaef79e5Smrg     NULL, (XtPointer) NULL},
284eaef79e5Smrg{CircleRequest, sizeof(BWStatus),
285eaef79e5Smrg     TwoPointsEngage, (XtPointer) BWDrawCircle,
286eaef79e5Smrg     TwoPointsTerminate, (XtPointer) BWDrawCircle,
287eaef79e5Smrg     NULL, (XtPointer) NULL},
288eaef79e5Smrg{FilledCircleRequest, sizeof(BWStatus),
289eaef79e5Smrg     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);
307eaef79e5Smrgstatic 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);
312eaef79e5Smrgstatic 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);
316eaef79e5Smrg
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  },
352eaef79e5Smrg  {
353eaef79e5Smrg    /* empty			*/	XtInheritChangeSensitive,
354eaef79e5Smrg  },
355eaef79e5Smrg  {
356eaef79e5Smrg    /* targets                  */      targets,
357eaef79e5Smrg    /* num_trets                */      XtNumber(targets),
358eaef79e5Smrg    /* requests                 */      requests,
359eaef79e5Smrg    /* num_requests             */      XtNumber(requests),
360eaef79e5Smrg  }
361eaef79e5Smrg};
362eaef79e5Smrg
363eaef79e5SmrgWidgetClass bitmapWidgetClass = (WidgetClass) &bitmapClassRec;
364eaef79e5Smrg
365eaef79e5Smrg/* ARGSUSED */
366eaef79e5Smrg
367eaef79e5Smrgvoid
368eaef79e5SmrgBWDebug(Widget w, XEvent *event, String *params, Cardinal *num_params)
369eaef79e5Smrg{
370eaef79e5Smrg    DEBUG ^= True;
371eaef79e5Smrg}
372eaef79e5Smrg
373eaef79e5SmrgPixmap
374eaef79e5SmrgBWGetPixmap(Widget w)
375eaef79e5Smrg{
376eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
377eaef79e5Smrg
378eaef79e5Smrg    return GetPixmap(BW, BW->bitmap.zoom.image);
379eaef79e5Smrg}
380eaef79e5Smrg
381eaef79e5SmrgPixmap
382eaef79e5SmrgBWGetUnzoomedPixmap(Widget w)
383eaef79e5Smrg{
384eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
385eaef79e5Smrg    GC gc;
386eaef79e5Smrg    Pixmap pix;
387eaef79e5Smrg
388eaef79e5Smrg    if (BW->bitmap.zooming) {
389eaef79e5Smrg	pix = XCreatePixmap(XtDisplay(w), XtWindow(w),
390eaef79e5Smrg			    BW->bitmap.zoom.image->width,
391eaef79e5Smrg			    BW->bitmap.zoom.image->height, 1);
392eaef79e5Smrg	if (!(gc = XCreateGC(XtDisplay(w), pix,
393eaef79e5Smrg			     (unsigned long) 0, (XGCValues *) 0)))
394eaef79e5Smrg	    return (Pixmap) None;
395eaef79e5Smrg
396eaef79e5Smrg	XPutImage(XtDisplay(w), pix, gc,
397eaef79e5Smrg		  BW->bitmap.zoom.image,
398eaef79e5Smrg		  0, 0, 0, 0,
399eaef79e5Smrg		  BW->bitmap.zoom.image->width,
400eaef79e5Smrg		  BW->bitmap.zoom.image->height);
401eaef79e5Smrg	XPutImage(XtDisplay(w), pix, gc,
402eaef79e5Smrg		  BW->bitmap.image,
403eaef79e5Smrg		  0, 0,
404eaef79e5Smrg		  BW->bitmap.zoom.at_x,
405eaef79e5Smrg		  BW->bitmap.zoom.at_y,
406eaef79e5Smrg		  BW->bitmap.image->width,
407eaef79e5Smrg		  BW->bitmap.image->height);
408eaef79e5Smrg    }
409eaef79e5Smrg    else {
410eaef79e5Smrg	pix = XCreatePixmap(XtDisplay(w), XtWindow(w),
411eaef79e5Smrg			    BW->bitmap.image->width,
412eaef79e5Smrg			    BW->bitmap.image->height, 1);
413eaef79e5Smrg	if (! (gc = XCreateGC(XtDisplay(w), pix,
414eaef79e5Smrg			      (unsigned long) 0, (XGCValues *) 0)))
415eaef79e5Smrg	    return (Pixmap) None;
416eaef79e5Smrg
417eaef79e5Smrg	XPutImage(XtDisplay(w), pix, gc,
418eaef79e5Smrg		  BW->bitmap.image,
419eaef79e5Smrg		  0, 0, 0, 0,
420eaef79e5Smrg		  BW->bitmap.image->width,
421eaef79e5Smrg		  BW->bitmap.image->height);
422eaef79e5Smrg    }
423eaef79e5Smrg    XFreeGC(XtDisplay(w), gc);
424eaef79e5Smrg    return(pix);
425eaef79e5Smrg}
426eaef79e5Smrg
427eaef79e5Smrg
428eaef79e5SmrgXImage *
429eaef79e5SmrgGetImage(BitmapWidget BW, Pixmap pixmap)
430eaef79e5Smrg{
431eaef79e5Smrg    Window root;
432eaef79e5Smrg    int x, y;
433eaef79e5Smrg    unsigned int width, height, border_width, depth;
434eaef79e5Smrg    XImage *source, *image;
435eaef79e5Smrg
436eaef79e5Smrg    XGetGeometry(XtDisplay(BW), pixmap, &root, &x, &y,
437eaef79e5Smrg		 &width, &height, &border_width, &depth);
438eaef79e5Smrg
439eaef79e5Smrg    source = XGetImage(XtDisplay(BW), pixmap, x, y, width, height,
440eaef79e5Smrg		     1, XYPixmap);
441eaef79e5Smrg
442eaef79e5Smrg    image = ConvertToBitmapImage(BW, source);
443eaef79e5Smrg
444eaef79e5Smrg    return image;
445eaef79e5Smrg}
446eaef79e5Smrg
447eaef79e5SmrgXImage *
448eaef79e5SmrgCreateBitmapImage(BitmapWidget BW, char *data,
449eaef79e5Smrg		  Dimension width, Dimension height)
450eaef79e5Smrg{
451eaef79e5Smrg    XImage *image = XCreateImage(XtDisplay(BW),
452eaef79e5Smrg				 DefaultVisual(XtDisplay(BW),
453eaef79e5Smrg					       DefaultScreen(XtDisplay(BW))),
454eaef79e5Smrg				 1, XYBitmap, 0,
455eaef79e5Smrg				 data, width, height,
456eaef79e5Smrg				 8, ((int)width + 7) / 8);
457eaef79e5Smrg
458eaef79e5Smrg    image->height = height;
459eaef79e5Smrg    image->width = width;
460eaef79e5Smrg    image->depth = 1;
461eaef79e5Smrg    image->xoffset = 0;
462eaef79e5Smrg    image->format = XYBitmap;
463eaef79e5Smrg    image->data = (char *)data;
464eaef79e5Smrg    image->byte_order = LSBFirst;
465eaef79e5Smrg    image->bitmap_unit = 8;
466eaef79e5Smrg    image->bitmap_bit_order = LSBFirst;
467eaef79e5Smrg    image->bitmap_pad = 8;
468eaef79e5Smrg    image->bytes_per_line = ((int)width + 7) / 8;
469eaef79e5Smrg
470eaef79e5Smrg    return image;
471eaef79e5Smrg}
472eaef79e5Smrg
473eaef79e5Smrgvoid
474eaef79e5SmrgDestroyBitmapImage(XImage **image)
475eaef79e5Smrg{
476eaef79e5Smrg    /*XDestroyImage(*image);*/
477eaef79e5Smrg    if (image) {
478eaef79e5Smrg	if (*image) {
479eaef79e5Smrg	    if ((*image)->data)
480eaef79e5Smrg		XtFree((*image)->data);
481eaef79e5Smrg	    XtFree((char *)*image);
482eaef79e5Smrg	}
483eaef79e5Smrg	*image = NULL;
484eaef79e5Smrg    }
485eaef79e5Smrg}
486eaef79e5Smrg
487eaef79e5Smrg#if 0
488eaef79e5SmrgXImage *
489eaef79e5SmrgBWGetImage(Widget w, XEvent *event, String *params, Cardinal *num_params)
490eaef79e5Smrg{
491eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
492eaef79e5Smrg
493eaef79e5Smrg    return BW->bitmap.image;
494eaef79e5Smrg}
495eaef79e5Smrg#endif
496eaef79e5Smrg
497eaef79e5Smrgvoid
498eaef79e5SmrgBWChangeNotify(Widget w)
499eaef79e5Smrg{
500eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
501eaef79e5Smrg
502eaef79e5Smrg    if (BW->bitmap.notify)
503eaef79e5Smrg	(*BW->bitmap.notify)(w, NULL, NULL, NULL);
504eaef79e5Smrg}
505eaef79e5Smrg
506eaef79e5Smrgvoid
507eaef79e5SmrgBWNotify(Widget w, XtActionProc proc)
508eaef79e5Smrg{
509eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
510eaef79e5Smrg
511eaef79e5Smrg    BW->bitmap.notify = proc;
512eaef79e5Smrg}
513eaef79e5Smrg
514eaef79e5Smrgvoid
515eaef79e5SmrgBWSetChanged(Widget w)
516eaef79e5Smrg{
517eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
518eaef79e5Smrg
519eaef79e5Smrg    BW->bitmap.changed = True;
520eaef79e5Smrg}
521eaef79e5Smrg
522eaef79e5SmrgBoolean
523eaef79e5SmrgBWQueryChanged(Widget w)
524eaef79e5Smrg{
525eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
526eaef79e5Smrg
527eaef79e5Smrg    return BW->bitmap.changed;
528eaef79e5Smrg}
529eaef79e5Smrg
530eaef79e5Smrgvoid
531eaef79e5SmrgBWClearChanged(Widget w)
532eaef79e5Smrg{
533eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
534eaef79e5Smrg
535eaef79e5Smrg    BW->bitmap.changed = False;
536eaef79e5Smrg}
537eaef79e5Smrg
538eaef79e5SmrgBoolean
539eaef79e5SmrgBWQueryStored(Widget w)
540eaef79e5Smrg{
541eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
542eaef79e5Smrg
543eaef79e5Smrg    return (BW->bitmap.storage != NULL);
544eaef79e5Smrg}
545eaef79e5Smrg
546eaef79e5SmrgBoolean
547eaef79e5SmrgBWQueryStippled(Widget w)
548eaef79e5Smrg{
549eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
550eaef79e5Smrg
551eaef79e5Smrg    return BW->bitmap.stippled;
552eaef79e5Smrg}
553eaef79e5Smrg
554eaef79e5Smrgstatic void
555eaef79e5SmrgRedrawStippled(BitmapWidget BW)
556eaef79e5Smrg{
557eaef79e5Smrg  XExposeEvent event;
558eaef79e5Smrg
559eaef79e5Smrg  event.type = Expose;
560eaef79e5Smrg  event.display = XtDisplay((Widget)BW);
561eaef79e5Smrg  event.window = XtWindow((Widget)BW);
562eaef79e5Smrg  event.x = 0;
563eaef79e5Smrg  event.y = 0;
564eaef79e5Smrg  event.width = BW->core.width;
565eaef79e5Smrg  event.height = BW->core.height;
566eaef79e5Smrg  event.count = 0;
567eaef79e5Smrg
568eaef79e5Smrg  BWRedrawMark((Widget)BW);
569eaef79e5Smrg
570eaef79e5Smrg  BW->bitmap.stipple_change_expose_event = True;
571eaef79e5Smrg
572eaef79e5Smrg  XtDispatchEvent((XEvent *)&event);
573eaef79e5Smrg
574eaef79e5Smrg  BW->bitmap.stipple_change_expose_event = False;
575eaef79e5Smrg}
576eaef79e5Smrg
577eaef79e5Smrgvoid
578eaef79e5SmrgBWSwitchStippled(Widget w)
579eaef79e5Smrg{
580eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
581eaef79e5Smrg
582eaef79e5Smrg    RedrawStippled(BW);
583eaef79e5Smrg
584eaef79e5Smrg    BW->bitmap.stippled ^= True;
585eaef79e5Smrg    XSetFillStyle(XtDisplay(BW), BW->bitmap.highlighting_gc,
586eaef79e5Smrg		  (BW->bitmap.stippled ? FillStippled : FillSolid));
587eaef79e5Smrg
588eaef79e5Smrg    RedrawStippled(BW);
589eaef79e5Smrg}
590eaef79e5Smrg
591eaef79e5Smrgvoid
592eaef79e5SmrgBWSelect(Widget w, Position from_x, Position from_y,
593eaef79e5Smrg	 Position to_x, Position to_y, Time btime)
594eaef79e5Smrg{
595eaef79e5Smrg    BWMark(w, from_x, from_y, to_x, to_y);
596eaef79e5Smrg
597eaef79e5Smrg    BWGrabSelection(w, btime);
598eaef79e5Smrg}
599eaef79e5Smrg
600eaef79e5SmrgBoolean
601eaef79e5SmrgBWQueryAxes(Widget w)
602eaef79e5Smrg{
603eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
604eaef79e5Smrg
605eaef79e5Smrg    return BW->bitmap.axes;
606eaef79e5Smrg}
607eaef79e5Smrg
608eaef79e5Smrgvoid
609eaef79e5SmrgBWSwitchAxes(Widget w)
610eaef79e5Smrg{
611eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
612eaef79e5Smrg
613eaef79e5Smrg    BW->bitmap.axes ^= True;
614eaef79e5Smrg    BWHighlightAxes(w);
615eaef79e5Smrg}
616eaef79e5Smrg
617eaef79e5Smrgvoid
618eaef79e5SmrgBWAxes(Widget w, Boolean _switch)
619eaef79e5Smrg{
620eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
621eaef79e5Smrg
622eaef79e5Smrg    if (BW->bitmap.axes != _switch)
623eaef79e5Smrg	BWSwitchAxes(w);
624eaef79e5Smrg}
625eaef79e5Smrg
626eaef79e5Smrgvoid
627eaef79e5SmrgBWRedrawAxes(Widget w)
628eaef79e5Smrg{
629eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
630eaef79e5Smrg
631eaef79e5Smrg    if (BW->bitmap.axes)
632eaef79e5Smrg	BWHighlightAxes(w);
633eaef79e5Smrg}
634eaef79e5Smrg
635eaef79e5Smrg#if 0
636eaef79e5Smrgvoid
637eaef79e5SmrgBWPutImage(BitmapWidget w, Display *display, Drawable drawable, GC gc,
638eaef79e5Smrg	   Position x, Position y)
639eaef79e5Smrg{
640eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
641eaef79e5Smrg
642eaef79e5Smrg  XPutImage(display, drawable, gc, BW->bitmap.image,
643eaef79e5Smrg	    0, 0, x, y, BW->bitmap.image->width, BW->bitmap.image->height);
644eaef79e5Smrg}
645eaef79e5Smrg#endif
646eaef79e5Smrg
647eaef79e5Smrgstatic String
648eaef79e5SmrgStripFilename(String filename)
649eaef79e5Smrg{
650eaef79e5Smrg    char *begin = strrchr(filename, '/');
651eaef79e5Smrg    char *end, *result;
652eaef79e5Smrg    int length;
653eaef79e5Smrg
654eaef79e5Smrg    if (filename) {
655eaef79e5Smrg	begin = (begin ? begin + 1 : filename);
656eaef79e5Smrg	end = strchr(begin, '.'); /* change to strrchr to allow longer names */
657eaef79e5Smrg	length = (end ? (end - begin) : strlen (begin));
658eaef79e5Smrg	result = (char *) XtMalloc (length + 1);
659eaef79e5Smrg	strncpy (result, begin, length);
660eaef79e5Smrg	result [length] = '\0';
661eaef79e5Smrg	return (result);
662eaef79e5Smrg    }
663eaef79e5Smrg    else
664eaef79e5Smrg	return (NULL);
665eaef79e5Smrg}
666eaef79e5Smrg
667eaef79e5Smrgstatic int
668eaef79e5SmrgXmuWriteBitmapDataToFile(String filename, String basename,
669eaef79e5Smrg			 int width, int height, char *datap,
670eaef79e5Smrg			 int x_hot, int y_hot)
671eaef79e5Smrg{
672eaef79e5Smrg    FILE *file;
673eaef79e5Smrg    int i, data_length;
674eaef79e5Smrg
675eaef79e5Smrg    data_length = Length(width, height);
676eaef79e5Smrg
677eaef79e5Smrg    if(!filename || !strcmp(filename, "") || !strcmp(filename, "-")) {
678eaef79e5Smrg	file = stdout;
679eaef79e5Smrg	filename = "dummy";
680eaef79e5Smrg	}
681eaef79e5Smrg    else
682eaef79e5Smrg    	file = fopen(filename, "w+");
683eaef79e5Smrg
684eaef79e5Smrg    if (!basename || !strcmp(basename, "") || !strcmp(basename, "-"))
685eaef79e5Smrg	basename = StripFilename(filename);
686eaef79e5Smrg
687eaef79e5Smrg    if (file) {
688eaef79e5Smrg	fprintf(file, "#define %s_width %d\n", basename, width);
689eaef79e5Smrg	fprintf(file, "#define %s_height %d\n", basename, height);
690eaef79e5Smrg	if (QuerySet(x_hot, y_hot)) {
691eaef79e5Smrg	    fprintf(file, "#define %s_x_hot %d\n", basename, x_hot);
692eaef79e5Smrg	    fprintf(file, "#define %s_y_hot %d\n", basename, y_hot);
693eaef79e5Smrg	}
694eaef79e5Smrg	fprintf(file, "static unsigned char %s_bits[] = {\n   0x%02x",
695eaef79e5Smrg		basename, (unsigned char) datap[0]);
696eaef79e5Smrg	for(i = 1; i < data_length; i++) {
697eaef79e5Smrg	    fprintf(file, ",");
698eaef79e5Smrg	    fprintf(file, (i % 12) ? " " : "\n   ");
699eaef79e5Smrg	    fprintf(file, "0x%02x", (unsigned char) datap[i]);
700eaef79e5Smrg	}
701eaef79e5Smrg	fprintf(file, "};\n");
702eaef79e5Smrg
703eaef79e5Smrg	if (file != stdout)
704eaef79e5Smrg	    fclose(file);
705eaef79e5Smrg
706eaef79e5Smrg	return BitmapSuccess;
707eaef79e5Smrg    }
708eaef79e5Smrg
709eaef79e5Smrg    return 1;
710eaef79e5Smrg}
711eaef79e5Smrg
712eaef79e5Smrg/*
713eaef79e5Smrg *
714eaef79e5Smrg */
715eaef79e5Smrg
716eaef79e5Smrg				/* ARGSUSED */
717eaef79e5Smrgstatic void
718eaef79e5SmrgCvtStringToButtonFunction(XrmValuePtr args, /* not used */
719eaef79e5Smrg			  Cardinal *num_args, /* not used */
720eaef79e5Smrg			  XrmValuePtr from_val,
721eaef79e5Smrg			  XrmValuePtr to_val)
722eaef79e5Smrg{
723eaef79e5Smrg  static int button_function;
724eaef79e5Smrg  char lower_name[80];
725eaef79e5Smrg
726eaef79e5Smrg  XmuCopyISOLatin1Lowered (lower_name, (char*)from_val->addr);
727eaef79e5Smrg
728eaef79e5Smrg  if (!strcmp(lower_name, XtClear)) {
729eaef79e5Smrg    button_function = Clear;
730eaef79e5Smrg    to_val->addr = (XPointer) &button_function;
731eaef79e5Smrg    to_val->size = sizeof(button_function);
732eaef79e5Smrg    return;
733eaef79e5Smrg  }
734eaef79e5Smrg
735eaef79e5Smrg  if (!strcmp(lower_name, XtSet)) {
736eaef79e5Smrg    button_function = Set;
737eaef79e5Smrg    to_val->addr = (XPointer) &button_function;
738eaef79e5Smrg    to_val->size = sizeof(button_function);
739eaef79e5Smrg    return;
740eaef79e5Smrg  }
741eaef79e5Smrg
742eaef79e5Smrg  if (!strcmp(lower_name, XtInvert)) {
743eaef79e5Smrg    button_function = Invert;
744eaef79e5Smrg    to_val->addr = (XPointer) &button_function;
745eaef79e5Smrg    to_val->size = sizeof(button_function);
746eaef79e5Smrg    return;
747eaef79e5Smrg  }
748eaef79e5Smrg
749eaef79e5Smrg  XtStringConversionWarning(from_val->addr, XtRButtonFunction);
750eaef79e5Smrg  button_function = Clear;
751eaef79e5Smrg  to_val->addr = (XPointer) &button_function;
752eaef79e5Smrg  to_val->size = sizeof(button_function);
753eaef79e5Smrg
754eaef79e5Smrg}
755eaef79e5Smrg
756eaef79e5Smrgstatic void
757eaef79e5SmrgClassInitialize(void)
758eaef79e5Smrg{
759eaef79e5Smrg  char *tm_table = XtMalloc(strlen(translations1) + strlen(translations2) + 1);
760eaef79e5Smrg  strcpy(tm_table, translations1);
761eaef79e5Smrg  strcat(tm_table, translations2);
762eaef79e5Smrg  bitmapClassRec.core_class.tm_table = tm_table;
763eaef79e5Smrg
764eaef79e5Smrg  XawInitializeWidgetSet();
765eaef79e5Smrg  XtAddConverter(XtRString, XtRButtonFunction, CvtStringToButtonFunction,
766eaef79e5Smrg		 NULL, 0);
767eaef79e5Smrg  DEBUG = False;
768eaef79e5Smrg}
769eaef79e5Smrg
770eaef79e5Smrgstatic void
771eaef79e5SmrgSetSizeFromSizeResource(BitmapWidget bw)
772eaef79e5Smrg{
773eaef79e5Smrg  if (BWParseSize(bw->bitmap.size,
774eaef79e5Smrg		  &bw->bitmap.width,
775eaef79e5Smrg		  &bw->bitmap.height)
776eaef79e5Smrg      ==
777eaef79e5Smrg      False) {
778eaef79e5Smrg    bw->bitmap.width = FallbackBitmapWidth;
779eaef79e5Smrg    bw->bitmap.height = FallbackBitmapHeight;
780eaef79e5Smrg    XtWarning("Cannot parse the size resource.  BitmapWidget");
781eaef79e5Smrg  }
782eaef79e5Smrg}
783eaef79e5Smrg
784eaef79e5Smrg
785eaef79e5Smrg/* ARGSUSED */
786eaef79e5Smrgstatic void
787eaef79e5SmrgInitialize(Widget wrequest, Widget wnew, ArgList argv, Cardinal *argc)
788eaef79e5Smrg{
789eaef79e5Smrg    BitmapWidget new = (BitmapWidget) wnew;
790eaef79e5Smrg
791eaef79e5Smrg    XGCValues  values;
792eaef79e5Smrg    XtGCMask   mask;
793eaef79e5Smrg    char *image_data, *buffer_data;
794eaef79e5Smrg
795eaef79e5Smrg    new->bitmap.stipple_change_expose_event = False;
796eaef79e5Smrg    new->bitmap.notify = NULL;
797eaef79e5Smrg    new->bitmap.cardinal = 0;
798eaef79e5Smrg    new->bitmap.current = 0;
799eaef79e5Smrg    new->bitmap.fold = False;
800eaef79e5Smrg    new->bitmap.changed = False;
801eaef79e5Smrg    new->bitmap.zooming = False;
802eaef79e5Smrg    new->bitmap.selection.own = False;
803eaef79e5Smrg    new->bitmap.selection.limbo = False;
804eaef79e5Smrg
805eaef79e5Smrg    new->bitmap.request_stack = (BWRequestStack *)
806eaef79e5Smrg	XtMalloc(sizeof(BWRequestStack));
807eaef79e5Smrg
808eaef79e5Smrg    new->bitmap.request_stack[0].request = NULL;
809eaef79e5Smrg    new->bitmap.request_stack[0].call_data = NULL;
810eaef79e5Smrg    new->bitmap.request_stack[0].trap = False;
811eaef79e5Smrg
812eaef79e5Smrg    SetSizeFromSizeResource(new);
813eaef79e5Smrg
814eaef79e5Smrg    new->core.width = new->bitmap.width * new->bitmap.squareW +
815eaef79e5Smrg	2 * new->bitmap.margin;
816eaef79e5Smrg    new->core.height = new->bitmap.height * new->bitmap.squareH +
817eaef79e5Smrg	2 * new->bitmap.margin;
818eaef79e5Smrg
819eaef79e5Smrg    new->bitmap.hot.x = new->bitmap.hot.y = NotSet;
820eaef79e5Smrg    new->bitmap.buffer_hot.x = new->bitmap.buffer_hot.y = NotSet;
821eaef79e5Smrg
822eaef79e5Smrg    new->bitmap.mark.from_x = new->bitmap.mark.from_y = NotSet;
823eaef79e5Smrg    new->bitmap.mark.to_x = new->bitmap.mark.to_y = NotSet;
824eaef79e5Smrg    new->bitmap.buffer_mark.from_x = new->bitmap.buffer_mark.from_y = NotSet;
825eaef79e5Smrg    new->bitmap.buffer_mark.to_x = new->bitmap.buffer_mark.to_y = NotSet;
826eaef79e5Smrg
827eaef79e5Smrg    values.foreground = new->bitmap.foreground_pixel;
828eaef79e5Smrg    values.background = new->core.background_pixel;
829eaef79e5Smrg    values.foreground ^= values.background;
830eaef79e5Smrg    values.function = GXxor;
831eaef79e5Smrg    mask = GCForeground | GCBackground | GCFunction;
832eaef79e5Smrg    new->bitmap.drawing_gc = XCreateGC(XtDisplay(new),
833eaef79e5Smrg				       RootWindow(XtDisplay(new),
834eaef79e5Smrg				       DefaultScreen(XtDisplay(new))),
835eaef79e5Smrg				       mask, &values);
836eaef79e5Smrg
837eaef79e5Smrg    values.foreground = new->bitmap.highlight_pixel;
838eaef79e5Smrg    values.background = new->core.background_pixel;
839eaef79e5Smrg    values.foreground ^= values.background;
840eaef79e5Smrg    values.function = GXxor;
841eaef79e5Smrg    mask = GCForeground | GCBackground | GCFunction;
842eaef79e5Smrg    if (new->bitmap.stipple != XtUnspecifiedPixmap)
843eaef79e5Smrg    {
844eaef79e5Smrg	values.stipple = new->bitmap.stipple;
845eaef79e5Smrg	mask |= GCStipple | GCFillStyle;
846eaef79e5Smrg    }
847eaef79e5Smrg    values.fill_style = (new->bitmap.stippled ? FillStippled : FillSolid);
848eaef79e5Smrg
849eaef79e5Smrg    new->bitmap.highlighting_gc = XCreateGC(XtDisplay(new),
850eaef79e5Smrg					    RootWindow(XtDisplay(new),
851eaef79e5Smrg					       DefaultScreen(XtDisplay(new))),
852eaef79e5Smrg					    mask, &values);
853eaef79e5Smrg
854eaef79e5Smrg
855eaef79e5Smrg    values.foreground = new->bitmap.frame_pixel;
856eaef79e5Smrg    values.background = new->core.background_pixel;
857eaef79e5Smrg    values.foreground ^= values.background;
858eaef79e5Smrg    mask = GCForeground | GCBackground | GCFunction;
859eaef79e5Smrg    if (new->bitmap.dashes != XtUnspecifiedPixmap)
860eaef79e5Smrg    {
861eaef79e5Smrg	values.stipple = new->bitmap.dashes;
862eaef79e5Smrg	mask |= GCStipple | GCFillStyle;
863eaef79e5Smrg    }
864eaef79e5Smrg    values.fill_style = (new->bitmap.dashed ? FillStippled : FillSolid);
865eaef79e5Smrg
866eaef79e5Smrg    new->bitmap.frame_gc = XCreateGC(XtDisplay(new),
867eaef79e5Smrg				     RootWindow(XtDisplay(new),
868eaef79e5Smrg						DefaultScreen(XtDisplay(new))),
869eaef79e5Smrg				     mask, &values);
870eaef79e5Smrg
871eaef79e5Smrg    values.foreground = new->bitmap.highlight_pixel;
872eaef79e5Smrg    values.background = new->core.background_pixel;
873eaef79e5Smrg    values.foreground ^= values.background;
874eaef79e5Smrg    mask = GCForeground | GCBackground | GCFunction;
875eaef79e5Smrg    new->bitmap.axes_gc = XCreateGC(XtDisplay(new),
876eaef79e5Smrg				     RootWindow(XtDisplay(new),
877eaef79e5Smrg						DefaultScreen(XtDisplay(new))),
878eaef79e5Smrg				     mask, &values);
879eaef79e5Smrg
880eaef79e5Smrg    image_data = CreateCleanData(Length(new->bitmap.width,
881eaef79e5Smrg					new->bitmap.height));
882eaef79e5Smrg    buffer_data = CreateCleanData(Length(new->bitmap.width,
883eaef79e5Smrg					 new->bitmap.height));
884eaef79e5Smrg
885eaef79e5Smrg    new->bitmap.storage = NULL;
886eaef79e5Smrg
887eaef79e5Smrg    new->bitmap.image = CreateBitmapImage(new,
888eaef79e5Smrg					  image_data,
889eaef79e5Smrg					  new->bitmap.width,
890eaef79e5Smrg					  new->bitmap.height);
891eaef79e5Smrg    new->bitmap.buffer = CreateBitmapImage(new,
892eaef79e5Smrg					   buffer_data,
893eaef79e5Smrg					   new->bitmap.width,
894eaef79e5Smrg					   new->bitmap.height);
895eaef79e5Smrg
896eaef79e5Smrg    /* Read file */
897eaef79e5Smrg    {
898eaef79e5Smrg	int status;
899eaef79e5Smrg	XImage *image, *buffer;
900eaef79e5Smrg	unsigned char *image_data;
901eaef79e5Smrg	char *buffer_data;
902eaef79e5Smrg	unsigned int width, height;
903eaef79e5Smrg	int x_hot, y_hot;
904eaef79e5Smrg
905eaef79e5Smrg	status = XmuReadBitmapDataFromFile(new->bitmap.filename,
906eaef79e5Smrg					   &width, &height, &image_data,
907eaef79e5Smrg					   &x_hot, &y_hot);
908eaef79e5Smrg	if (status == BitmapSuccess) {
909eaef79e5Smrg
910eaef79e5Smrg	    buffer_data = CreateCleanData(Length(width, height));
911eaef79e5Smrg
912eaef79e5Smrg	    image = CreateBitmapImage(new, (char *)image_data, width, height);
913eaef79e5Smrg	    buffer = CreateBitmapImage(new, buffer_data, width, height);
914eaef79e5Smrg
915eaef79e5Smrg	    TransferImageData(new->bitmap.image, buffer);
916eaef79e5Smrg
917eaef79e5Smrg	    DestroyBitmapImage(&new->bitmap.image);
918eaef79e5Smrg	    DestroyBitmapImage(&new->bitmap.buffer);
919eaef79e5Smrg
920eaef79e5Smrg	    new->bitmap.image = image;
921eaef79e5Smrg	    new->bitmap.buffer = buffer;
922eaef79e5Smrg	    new->bitmap.width = width;
923eaef79e5Smrg	    new->bitmap.height = height;
924eaef79e5Smrg
925eaef79e5Smrg	    new->bitmap.hot.x = x_hot;
926eaef79e5Smrg	    new->bitmap.hot.y = y_hot;
927eaef79e5Smrg
928eaef79e5Smrg	    new->bitmap.changed = False;
929eaef79e5Smrg	    new->bitmap.zooming = False;
930eaef79e5Smrg	}
931eaef79e5Smrg
932eaef79e5Smrg	new->bitmap.filename = XtNewString(new->bitmap.filename);
933eaef79e5Smrg
934eaef79e5Smrg	if (!strcmp(new->bitmap.basename, "")) {
935eaef79e5Smrg	    new->bitmap.basename = StripFilename(new->bitmap.filename);
936eaef79e5Smrg	}
937eaef79e5Smrg	else
938eaef79e5Smrg	  new->bitmap.basename = XtNewString(new->bitmap.basename);
939eaef79e5Smrg    }
940eaef79e5Smrg
941eaef79e5Smrg    Resize((Widget)new);
942eaef79e5Smrg}
943eaef79e5Smrg
944eaef79e5Smrg
945eaef79e5Smrg/* returns False if the format is wrong */
946eaef79e5SmrgBoolean
947eaef79e5SmrgBWParseSize(String size, Dimension *width, Dimension *height)
948eaef79e5Smrg{
949eaef79e5Smrg  int x, y;
950eaef79e5Smrg  unsigned int w, h;
951eaef79e5Smrg  int status;
952eaef79e5Smrg
953eaef79e5Smrg  status = XParseGeometry(size, &x, &y, &w, &h);
954eaef79e5Smrg
955eaef79e5Smrg  if (status & (WidthValue | HeightValue)) {
956eaef79e5Smrg    *width = (Dimension) w;
957eaef79e5Smrg    *height = (Dimension) h;
958eaef79e5Smrg    return True;
959eaef79e5Smrg  }
960eaef79e5Smrg  else return False;
961eaef79e5Smrg
962eaef79e5Smrg}
963eaef79e5Smrg
964eaef79e5Smrg
965eaef79e5SmrgBoolean
966eaef79e5SmrgBWQueryMarked(Widget w)
967eaef79e5Smrg{
968eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
969eaef79e5Smrg
970eaef79e5Smrg    return QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y);
971eaef79e5Smrg}
972eaef79e5Smrg
973eaef79e5Smrgstatic void
974eaef79e5SmrgFixMark(BitmapWidget BW)
975eaef79e5Smrg{
976eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
977eaef79e5Smrg	BW->bitmap.mark.from_x = min(BW->bitmap.mark.from_x,
978eaef79e5Smrg				     BW->bitmap.image->width);
979eaef79e5Smrg	BW->bitmap.mark.from_y = min(BW->bitmap.mark.from_y,
980eaef79e5Smrg				     BW->bitmap.image->height);
981eaef79e5Smrg	BW->bitmap.mark.to_x = min(BW->bitmap.mark.to_x,
982eaef79e5Smrg				   BW->bitmap.image->width);
983eaef79e5Smrg	BW->bitmap.mark.to_y = min(BW->bitmap.mark.to_y,
984eaef79e5Smrg				   BW->bitmap.image->height);
985eaef79e5Smrg
986eaef79e5Smrg	if((BW->bitmap.mark.from_x == BW->bitmap.mark.from_y) &&
987eaef79e5Smrg	   (BW->bitmap.mark.to_x   == BW->bitmap.mark.to_y))
988eaef79e5Smrg	    BW->bitmap.mark.from_x =
989eaef79e5Smrg		BW->bitmap.mark.from_y =
990eaef79e5Smrg		    BW->bitmap.mark.to_x =
991eaef79e5Smrg			BW->bitmap.mark.to_y = NotSet;
992eaef79e5Smrg    }
993eaef79e5Smrg}
994eaef79e5Smrg
995eaef79e5Smrg/* ARGSUSED */
996eaef79e5Smrgint
997eaef79e5SmrgBWStoreFile(Widget w, String filename, String *basename)
998eaef79e5Smrg{
999eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1000eaef79e5Smrg    int status;
1001eaef79e5Smrg    unsigned char *storage_data;
1002eaef79e5Smrg    unsigned int width, height;
1003eaef79e5Smrg    int x_hot, y_hot;
1004eaef79e5Smrg
1005eaef79e5Smrg    status = XmuReadBitmapDataFromFile(filename, &width, &height,
1006eaef79e5Smrg				       &storage_data, &x_hot, &y_hot);
1007eaef79e5Smrg    if (status == BitmapSuccess) {
1008eaef79e5Smrg
1009eaef79e5Smrg	DestroyBitmapImage(&BW->bitmap.storage);
1010eaef79e5Smrg
1011eaef79e5Smrg	BW->bitmap.storage = CreateBitmapImage(BW, (char *)storage_data, width, height);
1012eaef79e5Smrg
1013eaef79e5Smrg	return BitmapSuccess;
1014eaef79e5Smrg    }
1015eaef79e5Smrg    else
1016eaef79e5Smrg	XtWarning(" read file failed.  BitmapWidget");
1017eaef79e5Smrg
1018eaef79e5Smrg    return status;
1019eaef79e5Smrg}
1020eaef79e5Smrg
1021eaef79e5SmrgString
1022eaef79e5SmrgBWUnparseStatus(Widget w)
1023eaef79e5Smrg{
1024eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1025eaef79e5Smrg
1026eaef79e5Smrg    XmuSnprintf(BW->bitmap.status, sizeof(BW->bitmap.status),
1027eaef79e5Smrg	    "Filename: %s  Basename: %s  Size: %dx%d",
1028eaef79e5Smrg	    (strcmp(BW->bitmap.filename, "") ? BW->bitmap.filename : "<none>"),
1029eaef79e5Smrg	    (strcmp(BW->bitmap.basename, "") ? BW->bitmap.basename : "<none>"),
1030eaef79e5Smrg	    BW->bitmap.width, BW->bitmap.height);
1031eaef79e5Smrg
1032eaef79e5Smrg    return BW->bitmap.status;
1033eaef79e5Smrg}
1034eaef79e5Smrg
1035eaef79e5Smrgvoid
1036eaef79e5SmrgBWChangeFilename(Widget w, String str)
1037eaef79e5Smrg{
1038eaef79e5Smrg  BitmapWidget BW = (BitmapWidget) w;
1039eaef79e5Smrg
1040eaef79e5Smrg  if (str) {
1041eaef79e5Smrg    XtFree(BW->bitmap.filename);
1042eaef79e5Smrg    BW->bitmap.filename = XtNewString( str);
1043eaef79e5Smrg  }
1044eaef79e5Smrg}
1045eaef79e5Smrg
1046eaef79e5Smrgvoid
1047eaef79e5SmrgBWChangeBasename(Widget w, String str)
1048eaef79e5Smrg{
1049eaef79e5Smrg  BitmapWidget BW = (BitmapWidget) w;
1050eaef79e5Smrg
1051eaef79e5Smrg  if (str) {
1052eaef79e5Smrg    XtFree(BW->bitmap.basename);
1053eaef79e5Smrg    BW->bitmap.basename = XtNewString(str);
1054eaef79e5Smrg  }
1055eaef79e5Smrg}
1056eaef79e5Smrg
1057eaef79e5Smrg
1058eaef79e5Smrgint
1059eaef79e5SmrgBWReadFile(Widget w, String filename, String basename) /* ARGSUSED */
1060eaef79e5Smrg{
1061eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1062eaef79e5Smrg    int status;
1063eaef79e5Smrg    XImage *image, *buffer;
1064eaef79e5Smrg    unsigned char *image_data;
1065eaef79e5Smrg    char *buffer_data;
1066eaef79e5Smrg    unsigned int width, height;
1067eaef79e5Smrg    int x_hot, y_hot;
1068eaef79e5Smrg
1069eaef79e5Smrg    if (!filename)
1070eaef79e5Smrg	filename = BW->bitmap.filename;
1071eaef79e5Smrg
1072eaef79e5Smrg    status = XmuReadBitmapDataFromFile(filename, &width, &height, &image_data,
1073eaef79e5Smrg				       &x_hot, &y_hot);
1074eaef79e5Smrg    if (status == BitmapSuccess) {
1075eaef79e5Smrg
1076eaef79e5Smrg	buffer_data = CreateCleanData(Length(width, height));
1077eaef79e5Smrg
1078eaef79e5Smrg	image = CreateBitmapImage(BW, (char *)image_data, width, height);
1079eaef79e5Smrg	buffer = CreateBitmapImage(BW, buffer_data, width, height);
1080eaef79e5Smrg
1081eaef79e5Smrg	TransferImageData(BW->bitmap.image, buffer);
1082eaef79e5Smrg
1083eaef79e5Smrg	DestroyBitmapImage(&BW->bitmap.image);
1084eaef79e5Smrg	DestroyBitmapImage(&BW->bitmap.buffer);
1085eaef79e5Smrg
1086eaef79e5Smrg	BW->bitmap.image = image;
1087eaef79e5Smrg	BW->bitmap.buffer = buffer;
1088eaef79e5Smrg	BW->bitmap.width = width;
1089eaef79e5Smrg	BW->bitmap.height = height;
1090eaef79e5Smrg
1091eaef79e5Smrg	BW->bitmap.hot.x = x_hot;
1092eaef79e5Smrg	BW->bitmap.hot.y = y_hot;
1093eaef79e5Smrg
1094eaef79e5Smrg	BW->bitmap.changed = False;
1095eaef79e5Smrg	BW->bitmap.zooming = False;
1096eaef79e5Smrg
1097eaef79e5Smrg	XtFree(BW->bitmap.filename);
1098eaef79e5Smrg	BW->bitmap.filename = XtNewString(filename);
1099eaef79e5Smrg	XtFree(BW->bitmap.basename);
1100eaef79e5Smrg	BW->bitmap.basename= XtNewString(StripFilename(filename));
1101eaef79e5Smrg
1102eaef79e5Smrg	BWUnmark(w);
1103eaef79e5Smrg
1104eaef79e5Smrg	Resize((Widget)BW);
1105eaef79e5Smrg
1106eaef79e5Smrg	if (BW->core.visible) {
1107eaef79e5Smrg	    XClearArea(XtDisplay(BW), XtWindow(BW),
1108eaef79e5Smrg		       0, 0,
1109eaef79e5Smrg		       BW->core.width, BW->core.height,
1110eaef79e5Smrg		       True);
1111eaef79e5Smrg	}
1112eaef79e5Smrg
1113eaef79e5Smrg	return BitmapSuccess;
1114eaef79e5Smrg    }
1115eaef79e5Smrg    else
1116eaef79e5Smrg	XtWarning(" read file failed.  BitmapWidget");
1117eaef79e5Smrg
1118eaef79e5Smrg    return status;
1119eaef79e5Smrg}
1120eaef79e5Smrg
1121eaef79e5Smrg#if 0
1122eaef79e5Smrgvoid
1123eaef79e5SmrgBWSetImage(Widget w, XImage *image)
1124eaef79e5Smrg{
1125eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1126eaef79e5Smrg    XImage *buffer;
1127eaef79e5Smrg    char *buffer_data;
1128eaef79e5Smrg
1129eaef79e5Smrg    buffer_data = CreateCleanData(Length(image->width, image->height));
1130eaef79e5Smrg    buffer = CreateBitmapImage(BW, buffer_data,
1131eaef79e5Smrg			       (Dimension) image->width,
1132eaef79e5Smrg			       (Dimension) image->height);
1133eaef79e5Smrg
1134eaef79e5Smrg    TransferImageData(BW->bitmap.image, buffer);
1135eaef79e5Smrg
1136eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.image);
1137eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.buffer);
1138eaef79e5Smrg
1139eaef79e5Smrg    BW->bitmap.image = image;
1140eaef79e5Smrg    BW->bitmap.buffer = buffer;
1141eaef79e5Smrg    BW->bitmap.width = image->width;
1142eaef79e5Smrg    BW->bitmap.height = image->height;
1143eaef79e5Smrg
1144eaef79e5Smrg    Resize((Widget)BW);
1145eaef79e5Smrg
1146eaef79e5Smrg    if (BW->core.visible) {
1147eaef79e5Smrg	XClearArea(XtDisplay(BW), XtWindow(BW),
1148eaef79e5Smrg		   0, 0,
1149eaef79e5Smrg		   BW->core.width, BW->core.height,
1150eaef79e5Smrg		   True);
1151eaef79e5Smrg    }
1152eaef79e5Smrg}
1153eaef79e5Smrg#endif
1154eaef79e5Smrg
1155eaef79e5Smrgint
1156eaef79e5SmrgBWWriteFile(Widget w, String filename, String basename)
1157eaef79e5Smrg{
1158eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1159eaef79e5Smrg    char *data;
1160eaef79e5Smrg    XImage *image;
1161eaef79e5Smrg    XPoint hot;
1162eaef79e5Smrg    int status;
1163eaef79e5Smrg
1164eaef79e5Smrg    if (BW->bitmap.zooming) {
1165eaef79e5Smrg        data = XtMalloc(Length(BW->bitmap.zoom.image->width,
1166eaef79e5Smrg			       BW->bitmap.zoom.image->height));
1167eaef79e5Smrg	memmove( data, BW->bitmap.zoom.image->data,
1168eaef79e5Smrg	      Length(BW->bitmap.zoom.image->width,
1169eaef79e5Smrg		     BW->bitmap.zoom.image->height));
1170eaef79e5Smrg	image = CreateBitmapImage(BW, data,
1171eaef79e5Smrg				  (Dimension) BW->bitmap.zoom.image->width,
1172eaef79e5Smrg				  (Dimension) BW->bitmap.zoom.image->height);
1173eaef79e5Smrg	CopyImageData(BW->bitmap.image, image,
1174eaef79e5Smrg		      0, 0,
1175eaef79e5Smrg		      BW->bitmap.image->width - 1,
1176eaef79e5Smrg		      BW->bitmap.image->height - 1,
1177eaef79e5Smrg		      BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y);
1178eaef79e5Smrg
1179eaef79e5Smrg	if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
1180eaef79e5Smrg	    hot.x = BW->bitmap.hot.x + BW->bitmap.zoom.at_x;
1181eaef79e5Smrg	    hot.y = BW->bitmap.hot.y + BW->bitmap.zoom.at_y;
1182eaef79e5Smrg	}
1183eaef79e5Smrg	else
1184eaef79e5Smrg	    hot = BW->bitmap.zoom.hot;
1185eaef79e5Smrg    }
1186eaef79e5Smrg    else {
1187eaef79e5Smrg	image = BW->bitmap.image;
1188eaef79e5Smrg	hot = BW->bitmap.hot;
1189eaef79e5Smrg    }
1190eaef79e5Smrg
1191eaef79e5Smrg    if (!filename) filename = BW->bitmap.filename;
1192eaef79e5Smrg    else {
1193eaef79e5Smrg	XtFree(BW->bitmap.filename);
1194eaef79e5Smrg	BW->bitmap.filename = XtNewString(filename);
1195eaef79e5Smrg	XtFree(BW->bitmap.basename);
1196eaef79e5Smrg	BW->bitmap.basename= XtNewString(StripFilename(filename));
1197eaef79e5Smrg    }
1198eaef79e5Smrg    if (!basename) basename = BW->bitmap.basename;
1199eaef79e5Smrg    else {
1200eaef79e5Smrg	XtFree(BW->bitmap.basename);
1201eaef79e5Smrg	BW->bitmap.basename = XtNewString(basename);
1202eaef79e5Smrg    }
1203eaef79e5Smrg
1204eaef79e5Smrg    if (DEBUG)
1205eaef79e5Smrg	fprintf(stderr, "Saving filename: %s %s\n", filename, basename);
1206eaef79e5Smrg
1207eaef79e5Smrg    status = XmuWriteBitmapDataToFile(filename, basename,
1208eaef79e5Smrg				      image->width, image->height, image->data,
1209eaef79e5Smrg				      hot.x, hot.y);
1210eaef79e5Smrg    if (BW->bitmap.zooming)
1211eaef79e5Smrg	DestroyBitmapImage(&image);
1212eaef79e5Smrg
1213eaef79e5Smrg    if (status == BitmapSuccess)
1214eaef79e5Smrg	BW->bitmap.changed = False;
1215eaef79e5Smrg
1216eaef79e5Smrg    return status;
1217eaef79e5Smrg}
1218eaef79e5Smrg
1219eaef79e5SmrgString
1220eaef79e5SmrgBWGetFilename(Widget w, String *str)
1221eaef79e5Smrg{
1222eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1223eaef79e5Smrg
1224eaef79e5Smrg    *str = XtNewString(BW->bitmap.filename);
1225eaef79e5Smrg
1226eaef79e5Smrg    return *str;
1227eaef79e5Smrg}
1228eaef79e5Smrg
1229eaef79e5SmrgString
1230eaef79e5SmrgBWGetFilepath(Widget w, String *str)
1231eaef79e5Smrg{
1232eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1233eaef79e5Smrg    String end;
1234eaef79e5Smrg
1235eaef79e5Smrg    *str = XtNewString(BW->bitmap.filename);
1236eaef79e5Smrg    end = strrchr(*str, '/');
1237eaef79e5Smrg
1238eaef79e5Smrg    if (end)
1239eaef79e5Smrg	*(end + 1) = '\0';
1240eaef79e5Smrg    else
1241eaef79e5Smrg	**str = '\0';
1242eaef79e5Smrg
1243eaef79e5Smrg    return *str;
1244eaef79e5Smrg}
1245eaef79e5Smrg
1246eaef79e5Smrg
1247eaef79e5SmrgString
1248eaef79e5SmrgBWGetBasename(Widget w, String *str)
1249eaef79e5Smrg{
1250eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1251eaef79e5Smrg
1252eaef79e5Smrg    *str = XtNewString(BW->bitmap.basename);
1253eaef79e5Smrg
1254eaef79e5Smrg    return *str;
1255eaef79e5Smrg}
1256eaef79e5Smrg
1257eaef79e5Smrgstatic void
1258eaef79e5SmrgFixHotSpot(BitmapWidget BW)
1259eaef79e5Smrg{
1260eaef79e5Smrg    if (!QueryInBitmap(BW, BW->bitmap.hot.x, BW->bitmap.hot.y))
1261eaef79e5Smrg	BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet;
1262eaef79e5Smrg}
1263eaef79e5Smrg
1264eaef79e5Smrgstatic void
1265eaef79e5SmrgZoomOut(BitmapWidget BW)
1266eaef79e5Smrg{
1267eaef79e5Smrg    CopyImageData(BW->bitmap.image, BW->bitmap.zoom.image,
1268eaef79e5Smrg		  0, 0,
1269eaef79e5Smrg		  BW->bitmap.image->width - 1,
1270eaef79e5Smrg		  BW->bitmap.image->height - 1,
1271eaef79e5Smrg		  BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y);
1272eaef79e5Smrg
1273eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.image);
1274eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.buffer);
1275eaef79e5Smrg
1276eaef79e5Smrg    BW->bitmap.image = BW->bitmap.zoom.image;
1277eaef79e5Smrg    BW->bitmap.buffer = BW->bitmap.zoom.buffer;
1278eaef79e5Smrg    BW->bitmap.width = BW->bitmap.image->width;
1279eaef79e5Smrg    BW->bitmap.height = BW->bitmap.image->height;
1280eaef79e5Smrg    BW->bitmap.fold = BW->bitmap.zoom.fold;
1281eaef79e5Smrg    BW->bitmap.changed |= BW->bitmap.zoom.changed;
1282eaef79e5Smrg    BW->bitmap.grid = BW->bitmap.zoom.grid;
1283eaef79e5Smrg
1284eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
1285eaef79e5Smrg	BW->bitmap.hot.x += BW->bitmap.zoom.at_x;
1286eaef79e5Smrg	BW->bitmap.hot.y += BW->bitmap.zoom.at_y;
1287eaef79e5Smrg    }
1288eaef79e5Smrg    else
1289eaef79e5Smrg	BW->bitmap.hot = BW->bitmap.zoom.hot;
1290eaef79e5Smrg
1291eaef79e5Smrg    BW->bitmap.mark.from_x = NotSet;
1292eaef79e5Smrg    BW->bitmap.mark.from_y = NotSet;
1293eaef79e5Smrg    BW->bitmap.mark.to_x = NotSet;
1294eaef79e5Smrg    BW->bitmap.mark.to_y = NotSet;
1295eaef79e5Smrg    BW->bitmap.zooming = False;
1296eaef79e5Smrg}
1297eaef79e5Smrg
1298eaef79e5Smrgvoid
1299eaef79e5SmrgBWZoomOut(Widget w)
1300eaef79e5Smrg{
1301eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1302eaef79e5Smrg
1303eaef79e5Smrg    if (BW->bitmap.zooming) {
1304eaef79e5Smrg	ZoomOut(BW);
1305eaef79e5Smrg
1306eaef79e5Smrg	Resize((Widget)BW);
1307eaef79e5Smrg	if (BW->core.visible)
1308eaef79e5Smrg	    XClearArea(XtDisplay(BW), XtWindow(BW),
1309eaef79e5Smrg		       0, 0,
1310eaef79e5Smrg		       BW->core.width, BW->core.height,
1311eaef79e5Smrg		       True);
1312eaef79e5Smrg    }
1313eaef79e5Smrg}
1314eaef79e5Smrg
1315eaef79e5Smrg
1316eaef79e5Smrgvoid
1317eaef79e5SmrgBWZoomMarked(Widget w)
1318eaef79e5Smrg{
1319eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1320eaef79e5Smrg
1321eaef79e5Smrg    BWZoomIn(w,
1322eaef79e5Smrg	     BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1323eaef79e5Smrg	     BW->bitmap.mark.to_x,   BW->bitmap.mark.to_y);
1324eaef79e5Smrg}
1325eaef79e5Smrg
1326eaef79e5Smrgvoid
1327eaef79e5SmrgBWZoomIn(Widget w,
1328eaef79e5Smrg	 Position from_x, Position from_y,
1329eaef79e5Smrg	 Position to_x, Position to_y)
1330eaef79e5Smrg{
1331eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1332eaef79e5Smrg    XImage *image, *buffer;
1333eaef79e5Smrg    Dimension width, height;
1334eaef79e5Smrg    char *image_data, *buffer_data;
1335eaef79e5Smrg
1336eaef79e5Smrg    if (BW->bitmap.zooming)
1337eaef79e5Smrg	ZoomOut(BW);
1338eaef79e5Smrg
1339eaef79e5Smrg    QuerySwap(from_x, to_x);
1340eaef79e5Smrg    QuerySwap(from_y, to_y);
1341eaef79e5Smrg    from_x = max(0, from_x);
1342eaef79e5Smrg    from_y = max(0, from_y);
1343eaef79e5Smrg    to_x = min(BW->bitmap.width - 1, to_x);
1344eaef79e5Smrg    to_y = min(BW->bitmap.height - 1, to_y);
1345eaef79e5Smrg
1346eaef79e5Smrg    width = to_x - from_x + 1;
1347eaef79e5Smrg    height = to_y - from_y + 1;
1348eaef79e5Smrg
1349eaef79e5Smrg    image_data = CreateCleanData(Length(width, height));
1350eaef79e5Smrg    buffer_data = CreateCleanData(Length(width, height));
1351eaef79e5Smrg
1352eaef79e5Smrg    image = CreateBitmapImage(BW, image_data, width, height);
1353eaef79e5Smrg    buffer = CreateBitmapImage(BW, buffer_data, width, height);
1354eaef79e5Smrg
1355eaef79e5Smrg    CopyImageData(BW->bitmap.image, image, from_x, from_y, to_x, to_y, 0, 0);
1356eaef79e5Smrg    CopyImageData(BW->bitmap.buffer, buffer, from_x, from_y, to_x, to_y, 0, 0);
1357eaef79e5Smrg
1358eaef79e5Smrg    BW->bitmap.zoom.image = BW->bitmap.image;
1359eaef79e5Smrg    BW->bitmap.zoom.buffer = BW->bitmap.buffer;
1360eaef79e5Smrg    BW->bitmap.zoom.at_x = from_x;
1361eaef79e5Smrg    BW->bitmap.zoom.at_y = from_y;
1362eaef79e5Smrg    BW->bitmap.zoom.fold = BW->bitmap.fold;
1363eaef79e5Smrg    BW->bitmap.zoom.changed = BW->bitmap.changed;
1364eaef79e5Smrg    BW->bitmap.zoom.hot = BW->bitmap.hot;
1365eaef79e5Smrg    BW->bitmap.zoom.grid = BW->bitmap.grid;
1366eaef79e5Smrg
1367eaef79e5Smrg    BW->bitmap.image = image;
1368eaef79e5Smrg    BW->bitmap.buffer = buffer;
1369eaef79e5Smrg    BW->bitmap.width = width;
1370eaef79e5Smrg    BW->bitmap.height = height;
1371eaef79e5Smrg    BW->bitmap.changed = False;
1372eaef79e5Smrg    BW->bitmap.hot.x -= from_x;
1373eaef79e5Smrg    BW->bitmap.hot.y -= from_y;
1374eaef79e5Smrg    BW->bitmap.mark.from_x = NotSet;
1375eaef79e5Smrg    BW->bitmap.mark.from_y = NotSet;
1376eaef79e5Smrg    BW->bitmap.mark.to_x = NotSet;
1377eaef79e5Smrg    BW->bitmap.mark.to_y = NotSet;
1378eaef79e5Smrg    BW->bitmap.zooming = True;
1379eaef79e5Smrg    BW->bitmap.grid = True; /* potencially true, could use a resource here */
1380eaef79e5Smrg
1381eaef79e5Smrg    FixHotSpot(BW);
1382eaef79e5Smrg
1383eaef79e5Smrg    Resize((Widget)BW);
1384eaef79e5Smrg    if (BW->core.visible)
1385eaef79e5Smrg	XClearArea(XtDisplay(BW), XtWindow(BW),
1386eaef79e5Smrg		   0, 0,
1387eaef79e5Smrg		   BW->core.width, BW->core.height,
1388eaef79e5Smrg		   True);
1389eaef79e5Smrg}
1390eaef79e5Smrg
1391eaef79e5Smrg
1392eaef79e5Smrgvoid
1393eaef79e5SmrgBWRescale(Widget w, Dimension width, Dimension height)
1394eaef79e5Smrg{
1395eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1396eaef79e5Smrg    XImage *image, *buffer;
1397eaef79e5Smrg    char *buffer_data;
1398eaef79e5Smrg
1399eaef79e5Smrg    if (BW->bitmap.zooming)
1400eaef79e5Smrg	ZoomOut(BW);
1401eaef79e5Smrg
1402eaef79e5Smrg    image = ScaleBitmapImage(BW, BW->bitmap.image,
1403eaef79e5Smrg		       (double) width / (double) BW->bitmap.image->width,
1404eaef79e5Smrg		       (double) height / (double) BW->bitmap.image->height);
1405eaef79e5Smrg
1406eaef79e5Smrg    buffer_data = CreateCleanData(Length(image->width, image->height));
1407eaef79e5Smrg    buffer = CreateBitmapImage(BW, buffer_data,
1408eaef79e5Smrg			       (Dimension) image->width,
1409eaef79e5Smrg			       (Dimension) image->height);
1410eaef79e5Smrg
1411eaef79e5Smrg    TransferImageData(BW->bitmap.buffer, buffer);
1412eaef79e5Smrg
1413eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.image);
1414eaef79e5Smrg    DestroyBitmapImage(&BW->bitmap.buffer);
1415eaef79e5Smrg
1416eaef79e5Smrg    BW->bitmap.image = image;
1417eaef79e5Smrg    BW->bitmap.buffer = buffer;
1418eaef79e5Smrg    BW->bitmap.width = image->width;
1419eaef79e5Smrg    BW->bitmap.height = image->height;
1420eaef79e5Smrg
1421eaef79e5Smrg    FixHotSpot(BW);
1422eaef79e5Smrg    FixMark(BW);
1423eaef79e5Smrg
1424eaef79e5Smrg    Resize((Widget)BW);
1425eaef79e5Smrg    if (BW->core.visible)
1426eaef79e5Smrg	XClearArea(XtDisplay(BW), XtWindow(BW),
1427eaef79e5Smrg		   0, 0,
1428eaef79e5Smrg		   BW->core.width, BW->core.height,
1429eaef79e5Smrg		   True);
1430eaef79e5Smrg}
1431eaef79e5Smrg
1432eaef79e5SmrgBoolean
1433eaef79e5SmrgBWQueryZooming(Widget w)
1434eaef79e5Smrg{
1435eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1436eaef79e5Smrg
1437eaef79e5Smrg    return BW->bitmap.zooming;
1438eaef79e5Smrg}
1439eaef79e5Smrg
1440eaef79e5Smrg
1441eaef79e5Smrgstatic void
1442eaef79e5SmrgResizeGrid(BitmapWidget BW, Dimension width, Dimension height)
1443eaef79e5Smrg{
1444eaef79e5Smrg  XImage *image, *buffer;
1445eaef79e5Smrg  char *image_data, *buffer_data;
1446eaef79e5Smrg
1447eaef79e5Smrg  if (BW->bitmap.zooming)
1448eaef79e5Smrg    ZoomOut(BW);
1449eaef79e5Smrg
1450eaef79e5Smrg  image_data = CreateCleanData(Length(width, height));
1451eaef79e5Smrg  buffer_data = CreateCleanData(Length(width, height));
1452eaef79e5Smrg
1453eaef79e5Smrg  image = CreateBitmapImage(BW, image_data, width, height);
1454eaef79e5Smrg  buffer = CreateBitmapImage(BW, buffer_data, width, height);
1455eaef79e5Smrg
1456eaef79e5Smrg  TransferImageData(BW->bitmap.image, image);
1457eaef79e5Smrg  TransferImageData(BW->bitmap.buffer, buffer);
1458eaef79e5Smrg
1459eaef79e5Smrg  DestroyBitmapImage(&BW->bitmap.image);
1460eaef79e5Smrg  DestroyBitmapImage(&BW->bitmap.buffer);
1461eaef79e5Smrg
1462eaef79e5Smrg  BW->bitmap.image = image;
1463eaef79e5Smrg  BW->bitmap.buffer = buffer;
1464eaef79e5Smrg  BW->bitmap.width = width;
1465eaef79e5Smrg  BW->bitmap.height = height;
1466eaef79e5Smrg
1467eaef79e5Smrg  FixHotSpot(BW);
1468eaef79e5Smrg  FixMark(BW);
1469eaef79e5Smrg}
1470eaef79e5Smrg
1471eaef79e5Smrgvoid
1472eaef79e5SmrgBWResize(Widget w, Dimension width, Dimension height)
1473eaef79e5Smrg{
1474eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1475eaef79e5Smrg
1476eaef79e5Smrg    ResizeGrid(BW, width, height);
1477eaef79e5Smrg
1478eaef79e5Smrg    Resize((Widget)BW);
1479eaef79e5Smrg    if (BW->core.visible)
1480eaef79e5Smrg	XClearArea(XtDisplay(BW), XtWindow(BW),
1481eaef79e5Smrg		   0, 0,
1482eaef79e5Smrg		   BW->core.width, BW->core.height,
1483eaef79e5Smrg		   True);
1484eaef79e5Smrg}
1485eaef79e5Smrg
1486eaef79e5Smrgstatic void
1487eaef79e5SmrgDestroy(Widget w)
1488eaef79e5Smrg{
1489eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1490eaef79e5Smrg
1491eaef79e5Smrg    XFreeGC(XtDisplay(w), BW->bitmap.drawing_gc);
1492eaef79e5Smrg    XFreeGC(XtDisplay(w), BW->bitmap.highlighting_gc);
1493eaef79e5Smrg    XFreeGC(XtDisplay(w), BW->bitmap.frame_gc);
1494eaef79e5Smrg    XFreeGC(XtDisplay(w), BW->bitmap.axes_gc);
1495eaef79e5Smrg    BWRemoveAllRequests(w);
1496eaef79e5Smrg
1497eaef79e5Smrg    XtFree(BW->bitmap.filename);
1498eaef79e5Smrg    XtFree(BW->bitmap.basename);
1499eaef79e5Smrg}
1500eaef79e5Smrg
1501eaef79e5Smrg
1502eaef79e5Smrgstatic void
1503eaef79e5SmrgResize(Widget w)
1504eaef79e5Smrg{
1505eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1506eaef79e5Smrg
1507eaef79e5Smrg    Dimension squareW, squareH;
1508eaef79e5Smrg
1509eaef79e5Smrg    squareW = max(1, ((int)BW->core.width - 2 * (int)BW->bitmap.margin) /
1510eaef79e5Smrg		  (int)BW->bitmap.width);
1511eaef79e5Smrg    squareH = max(1, ((int)BW->core.height - 2 * (int)BW->bitmap.margin) /
1512eaef79e5Smrg		  (int)BW->bitmap.height);
1513eaef79e5Smrg
1514eaef79e5Smrg    if (BW->bitmap.proportional)
1515eaef79e5Smrg	BW->bitmap.squareW = BW->bitmap.squareH = min(squareW, squareH);
1516eaef79e5Smrg    else {
1517eaef79e5Smrg	BW->bitmap.squareW = squareW;
1518eaef79e5Smrg	BW->bitmap.squareH = squareH;
1519eaef79e5Smrg    }
1520eaef79e5Smrg
1521eaef79e5Smrg    BW->bitmap.horizOffset = max((Position)BW->bitmap.margin,
1522eaef79e5Smrg				 (Position)(BW->core.width -
1523eaef79e5Smrg					    BW->bitmap.width *
1524eaef79e5Smrg					    BW->bitmap.squareW) / 2);
1525eaef79e5Smrg    BW->bitmap.vertOffset = max((Position)BW->bitmap.margin,
1526eaef79e5Smrg				(Position)(BW->core.height -
1527eaef79e5Smrg					   BW->bitmap.height *
1528eaef79e5Smrg					   BW->bitmap.squareH) / 2);
1529eaef79e5Smrg
1530eaef79e5Smrg    BW->bitmap.grid &= ((BW->bitmap.squareW > BW->bitmap.grid_tolerance) &&
1531eaef79e5Smrg			(BW->bitmap.squareH > BW->bitmap.grid_tolerance));
1532eaef79e5Smrg}
1533eaef79e5Smrg
1534eaef79e5Smrg/* ARGSUSED */
1535eaef79e5Smrgstatic void
1536eaef79e5SmrgRedisplay(Widget w, XEvent *event, Region region)
1537eaef79e5Smrg{
1538eaef79e5Smrg     BitmapWidget BW = (BitmapWidget) w;
1539eaef79e5Smrg
1540eaef79e5Smrg  if(event->type == Expose
1541eaef79e5Smrg     &&
1542eaef79e5Smrg     BW->core.visible)
1543eaef79e5Smrg    if (BW->bitmap.stipple_change_expose_event == False)
1544eaef79e5Smrg      Refresh(BW,
1545eaef79e5Smrg	      event->xexpose.x, event->xexpose.y,
1546eaef79e5Smrg	      event->xexpose.width, event->xexpose.height);
1547eaef79e5Smrg}
1548eaef79e5Smrg
1549eaef79e5Smrgvoid
1550eaef79e5SmrgBWClip(Widget w, Position x, Position y, Dimension width, Dimension height)
1551eaef79e5Smrg{
1552eaef79e5Smrg    Position      from_x, from_y,
1553eaef79e5Smrg                  to_x, to_y;
1554eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1555eaef79e5Smrg    XRectangle rectangle;
1556eaef79e5Smrg
1557eaef79e5Smrg    from_x = InBitmapX(BW, x);
1558eaef79e5Smrg    from_y = InBitmapY(BW, y);
1559eaef79e5Smrg    to_x = InBitmapX(BW, x + width);
1560eaef79e5Smrg    to_y = InBitmapY(BW, y + height);
1561eaef79e5Smrg    QuerySwap(from_x, to_x);
1562eaef79e5Smrg    QuerySwap(from_y, to_y);
1563eaef79e5Smrg    from_x = max(0, from_x);
1564eaef79e5Smrg    from_y = max(0, from_y);
1565eaef79e5Smrg    to_x = min(BW->bitmap.width - 1, to_x);
1566eaef79e5Smrg    to_y = min(BW->bitmap.height - 1, to_y);
1567eaef79e5Smrg
1568eaef79e5Smrg    rectangle.x = InWindowX(BW, from_x);
1569eaef79e5Smrg    rectangle.y = InWindowY(BW, from_y);
1570eaef79e5Smrg    rectangle.width = InWindowX(BW, to_x  + 1) - InWindowX(BW, from_x);
1571eaef79e5Smrg    rectangle.height = InWindowY(BW, to_y + 1) - InWindowY(BW, from_y);
1572eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1573eaef79e5Smrg		       BW->bitmap.highlighting_gc,
1574eaef79e5Smrg		       0, 0,
1575eaef79e5Smrg		       &rectangle, 1,
1576eaef79e5Smrg		       Unsorted);
1577eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1578eaef79e5Smrg		       BW->bitmap.drawing_gc,
1579eaef79e5Smrg		       0, 0,
1580eaef79e5Smrg		       &rectangle, 1,
1581eaef79e5Smrg		       Unsorted);
1582eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1583eaef79e5Smrg		       BW->bitmap.frame_gc,
1584eaef79e5Smrg		       0, 0,
1585eaef79e5Smrg		       &rectangle, 1,
1586eaef79e5Smrg		       Unsorted);
1587eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1588eaef79e5Smrg		       BW->bitmap.axes_gc,
1589eaef79e5Smrg		       0, 0,
1590eaef79e5Smrg		       &rectangle, 1,
1591eaef79e5Smrg		       Unsorted);
1592eaef79e5Smrg}
1593eaef79e5Smrg
1594eaef79e5Smrgvoid
1595eaef79e5SmrgBWUnclip(Widget w)
1596eaef79e5Smrg{
1597eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1598eaef79e5Smrg    XRectangle rectangle;
1599eaef79e5Smrg
1600eaef79e5Smrg    rectangle.x = InWindowX(BW, 0);
1601eaef79e5Smrg    rectangle.y = InWindowY(BW, 0);
1602eaef79e5Smrg    rectangle.width = InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0);
1603eaef79e5Smrg    rectangle.height = InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0);
1604eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1605eaef79e5Smrg		       BW->bitmap.highlighting_gc,
1606eaef79e5Smrg		       0, 0,
1607eaef79e5Smrg		       &rectangle, 1,
1608eaef79e5Smrg		       Unsorted);
1609eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1610eaef79e5Smrg		       BW->bitmap.drawing_gc,
1611eaef79e5Smrg		       0, 0,
1612eaef79e5Smrg		       &rectangle, 1,
1613eaef79e5Smrg		       Unsorted);
1614eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1615eaef79e5Smrg		       BW->bitmap.frame_gc,
1616eaef79e5Smrg		       0, 0,
1617eaef79e5Smrg		       &rectangle, 1,
1618eaef79e5Smrg		       Unsorted);
1619eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1620eaef79e5Smrg		       BW->bitmap.axes_gc,
1621eaef79e5Smrg		       0, 0,
1622eaef79e5Smrg		       &rectangle, 1,
1623eaef79e5Smrg		       Unsorted);
1624eaef79e5Smrg}
1625eaef79e5Smrg
1626eaef79e5Smrgstatic void
1627eaef79e5SmrgRefresh(BitmapWidget BW, Position x, Position y,
1628eaef79e5Smrg	Dimension width, Dimension height)
1629eaef79e5Smrg{
1630eaef79e5Smrg    XRectangle rectangle;
1631eaef79e5Smrg
1632eaef79e5Smrg    rectangle.x = min(x, InWindowX(BW, InBitmapX(BW, x)));
1633eaef79e5Smrg    rectangle.y = min(y, InWindowY(BW, InBitmapY(BW, y)));
1634eaef79e5Smrg    rectangle.width = max(x + width,
1635eaef79e5Smrg		     InWindowX(BW, InBitmapX(BW, x + width)+1)) - rectangle.x;
1636eaef79e5Smrg    rectangle.height = max(y + height,
1637eaef79e5Smrg		     InWindowY(BW, InBitmapY(BW, y + height)+1)) - rectangle.y;
1638eaef79e5Smrg
1639eaef79e5Smrg    XClearArea(XtDisplay(BW), XtWindow(BW),
1640eaef79e5Smrg	       rectangle.x, rectangle.y,
1641eaef79e5Smrg	       rectangle.width, rectangle.height,
1642eaef79e5Smrg	       False);
1643eaef79e5Smrg
1644eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1645eaef79e5Smrg		       BW->bitmap.frame_gc,
1646eaef79e5Smrg		       0, 0,
1647eaef79e5Smrg		       &rectangle, 1,
1648eaef79e5Smrg		       Unsorted);
1649eaef79e5Smrg
1650eaef79e5Smrg    XDrawRectangle(XtDisplay(BW), XtWindow(BW),
1651eaef79e5Smrg		   BW->bitmap.frame_gc,
1652eaef79e5Smrg		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
1653eaef79e5Smrg		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
1654eaef79e5Smrg		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
1655eaef79e5Smrg
1656eaef79e5Smrg    BWClip((Widget) BW, x, y, width, height);
1657eaef79e5Smrg
1658eaef79e5Smrg    BWRedrawGrid((Widget) BW, x, y, width, height);
1659eaef79e5Smrg
1660eaef79e5Smrg    BWRedrawSquares((Widget) BW, x, y, width, height);
1661eaef79e5Smrg
1662eaef79e5Smrg    BWRedrawMark((Widget) BW);
1663eaef79e5Smrg    BWRedrawHotSpot((Widget) BW);
1664eaef79e5Smrg    BWRedrawAxes((Widget) BW);
1665eaef79e5Smrg    BWUnclip((Widget) BW);
1666eaef79e5Smrg}
1667eaef79e5Smrg
1668eaef79e5SmrgBoolean
1669eaef79e5SmrgBWQueryGrid(Widget w)
1670eaef79e5Smrg{
1671eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1672eaef79e5Smrg
1673eaef79e5Smrg    return BW->bitmap.grid;
1674eaef79e5Smrg}
1675eaef79e5Smrg
1676eaef79e5Smrgvoid
1677eaef79e5SmrgBWSwitchGrid(Widget w)
1678eaef79e5Smrg{
1679eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1680eaef79e5Smrg    BW->bitmap.grid ^= TRUE;
1681eaef79e5Smrg    BWDrawGrid(w,
1682eaef79e5Smrg	       0, 0,
1683eaef79e5Smrg	       BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
1684eaef79e5Smrg}
1685eaef79e5Smrg
1686eaef79e5Smrgvoid
1687eaef79e5SmrgBWGrid(Widget w, Boolean _switch)
1688eaef79e5Smrg{
1689eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1690eaef79e5Smrg
1691eaef79e5Smrg    if (BW->bitmap.grid != _switch)
1692eaef79e5Smrg	BWSwitchGrid(w);
1693eaef79e5Smrg}
1694eaef79e5Smrg
1695eaef79e5SmrgBoolean
1696eaef79e5SmrgBWQueryDashed(Widget w)
1697eaef79e5Smrg{
1698eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1699eaef79e5Smrg
1700eaef79e5Smrg    return (BW->bitmap.dashed);
1701eaef79e5Smrg}
1702eaef79e5Smrg
1703eaef79e5Smrgvoid
1704eaef79e5SmrgBWSwitchDashed(Widget w)
1705eaef79e5Smrg{
1706eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1707eaef79e5Smrg    XRectangle rectangle;
1708eaef79e5Smrg
1709eaef79e5Smrg    BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1);
1710eaef79e5Smrg
1711eaef79e5Smrg    rectangle.x = 0;
1712eaef79e5Smrg    rectangle.y = 0;
1713eaef79e5Smrg    rectangle.width = BW->core.width;
1714eaef79e5Smrg    rectangle.height = BW->core.height;
1715eaef79e5Smrg
1716eaef79e5Smrg    XSetClipRectangles(XtDisplay(BW),
1717eaef79e5Smrg		       BW->bitmap.frame_gc,
1718eaef79e5Smrg		       0, 0,
1719eaef79e5Smrg		       &rectangle, 1,
1720eaef79e5Smrg		       Unsorted);
1721eaef79e5Smrg
1722eaef79e5Smrg    XDrawRectangle(XtDisplay(BW), XtWindow(BW),
1723eaef79e5Smrg		   BW->bitmap.frame_gc,
1724eaef79e5Smrg		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
1725eaef79e5Smrg		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
1726eaef79e5Smrg		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
1727eaef79e5Smrg
1728eaef79e5Smrg    BW->bitmap.dashed ^= True;
1729eaef79e5Smrg    XSetFillStyle(XtDisplay(BW), BW->bitmap.frame_gc,
1730eaef79e5Smrg		  (BW->bitmap.dashed ? FillStippled : FillSolid));
1731eaef79e5Smrg
1732eaef79e5Smrg    XDrawRectangle(XtDisplay(BW), XtWindow(BW),
1733eaef79e5Smrg		   BW->bitmap.frame_gc,
1734eaef79e5Smrg		   InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1,
1735eaef79e5Smrg		   InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1,
1736eaef79e5Smrg		   InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1);
1737eaef79e5Smrg
1738eaef79e5Smrg    BWUnclip(w);
1739eaef79e5Smrg
1740eaef79e5Smrg    BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1);
1741eaef79e5Smrg}
1742eaef79e5Smrg
1743eaef79e5Smrgvoid
1744eaef79e5SmrgBWDashed(Widget w, Boolean _switch)
1745eaef79e5Smrg{
1746eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1747eaef79e5Smrg
1748eaef79e5Smrg    if (BW->bitmap.dashed != _switch)
1749eaef79e5Smrg	BWSwitchDashed(w);
1750eaef79e5Smrg}
1751eaef79e5Smrg
1752eaef79e5Smrgstatic Boolean
1753eaef79e5SmrgSetValues(Widget old, Widget request, Widget new,
1754eaef79e5Smrg	  ArgList args, Cardinal *num_args) /* ARGSUSED */
1755eaef79e5Smrg{
1756eaef79e5Smrg  BitmapWidget oldbw = (BitmapWidget) old;
1757eaef79e5Smrg  BitmapWidget newbw = (BitmapWidget) new;
1758eaef79e5Smrg  Boolean resize = False;
1759eaef79e5Smrg  Boolean redisplay = False;
1760eaef79e5Smrg
1761eaef79e5Smrg#define NE(field) (oldbw->field != newbw->field)
1762eaef79e5Smrg
1763eaef79e5Smrg  if (NE(bitmap.grid))
1764eaef79e5Smrg    BWSwitchGrid(old);
1765eaef79e5Smrg
1766eaef79e5Smrg  if (NE(bitmap.dashed))
1767eaef79e5Smrg    BWSwitchDashed(old);
1768eaef79e5Smrg
1769eaef79e5Smrg  if (NE(bitmap.axes))
1770eaef79e5Smrg    BWSwitchAxes(old);
1771eaef79e5Smrg
1772eaef79e5Smrg  if (NE(bitmap.stippled))
1773eaef79e5Smrg    BWSwitchStippled(old);
1774eaef79e5Smrg
1775eaef79e5Smrg  if (NE(bitmap.proportional))
1776eaef79e5Smrg    resize = True;
1777eaef79e5Smrg
1778eaef79e5Smrg  if (NE(bitmap.filename) || NE(bitmap.basename)  || NE(bitmap.size))
1779eaef79e5Smrg    BWChangeNotify(old);
1780eaef79e5Smrg
1781eaef79e5Smrg  if (NE(bitmap.filename)) {
1782eaef79e5Smrg    if (newbw->bitmap.filename) {
1783eaef79e5Smrg      XtFree(oldbw->bitmap.filename);
1784eaef79e5Smrg      newbw->bitmap.filename = XtNewString(newbw->bitmap.filename);
1785eaef79e5Smrg    }
1786eaef79e5Smrg    else
1787eaef79e5Smrg      newbw->bitmap.filename = oldbw->bitmap.filename;
1788eaef79e5Smrg  }
1789eaef79e5Smrg
1790eaef79e5Smrg  if (NE(bitmap.basename)) {
1791eaef79e5Smrg    if (newbw->bitmap.basename) {
1792eaef79e5Smrg      XtFree(oldbw->bitmap.basename);
1793eaef79e5Smrg      newbw->bitmap.basename = XtNewString(newbw->bitmap.basename);
1794eaef79e5Smrg    }
1795eaef79e5Smrg    else
1796eaef79e5Smrg      newbw->bitmap.basename = oldbw->bitmap.basename;
1797eaef79e5Smrg  }
1798eaef79e5Smrg
1799eaef79e5Smrg  if (NE(bitmap.size)) {
1800eaef79e5Smrg    Dimension width, height;
1801eaef79e5Smrg
1802eaef79e5Smrg    if (BWParseSize(newbw->bitmap.size, &width, &height)) {
1803eaef79e5Smrg      ResizeGrid(newbw, width, height);
1804eaef79e5Smrg      resize = True;
1805eaef79e5Smrg    }
1806eaef79e5Smrg  }
1807eaef79e5Smrg
1808eaef79e5Smrg  if (NE(bitmap.margin) ||
1809eaef79e5Smrg      NE(bitmap.grid_tolerance) ||
1810eaef79e5Smrg      NE(bitmap.squareW) ||
1811eaef79e5Smrg      NE(bitmap.squareH) ||
1812eaef79e5Smrg      NE(core.height) ||
1813eaef79e5Smrg      NE(core.width))
1814eaef79e5Smrg    resize = True;
1815eaef79e5Smrg
1816eaef79e5Smrg  if (NE(bitmap.hot.x) || NE(bitmap.hot.y))
1817eaef79e5Smrg    BWSetHotSpot(old, newbw->bitmap.hot.x, newbw->bitmap.hot.y);
1818eaef79e5Smrg
1819eaef79e5Smrg  if (NE(bitmap.foreground_pixel) || NE(core.background_pixel)) {
1820eaef79e5Smrg    XSetForeground(XtDisplay(new),
1821eaef79e5Smrg		   newbw->bitmap.drawing_gc,
1822eaef79e5Smrg		   newbw->bitmap.foreground_pixel
1823eaef79e5Smrg		   ^
1824eaef79e5Smrg		   newbw->core.background_pixel);
1825eaef79e5Smrg    redisplay = True;
1826eaef79e5Smrg  }
1827eaef79e5Smrg
1828eaef79e5Smrg  if (NE(bitmap.frame_pixel) || NE(core.background_pixel)) {
1829eaef79e5Smrg    XSetForeground(XtDisplay(new),
1830eaef79e5Smrg		   newbw->bitmap.frame_gc,
1831eaef79e5Smrg		   newbw->bitmap.frame_pixel
1832eaef79e5Smrg		   ^
1833eaef79e5Smrg		   newbw->core.background_pixel);
1834eaef79e5Smrg    redisplay = True;
1835eaef79e5Smrg  }
1836eaef79e5Smrg
1837eaef79e5Smrg  if (NE(bitmap.dashes)) {
1838eaef79e5Smrg    XSetStipple(XtDisplay(new),
1839eaef79e5Smrg		newbw->bitmap.frame_gc,
1840eaef79e5Smrg		newbw->bitmap.dashes);
1841eaef79e5Smrg    redisplay = True;
1842eaef79e5Smrg  }
1843eaef79e5Smrg
1844eaef79e5Smrg  if (NE(bitmap.highlight_pixel) || NE(core.background_pixel)) {
1845eaef79e5Smrg    RedrawStippled(newbw);
1846eaef79e5Smrg    XSetForeground(XtDisplay(new),
1847eaef79e5Smrg		   newbw->bitmap.highlighting_gc,
1848eaef79e5Smrg		   newbw->bitmap.highlight_pixel
1849eaef79e5Smrg		   ^
1850eaef79e5Smrg		   newbw->core.background_pixel);
1851eaef79e5Smrg    RedrawStippled(newbw);
1852eaef79e5Smrg  }
1853eaef79e5Smrg
1854eaef79e5Smrg  if (NE(bitmap.stipple)) {
1855eaef79e5Smrg    RedrawStippled(newbw);
1856eaef79e5Smrg    XSetStipple(XtDisplay(new),
1857eaef79e5Smrg		newbw->bitmap.highlighting_gc,
1858eaef79e5Smrg		newbw->bitmap.stipple);
1859eaef79e5Smrg    RedrawStippled(newbw);
1860eaef79e5Smrg  }
1861eaef79e5Smrg
1862eaef79e5Smrg  if (resize) Resize((Widget)newbw);
1863eaef79e5Smrg
1864eaef79e5Smrg    return (redisplay || resize);
1865eaef79e5Smrg
1866eaef79e5Smrg#undef NE
1867eaef79e5Smrg}
1868eaef79e5Smrg
1869eaef79e5SmrgBoolean
1870eaef79e5SmrgBWQueryProportional(Widget w)
1871eaef79e5Smrg{
1872eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1873eaef79e5Smrg
1874eaef79e5Smrg    return (BW->bitmap.proportional);
1875eaef79e5Smrg}
1876eaef79e5Smrg
1877eaef79e5Smrgvoid
1878eaef79e5SmrgBWSwitchProportional(Widget w)
1879eaef79e5Smrg{
1880eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1881eaef79e5Smrg
1882eaef79e5Smrg    BW->bitmap.proportional ^= True;
1883eaef79e5Smrg
1884eaef79e5Smrg    Resize((Widget)BW);
1885eaef79e5Smrg    if (BW->core.visible)
1886eaef79e5Smrg	XClearArea(XtDisplay(BW), XtWindow(BW),
1887eaef79e5Smrg		   0, 0,
1888eaef79e5Smrg		   BW->core.width, BW->core.height,
1889eaef79e5Smrg		   True);
1890eaef79e5Smrg}
1891eaef79e5Smrg
1892eaef79e5Smrg#if 0
1893eaef79e5Smrgvoid
1894eaef79e5SmrgBWProportional(Widget w, Boolean _switch)
1895eaef79e5Smrg{
1896eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1897eaef79e5Smrg
1898eaef79e5Smrg    if (BW->bitmap.proportional != _switch)
1899eaef79e5Smrg	BWSwitchProportional(w);
1900eaef79e5Smrg}
1901eaef79e5Smrg#endif
1902eaef79e5Smrg
1903eaef79e5Smrgvoid
1904eaef79e5SmrgBWTPaste(Widget w, XEvent *event, String *params, Cardinal *num_params)
1905eaef79e5Smrg{
1906eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1907eaef79e5Smrg
1908eaef79e5Smrg    BWRequestSelection(w, event->xbutton.time, TRUE);
1909eaef79e5Smrg
1910eaef79e5Smrg    if (!BWQueryStored(w))
1911eaef79e5Smrg	return;
1912eaef79e5Smrg
1913eaef79e5Smrg    BWEngageRequest(w, RestoreRequest, False,
1914eaef79e5Smrg		    (char *)&(event->xbutton.state), sizeof(int));
1915eaef79e5Smrg
1916eaef79e5Smrg    OnePointHandler(w,
1917eaef79e5Smrg	       (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status,
1918eaef79e5Smrg	       event, NULL);
1919eaef79e5Smrg}
1920eaef79e5Smrg
1921eaef79e5Smrgvoid
1922eaef79e5SmrgBWTMark(Widget w, XEvent *event, String *params, Cardinal *num_params)
1923eaef79e5Smrg{
1924eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1925eaef79e5Smrg
1926eaef79e5Smrg    BWEngageRequest(w, MarkRequest, False,
1927eaef79e5Smrg		    (char *)&(event->xbutton.state), sizeof(int));
1928eaef79e5Smrg    TwoPointsHandler(w,
1929eaef79e5Smrg            (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status,
1930eaef79e5Smrg	     event, NULL);
1931eaef79e5Smrg
1932eaef79e5Smrg}
1933eaef79e5Smrg
1934eaef79e5Smrgvoid
1935eaef79e5SmrgBWTMarkAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
1936eaef79e5Smrg{
1937eaef79e5Smrg    BWMarkAll(w);
1938eaef79e5Smrg
1939eaef79e5Smrg    BWGrabSelection(w, event->xkey.time);
1940eaef79e5Smrg}
1941eaef79e5Smrg
1942eaef79e5Smrgvoid
1943eaef79e5SmrgBWTUnmark(Widget w, XEvent *event, String *params, Cardinal *num_params)
1944eaef79e5Smrg{
1945eaef79e5Smrg    BWUnmark(w);
1946eaef79e5Smrg}
1947eaef79e5Smrg
1948eaef79e5Smrg/*****************************************************************************/
1949