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