Graphics.c revision eaef79e5
1eaef79e5Smrg/* $Xorg: Graphics.c,v 1.4 2001/02/09 02:05:28 xorgcvs Exp $ */
2eaef79e5Smrg/*
3eaef79e5Smrg
4eaef79e5SmrgCopyright 1989, 1998  The Open Group
5eaef79e5Smrg
6eaef79e5SmrgPermission to use, copy, modify, distribute, and sell this software and its
7eaef79e5Smrgdocumentation for any purpose is hereby granted without fee, provided that
8eaef79e5Smrgthe above copyright notice appear in all copies and that both that
9eaef79e5Smrgcopyright notice and this permission notice appear in supporting
10eaef79e5Smrgdocumentation.
11eaef79e5Smrg
12eaef79e5SmrgThe above copyright notice and this permission notice shall be included
13eaef79e5Smrgin all copies or substantial portions of the Software.
14eaef79e5Smrg
15eaef79e5SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16eaef79e5SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17eaef79e5SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18eaef79e5SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19eaef79e5SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20eaef79e5SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21eaef79e5SmrgOTHER DEALINGS IN THE SOFTWARE.
22eaef79e5Smrg
23eaef79e5SmrgExcept as contained in this notice, the name of The Open Group shall
24eaef79e5Smrgnot be used in advertising or otherwise to promote the sale, use or
25eaef79e5Smrgother dealings in this Software without prior written authorization
26eaef79e5Smrgfrom The Open Group.
27eaef79e5Smrg
28eaef79e5Smrg*/
29eaef79e5Smrg/* $XFree86: xc/programs/bitmap/Graphics.c,v 1.5 2001/01/17 23:44:51 dawes Exp $ */
30eaef79e5Smrg
31eaef79e5Smrg/*
32eaef79e5Smrg * Author:  Davor Matic, MIT X Consortium
33eaef79e5Smrg */
34eaef79e5Smrg
35eaef79e5Smrg#include <X11/IntrinsicP.h>
36eaef79e5Smrg#include <X11/StringDefs.h>
37eaef79e5Smrg#include <X11/Xfuncs.h>
38eaef79e5Smrg#include "BitmapP.h"
39eaef79e5Smrg#include "Bitmap.h"
40eaef79e5Smrg#include "Requests.h"
41eaef79e5Smrg
42eaef79e5Smrg#include <stdio.h>
43eaef79e5Smrg#include <math.h>
44eaef79e5Smrg
45eaef79e5Smrg#ifndef abs
46eaef79e5Smrg#define abs(x)                        (((x) > 0) ? (x) : -(x))
47eaef79e5Smrg#endif
48eaef79e5Smrg#define min(x, y)                     (((int)(x) < (int)(y)) ? (x) : (y))
49eaef79e5Smrg#define max(x, y)                     (((int)(x) > (int)(y)) ? (x) : (y))
50eaef79e5Smrg#ifndef rint
51eaef79e5Smrg#define rint(x)                       floor(x + 0.5)
52eaef79e5Smrg#endif
53eaef79e5Smrg
54eaef79e5Smrg/*****************************************************************************\
55eaef79e5Smrg *                                   Graphics                                *
56eaef79e5Smrg\*****************************************************************************/
57eaef79e5Smrg
58eaef79e5Smrg#define GetBit(image, x, y)\
59eaef79e5Smrg    ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\
60eaef79e5Smrg	    (1 << ((x) % 8))) ? 1 : 0))
61eaef79e5Smrg
62eaef79e5Smrg#if 0
63eaef79e5Smrgbit
64eaef79e5SmrgBWGetBit(Widget w, Position x, Position y)
65eaef79e5Smrg{
66eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
67eaef79e5Smrg
68eaef79e5Smrg    if (QueryInBitmap(BW, x, y))
69eaef79e5Smrg	return GetBit(BW->bitmap.image, x, y);
70eaef79e5Smrg    else
71eaef79e5Smrg	return NotSet;
72eaef79e5Smrg}
73eaef79e5Smrg#endif
74eaef79e5Smrg
75eaef79e5Smrg#define InvertBit(image, x, y)\
76eaef79e5Smrg    (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\
77eaef79e5Smrg     (bit) (1 << ((x) % 8)))
78eaef79e5Smrg
79eaef79e5Smrg
80eaef79e5Smrg#define SetBit(image, x, y)\
81eaef79e5Smrg    (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\
82eaef79e5Smrg     (bit) (1 << ((x) % 8)))
83eaef79e5Smrg
84eaef79e5Smrg#define ClearBit(image, x, y)\
85eaef79e5Smrg    (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\
86eaef79e5Smrg     (bit)~(1 << ((x) % 8)))
87eaef79e5Smrg
88eaef79e5Smrg
89eaef79e5Smrg#define HighlightSquare(BW, x, y)\
90eaef79e5Smrg    XFillRectangle(XtDisplay(BW), XtWindow(BW),\
91eaef79e5Smrg                   BW->bitmap.highlighting_gc,\
92eaef79e5Smrg		   InWindowX(BW, x), InWindowY(BW, y),\
93eaef79e5Smrg                   BW->bitmap.squareW, BW->bitmap.squareH)
94eaef79e5Smrg/*
95eaef79e5Smrgvoid
96eaef79e5SmrgHighlightSquare(BitmapWidget BW, Position x, Position y)
97eaef79e5Smrg{
98eaef79e5Smrg    XFillRectangle(XtDisplay(BW), XtWindow(BW),
99eaef79e5Smrg                   BW->bitmap.highlighting_gc,
100eaef79e5Smrg		   InWindowX(BW, x), InWindowY(BW, y),
101eaef79e5Smrg                   BW->bitmap.squareW, BW->bitmap.squareH);
102eaef79e5Smrg}
103eaef79e5Smrg*/
104eaef79e5Smrg
105eaef79e5Smrg#define DrawSquare(BW, x, y)\
106eaef79e5Smrg    XFillRectangle(XtDisplay(BW), XtWindow(BW),\
107eaef79e5Smrg                   BW->bitmap.drawing_gc,\
108eaef79e5Smrg		   InWindowX(BW, x), InWindowY(BW, y),\
109eaef79e5Smrg                   BW->bitmap.squareW, BW->bitmap.squareH)
110eaef79e5Smrg
111eaef79e5Smrg/*
112eaef79e5Smrgvoid
113eaef79e5SmrgDrawSquare(BitmapWidget BW, Position x, Position y)
114eaef79e5Smrg{
115eaef79e5Smrg    XFillRectangle(XtDisplay(BW), XtWindow(BW),
116eaef79e5Smrg                   BW->bitmap.drawing_gc,
117eaef79e5Smrg		   InWindowX(BW, x), InWindowY(BW, y),
118eaef79e5Smrg                   BW->bitmap.squareW, BW->bitmap.squareH);
119eaef79e5Smrg}
120eaef79e5Smrg*/
121eaef79e5Smrg
122eaef79e5Smrg#define InvertPoint(BW, x, y)\
123eaef79e5Smrg    {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);}
124eaef79e5Smrg
125eaef79e5Smrg#define DrawPoint(BW, x, y, value)\
126eaef79e5Smrg    if (GetBit(BW->bitmap.image, x, y) != value)\
127eaef79e5Smrg       InvertPoint(BW, x, y)
128eaef79e5Smrg
129eaef79e5Smrgvoid
130eaef79e5SmrgBWDrawPoint(Widget w, Position x, Position y, bit value)
131eaef79e5Smrg{
132eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
133eaef79e5Smrg
134eaef79e5Smrg    if (QueryInBitmap(BW, x, y)) {
135eaef79e5Smrg	if (value == Highlight)
136eaef79e5Smrg	    HighlightSquare(BW, x, y);
137eaef79e5Smrg	else
138eaef79e5Smrg	    DrawPoint(BW, x, y, value);
139eaef79e5Smrg    }
140eaef79e5Smrg}
141eaef79e5Smrg
142eaef79e5Smrgstatic XPoint *
143eaef79e5SmrgHotSpotShape(BitmapWidget BW, Position x, Position y)
144eaef79e5Smrg{
145eaef79e5Smrg    static XPoint points[5];
146eaef79e5Smrg
147eaef79e5Smrg    points[0].x = InWindowX(BW, x);
148eaef79e5Smrg    points[0].y = InWindowY(BW, y + 1.0/2);
149eaef79e5Smrg    points[1].x = InWindowX(BW, x + 1.0/2);
150eaef79e5Smrg    points[1].y = InWindowY(BW, y + 1);
151eaef79e5Smrg    points[2].x = InWindowX(BW, x + 1);
152eaef79e5Smrg    points[2].y = InWindowY(BW, y + 1.0/2);
153eaef79e5Smrg    points[3].x = InWindowX(BW, x + 1.0/2);
154eaef79e5Smrg    points[3].y = InWindowY(BW, y);
155eaef79e5Smrg    points[4].x = InWindowX(BW, x);
156eaef79e5Smrg    points[4].y = InWindowY(BW, y + 1.0/2);
157eaef79e5Smrg
158eaef79e5Smrg    return points;
159eaef79e5Smrg}
160eaef79e5Smrg
161eaef79e5Smrg#define DrawHotSpot(BW, x, y)\
162eaef79e5Smrg  XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\
163eaef79e5Smrg	       HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
164eaef79e5Smrg
165eaef79e5Smrg#define HighlightHotSpot(BW, x, y)\
166eaef79e5Smrg  XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\
167eaef79e5Smrg	       HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
168eaef79e5Smrg
169eaef79e5Smrg/*
170eaef79e5SmrgXImage *CreateBitmapImage();
171eaef79e5Smrgvoid DestroyBitmapImage();
172eaef79e5Smrg*/
173eaef79e5Smrg
174eaef79e5Smrgvoid
175eaef79e5SmrgBWRedrawHotSpot(Widget w)
176eaef79e5Smrg{
177eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
178eaef79e5Smrg
179eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
180eaef79e5Smrg	DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
181eaef79e5Smrg}
182eaef79e5Smrg
183eaef79e5Smrgvoid
184eaef79e5SmrgBWClearHotSpot(Widget w)
185eaef79e5Smrg{
186eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
187eaef79e5Smrg
188eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
189eaef79e5Smrg      DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
190eaef79e5Smrg      BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet;
191eaef79e5Smrg    }
192eaef79e5Smrg}
193eaef79e5Smrg
194eaef79e5Smrgvoid
195eaef79e5SmrgBWDrawHotSpot(Widget w, Position x, Position y, int value)
196eaef79e5Smrg{
197eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
198eaef79e5Smrg
199eaef79e5Smrg    if (QueryInBitmap(BW, x, y)) {
200eaef79e5Smrg	if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) &&
201eaef79e5Smrg	    ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) {
202eaef79e5Smrg	    if ((value == Clear) || (value == Invert)) {
203eaef79e5Smrg		BWClearHotSpot(w);
204eaef79e5Smrg	    }
205eaef79e5Smrg	}
206eaef79e5Smrg	else
207eaef79e5Smrg	    if ((value == Set) || (value == Invert)) {
208eaef79e5Smrg		BWClearHotSpot(w);
209eaef79e5Smrg		DrawHotSpot(BW, x, y);
210eaef79e5Smrg		BW->bitmap.hot.x = x;
211eaef79e5Smrg		BW->bitmap.hot.y = y;
212eaef79e5Smrg	    }
213eaef79e5Smrg
214eaef79e5Smrg	if (value == Highlight)
215eaef79e5Smrg	    HighlightHotSpot(BW, x, y);
216eaef79e5Smrg    }
217eaef79e5Smrg}
218eaef79e5Smrg
219eaef79e5Smrgvoid
220eaef79e5SmrgBWSetHotSpot(Widget w, Position x, Position y)
221eaef79e5Smrg{
222eaef79e5Smrg    if (QuerySet(x, y))
223eaef79e5Smrg	BWDrawHotSpot(w, x, y, Set);
224eaef79e5Smrg    else
225eaef79e5Smrg	BWClearHotSpot(w);
226eaef79e5Smrg}
227eaef79e5Smrg
228eaef79e5Smrg/* high level procedures */
229eaef79e5Smrg
230eaef79e5Smrgvoid
231eaef79e5SmrgBWRedrawSquares(Widget w,
232eaef79e5Smrg		Position x, Position y,
233eaef79e5Smrg		Dimension width, Dimension height)
234eaef79e5Smrg{
235eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
236eaef79e5Smrg    Position from_x = InBitmapX(BW, x);
237eaef79e5Smrg    Position from_y = InBitmapY(BW, y);
238eaef79e5Smrg    Position to_x = InBitmapX(BW, x + width);
239eaef79e5Smrg    Position to_y = InBitmapY(BW, y + height);
240eaef79e5Smrg
241eaef79e5Smrg    QuerySwap(from_x, to_x);
242eaef79e5Smrg    QuerySwap(from_y, to_y);
243eaef79e5Smrg    from_x = max(0, from_x);
244eaef79e5Smrg    from_y = max(0, from_y);
245eaef79e5Smrg    to_x = min(BW->bitmap.image->width - 1, to_x);
246eaef79e5Smrg    to_y = min(BW->bitmap.image->height - 1, to_y);
247eaef79e5Smrg
248eaef79e5Smrg    for (x = from_x; x <= to_x; x++)
249eaef79e5Smrg	for (y = from_y; y <= to_y; y++)
250eaef79e5Smrg	    if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y);
251eaef79e5Smrg}
252eaef79e5Smrg
253eaef79e5Smrgvoid
254eaef79e5SmrgBWDrawGrid(Widget w,
255eaef79e5Smrg	   Position from_x, Position from_y,
256eaef79e5Smrg	   Position to_x, Position to_y)
257eaef79e5Smrg{
258eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
259eaef79e5Smrg    int i;
260eaef79e5Smrg
261eaef79e5Smrg    QuerySwap(from_x, to_x);
262eaef79e5Smrg    QuerySwap(from_y, to_y);
263eaef79e5Smrg    from_x = max(0, from_x);
264eaef79e5Smrg    from_y = max(0, from_y);
265eaef79e5Smrg    to_x = min(BW->bitmap.image->width - 1, to_x);
266eaef79e5Smrg    to_y = min(BW->bitmap.image->height - 1, to_y);
267eaef79e5Smrg
268eaef79e5Smrg    for(i = from_x + (from_x == 0); i <= to_x; i++)
269eaef79e5Smrg	XDrawLine(XtDisplay(BW), XtWindow(BW),
270eaef79e5Smrg		  BW->bitmap.frame_gc,
271eaef79e5Smrg		  InWindowX(BW, i), InWindowY(BW, from_y),
272eaef79e5Smrg		  InWindowX(BW, i), InWindowY(BW, to_y + 1));
273eaef79e5Smrg
274eaef79e5Smrg    for(i = from_y + (from_y == 0); i <= to_y; i++)
275eaef79e5Smrg	XDrawLine(XtDisplay(BW), XtWindow(BW),
276eaef79e5Smrg		  BW->bitmap.frame_gc,
277eaef79e5Smrg		  InWindowX(BW, from_x), InWindowY(BW, i),
278eaef79e5Smrg		  InWindowX(BW, to_x + 1), InWindowY(BW, i));
279eaef79e5Smrg}
280eaef79e5Smrg
281eaef79e5Smrg
282eaef79e5Smrgvoid
283eaef79e5SmrgBWRedrawGrid(Widget w,
284eaef79e5Smrg	     Position x, Position y,
285eaef79e5Smrg	     Dimension width, Dimension height)
286eaef79e5Smrg{
287eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
288eaef79e5Smrg    Position from_x = InBitmapX(BW, x);
289eaef79e5Smrg    Position from_y = InBitmapY(BW, y);
290eaef79e5Smrg    Position to_x = InBitmapX(BW, x + width);
291eaef79e5Smrg    Position to_y = InBitmapY(BW, y + height);
292eaef79e5Smrg
293eaef79e5Smrg    if (BW->bitmap.grid)
294eaef79e5Smrg	BWDrawGrid(w, from_x, from_y, to_x, to_y);
295eaef79e5Smrg}
296eaef79e5Smrg
297eaef79e5Smrgvoid
298eaef79e5SmrgBWDrawLine(Widget w,
299eaef79e5Smrg	   Position from_x, Position from_y,
300eaef79e5Smrg	   Position to_x, Position to_y, int value)
301eaef79e5Smrg{
302eaef79e5Smrg    Position i;
303eaef79e5Smrg    register double x, y;
304eaef79e5Smrg    double dx, dy, delta;
305eaef79e5Smrg
306eaef79e5Smrg    dx = to_x - from_x;
307eaef79e5Smrg    dy = to_y - from_y;
308eaef79e5Smrg    x = from_x + 0.5;
309eaef79e5Smrg    y = from_y + 0.5;
310eaef79e5Smrg    delta = max(abs(dx), abs(dy));
311eaef79e5Smrg    if (delta > 0) {
312eaef79e5Smrg	dx /= delta;
313eaef79e5Smrg	dy /= delta;
314eaef79e5Smrg	for(i = 0; i <= delta; i++) {
315eaef79e5Smrg	    BWDrawPoint(w, (Position) x, (Position) y, value);
316eaef79e5Smrg	    x += dx;
317eaef79e5Smrg	    y += dy;
318eaef79e5Smrg	}
319eaef79e5Smrg    }
320eaef79e5Smrg    else
321eaef79e5Smrg	BWDrawPoint(w, from_x, from_y, value);
322eaef79e5Smrg}
323eaef79e5Smrg
324eaef79e5Smrgvoid
325eaef79e5SmrgBWBlindLine(Widget w,
326eaef79e5Smrg	    Position from_x, Position from_y,
327eaef79e5Smrg	    Position to_x, Position to_y, int value)
328eaef79e5Smrg{
329eaef79e5Smrg    Position i;
330eaef79e5Smrg    register double x, y;
331eaef79e5Smrg    double dx, dy, delta;
332eaef79e5Smrg
333eaef79e5Smrg    dx = to_x - from_x;
334eaef79e5Smrg    dy = to_y - from_y;
335eaef79e5Smrg    x = from_x + 0.5;
336eaef79e5Smrg    y = from_y + 0.5;
337eaef79e5Smrg    delta = max(abs(dx), abs(dy));
338eaef79e5Smrg    if (delta > 0) {
339eaef79e5Smrg	dx /= delta;
340eaef79e5Smrg	dy /= delta;
341eaef79e5Smrg	x += dx;
342eaef79e5Smrg	y += dy;
343eaef79e5Smrg	for(i = 1; i <= delta; i++) {
344eaef79e5Smrg	    BWDrawPoint(w, (Position) x, (Position) y, value);
345eaef79e5Smrg	    x += dx;
346eaef79e5Smrg	    y += dy;
347eaef79e5Smrg	}
348eaef79e5Smrg    }
349eaef79e5Smrg    else
350eaef79e5Smrg	BWDrawPoint(w, from_x, from_y, value);
351eaef79e5Smrg}
352eaef79e5Smrg
353eaef79e5Smrgvoid
354eaef79e5SmrgBWDrawRectangle(Widget w,
355eaef79e5Smrg		Position from_x, Position from_y,
356eaef79e5Smrg		Position to_x, Position to_y, int value)
357eaef79e5Smrg{
358eaef79e5Smrg    register Position i;
359eaef79e5Smrg    Dimension delta, width, height;
360eaef79e5Smrg
361eaef79e5Smrg    QuerySwap(from_x, to_x);
362eaef79e5Smrg    QuerySwap(from_y, to_y);
363eaef79e5Smrg
364eaef79e5Smrg    width = to_x - from_x;
365eaef79e5Smrg    height = to_y - from_y;
366eaef79e5Smrg
367eaef79e5Smrg    delta = max(width, height);
368eaef79e5Smrg
369eaef79e5Smrg    if (!QueryZero(width, height)) {
370eaef79e5Smrg	for (i = 0; (int)i < (int)delta; i++) {
371eaef79e5Smrg	    if ((int)i < (int)width) {
372eaef79e5Smrg		BWDrawPoint(w, from_x + i, from_y, value);
373eaef79e5Smrg		BWDrawPoint(w, to_x - i, to_y, value);
374eaef79e5Smrg	    }
375eaef79e5Smrg	    if ((int)i < (int)height) {
376eaef79e5Smrg		BWDrawPoint(w, from_x, to_y - i, value);
377eaef79e5Smrg		BWDrawPoint(w, to_x, from_y + i, value);
378eaef79e5Smrg	    }
379eaef79e5Smrg	}
380eaef79e5Smrg    }
381eaef79e5Smrg    else
382eaef79e5Smrg	BWDrawLine(w,
383eaef79e5Smrg		   from_x, from_y,
384eaef79e5Smrg		   to_x, to_y, value);
385eaef79e5Smrg}
386eaef79e5Smrg
387eaef79e5Smrgvoid
388eaef79e5SmrgBWDrawFilledRectangle(Widget w,
389eaef79e5Smrg		      Position from_x, Position from_y,
390eaef79e5Smrg		      Position to_x, Position to_y, int value)
391eaef79e5Smrg{
392eaef79e5Smrg    register Position x, y;
393eaef79e5Smrg
394eaef79e5Smrg    QuerySwap(from_x, to_x);
395eaef79e5Smrg    QuerySwap(from_y, to_y);
396eaef79e5Smrg
397eaef79e5Smrg    for (x = from_x; x <= to_x; x++)
398eaef79e5Smrg	for (y = from_y; y <= to_y; y++)
399eaef79e5Smrg	    BWDrawPoint(w, x, y, value);
400eaef79e5Smrg}
401eaef79e5Smrg
402eaef79e5Smrgvoid
403eaef79e5SmrgBWDrawCircle(Widget w,
404eaef79e5Smrg	     Position origin_x, Position origin_y,
405eaef79e5Smrg	     Position point_x, Position point_y, int value)
406eaef79e5Smrg{
407eaef79e5Smrg    register Position i, delta;
408eaef79e5Smrg    Dimension dx, dy, half;
409eaef79e5Smrg    double radius;
410eaef79e5Smrg
411eaef79e5Smrg    dx = abs(point_x - origin_x);
412eaef79e5Smrg    dy = abs(point_y - origin_y);
413eaef79e5Smrg    radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
414eaef79e5Smrg    if (radius < 1.0) {
415eaef79e5Smrg	BWDrawPoint(w, origin_x, origin_y, value);
416eaef79e5Smrg    }
417eaef79e5Smrg    else {
418eaef79e5Smrg	BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value);
419eaef79e5Smrg	BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value);
420eaef79e5Smrg	BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value);
421eaef79e5Smrg	BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value);
422eaef79e5Smrg    }
423eaef79e5Smrg    half = radius / sqrt(2.0);
424eaef79e5Smrg    for(i = 1; (int)i <= (int)half; i++) {
425eaef79e5Smrg	delta = sqrt(radius * radius - i * i);
426eaef79e5Smrg	BWDrawPoint(w, origin_x - delta, origin_y - i, value);
427eaef79e5Smrg	BWDrawPoint(w, origin_x - delta, origin_y + i, value);
428eaef79e5Smrg	BWDrawPoint(w, origin_x + delta, origin_y - i, value);
429eaef79e5Smrg	BWDrawPoint(w, origin_x + delta, origin_y + i, value);
430eaef79e5Smrg	if (i != delta) {
431eaef79e5Smrg	    BWDrawPoint(w, origin_x - i, origin_y - delta, value);
432eaef79e5Smrg	    BWDrawPoint(w, origin_x - i, origin_y + delta, value);
433eaef79e5Smrg	    BWDrawPoint(w, origin_x + i, origin_y - delta, value);
434eaef79e5Smrg	    BWDrawPoint(w, origin_x + i, origin_y + delta, value);
435eaef79e5Smrg	}
436eaef79e5Smrg    }
437eaef79e5Smrg}
438eaef79e5Smrg
439eaef79e5Smrgvoid
440eaef79e5SmrgBWDrawFilledCircle(Widget w,
441eaef79e5Smrg		   Position origin_x, Position origin_y,
442eaef79e5Smrg		   Position point_x, Position point_y, int value)
443eaef79e5Smrg{
444eaef79e5Smrg    register Position i, j, delta;
445eaef79e5Smrg    Dimension dx, dy;
446eaef79e5Smrg    double radius;
447eaef79e5Smrg
448eaef79e5Smrg    dx = abs(point_x - origin_x);
449eaef79e5Smrg    dy = abs(point_y - origin_y);
450eaef79e5Smrg    radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
451eaef79e5Smrg    for(j = origin_x - (Position) floor(radius);
452eaef79e5Smrg	j <= origin_x + (Position) floor(radius); j++)
453eaef79e5Smrg	BWDrawPoint(w, j, origin_y, value);
454eaef79e5Smrg    for(i = 1; i <= (Position) floor(radius); i++) {
455eaef79e5Smrg	delta = sqrt(radius * radius - i * i);
456eaef79e5Smrg	for(j = origin_x - delta; j <= origin_x + delta; j++) {
457eaef79e5Smrg	    BWDrawPoint(w, j, origin_y - i, value);
458eaef79e5Smrg	    BWDrawPoint(w, j, origin_y + i, value);
459eaef79e5Smrg	}
460eaef79e5Smrg    }
461eaef79e5Smrg}
462eaef79e5Smrg
463eaef79e5Smrg#define QueryFlood(BW, x, y, value)\
464eaef79e5Smrg    ((GetBit(BW->bitmap.image, x, y) !=\
465eaef79e5Smrg      (value & 1)) && QueryInBitmap(BW, x, y))
466eaef79e5Smrg
467eaef79e5Smrg#define Flood(BW, x, y, value)\
468eaef79e5Smrg    {if (value == Highlight) HighlightSquare(BW, x, y);\
469eaef79e5Smrg     else InvertPoint(BW, x, y);}
470eaef79e5Smrg
471eaef79e5Smrg/*
472eaef79e5Smrgstatic void
473eaef79e5SmrgFloodLoop(BitmapWidget BW, Position x, Position y, int value)
474eaef79e5Smrg{
475eaef79e5Smrg    if (QueryFlood(BW, x, y, value)) {
476eaef79e5Smrg	Flood(BW, x, y, value);
477eaef79e5Smrg	FloodLoop(BW, x, y - 1, value);
478eaef79e5Smrg	FloodLoop(BW, x - 1, y, value);
479eaef79e5Smrg	FloodLoop(BW, x, y + 1, value);
480eaef79e5Smrg	FloodLoop(BW, x + 1, y, value);
481eaef79e5Smrg    }
482eaef79e5Smrg}
483eaef79e5Smrg*/
484eaef79e5Smrg
485eaef79e5Smrgstatic void
486eaef79e5SmrgFloodLoop(BitmapWidget BW, Position x, Position y, int value)
487eaef79e5Smrg{
488eaef79e5Smrg    Position save_x, save_y, x_left, x_right;
489eaef79e5Smrg
490eaef79e5Smrg    if (QueryFlood(BW, x, y, value))
491eaef79e5Smrg	Flood(BW, x, y, value)
492eaef79e5Smrg
493eaef79e5Smrg
494eaef79e5Smrg    save_x = x;
495eaef79e5Smrg    save_y = y;
496eaef79e5Smrg
497eaef79e5Smrg    x++;
498eaef79e5Smrg    while (QueryFlood(BW, x, y, value)) {
499eaef79e5Smrg	Flood(BW, x, y, value);
500eaef79e5Smrg	x++;
501eaef79e5Smrg    }
502eaef79e5Smrg    x_right = --x;
503eaef79e5Smrg
504eaef79e5Smrg    x = save_x;
505eaef79e5Smrg    x--;
506eaef79e5Smrg    while (QueryFlood(BW, x, y, value)) {
507eaef79e5Smrg	Flood(BW, x, y, value);
508eaef79e5Smrg	x--;
509eaef79e5Smrg    }
510eaef79e5Smrg    x_left = ++x;
511eaef79e5Smrg
512eaef79e5Smrg
513eaef79e5Smrg    x = x_left;
514eaef79e5Smrg    y = save_y;
515eaef79e5Smrg    y++;
516eaef79e5Smrg
517eaef79e5Smrg    while (x <= x_right) {
518eaef79e5Smrg	Boolean flag = False;
519eaef79e5Smrg	Position x_enter;
520eaef79e5Smrg
521eaef79e5Smrg	while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
522eaef79e5Smrg	    flag = True;
523eaef79e5Smrg	    x++;
524eaef79e5Smrg	}
525eaef79e5Smrg
526eaef79e5Smrg	if (flag) {
527eaef79e5Smrg	    if ((x == x_right) && QueryFlood(BW, x, y, value))
528eaef79e5Smrg		FloodLoop(BW, x, y, value);
529eaef79e5Smrg	    else
530eaef79e5Smrg		FloodLoop(BW, x - 1, y, value);
531eaef79e5Smrg	}
532eaef79e5Smrg
533eaef79e5Smrg	x_enter = x;
534eaef79e5Smrg
535eaef79e5Smrg	while (!QueryFlood(BW, x, y, value) && (x < x_right))
536eaef79e5Smrg	    x++;
537eaef79e5Smrg
538eaef79e5Smrg	if (x == x_enter) x++;
539eaef79e5Smrg    }
540eaef79e5Smrg
541eaef79e5Smrg    x = x_left;
542eaef79e5Smrg    y = save_y;
543eaef79e5Smrg    y--;
544eaef79e5Smrg
545eaef79e5Smrg    while (x <= x_right) {
546eaef79e5Smrg	Boolean flag = False;
547eaef79e5Smrg	Position x_enter;
548eaef79e5Smrg
549eaef79e5Smrg	while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
550eaef79e5Smrg	    flag = True;
551eaef79e5Smrg	    x++;
552eaef79e5Smrg	}
553eaef79e5Smrg
554eaef79e5Smrg	if (flag) {
555eaef79e5Smrg	    if ((x == x_right) && QueryFlood(BW, x, y, value))
556eaef79e5Smrg		FloodLoop(BW, x, y, value);
557eaef79e5Smrg	    else
558eaef79e5Smrg		FloodLoop(BW, x - 1, y, value);
559eaef79e5Smrg	}
560eaef79e5Smrg
561eaef79e5Smrg	x_enter = x;
562eaef79e5Smrg
563eaef79e5Smrg	while (!QueryFlood(BW, x, y, value) && (x < x_right))
564eaef79e5Smrg	    x++;
565eaef79e5Smrg
566eaef79e5Smrg	if (x == x_enter) x++;
567eaef79e5Smrg    }
568eaef79e5Smrg}
569eaef79e5Smrg
570eaef79e5Smrgvoid
571eaef79e5SmrgBWFloodFill(Widget w, Position x, Position y, int value)
572eaef79e5Smrg{
573eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
574eaef79e5Smrg    int pixel;
575eaef79e5Smrg
576eaef79e5Smrg    pixel = GetBit(BW->bitmap.image, x, y);
577eaef79e5Smrg
578eaef79e5Smrg    if (value == Invert)
579eaef79e5Smrg	FloodLoop(BW, x, y, (pixel ? Clear : Set));
580eaef79e5Smrg    else if (value != pixel)
581eaef79e5Smrg	FloodLoop(BW, x, y, value);
582eaef79e5Smrg}
583eaef79e5Smrg
584eaef79e5Smrg#define QueryHotInMark(BW)\
585eaef79e5Smrg    ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\
586eaef79e5Smrg			      min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\
587eaef79e5Smrg     &&\
588eaef79e5Smrg     (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\
589eaef79e5Smrg			      min(BW->bitmap.hot.y, BW->bitmap.mark.to_y))))
590eaef79e5Smrg
591eaef79e5Smrgvoid
592eaef79e5SmrgBWUp(Widget w)
593eaef79e5Smrg{
594eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
595eaef79e5Smrg    register Position x, y;
596eaef79e5Smrg    bit first, up, down=0;
597eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
598eaef79e5Smrg
599eaef79e5Smrg    if (BWQueryMarked(w)) {
600eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
601eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
602eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
603eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
604eaef79e5Smrg    }
605eaef79e5Smrg    else {
606eaef79e5Smrg	from_x = 0;
607eaef79e5Smrg	from_y = 0;
608eaef79e5Smrg	to_x = BW->bitmap.width - 1;
609eaef79e5Smrg	to_y = BW->bitmap.height - 1;
610eaef79e5Smrg    }
611eaef79e5Smrg
612eaef79e5Smrg    if ((to_y - from_y) == 0)
613eaef79e5Smrg	return;
614eaef79e5Smrg
615eaef79e5Smrg    for(x = from_x; x <= to_x; x++) {
616eaef79e5Smrg	first = up = GetBit(BW->bitmap.image, x, to_y);
617eaef79e5Smrg	for(y = to_y - 1; y >= from_y; y--) {
618eaef79e5Smrg	    down = GetBit(BW->bitmap.image, x, y);
619eaef79e5Smrg	    if (up != down)
620eaef79e5Smrg		InvertPoint(BW, x, y);
621eaef79e5Smrg	    up =down;
622eaef79e5Smrg	}
623eaef79e5Smrg	if(first != down)
624eaef79e5Smrg	    InvertPoint(BW, x, to_y);
625eaef79e5Smrg    }
626eaef79e5Smrg
627eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
628eaef79e5Smrg	&&
629eaef79e5Smrg	!BWQueryMarked(w))
630eaef79e5Smrg	BWSetHotSpot(w,
631eaef79e5Smrg		     BW->bitmap.hot.x,
632eaef79e5Smrg		     (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) %
633eaef79e5Smrg		     BW->bitmap.image->height);
634eaef79e5Smrg
635eaef79e5Smrg}
636eaef79e5Smrg
637eaef79e5Smrgvoid
638eaef79e5SmrgBWDown(Widget w)
639eaef79e5Smrg{
640eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
641eaef79e5Smrg    register Position x, y;
642eaef79e5Smrg    bit first, down, up=0;
643eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
644eaef79e5Smrg
645eaef79e5Smrg    if (BWQueryMarked(w)) {
646eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
647eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
648eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
649eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
650eaef79e5Smrg    }
651eaef79e5Smrg    else {
652eaef79e5Smrg	from_x = 0;
653eaef79e5Smrg	from_y = 0;
654eaef79e5Smrg	to_x = BW->bitmap.width - 1;
655eaef79e5Smrg	to_y = BW->bitmap.height - 1;
656eaef79e5Smrg    }
657eaef79e5Smrg
658eaef79e5Smrg    if ((to_y - from_y) == 0)
659eaef79e5Smrg	return;
660eaef79e5Smrg
661eaef79e5Smrg    for(x = from_x; x <= to_x; x++) {
662eaef79e5Smrg	first = down = GetBit(BW->bitmap.image, x, from_y);
663eaef79e5Smrg	for(y = from_y + 1; y <= to_y; y++) {
664eaef79e5Smrg	    up = GetBit(BW->bitmap.image, x, y);
665eaef79e5Smrg	    if (down != up)
666eaef79e5Smrg		InvertPoint(BW, x, y);
667eaef79e5Smrg	    down = up;
668eaef79e5Smrg	}
669eaef79e5Smrg	if(first != up)
670eaef79e5Smrg	    InvertPoint(BW, x, from_y);
671eaef79e5Smrg    }
672eaef79e5Smrg
673eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
674eaef79e5Smrg	&&
675eaef79e5Smrg	!BWQueryMarked(w))
676eaef79e5Smrg	BWSetHotSpot(w,
677eaef79e5Smrg		     BW->bitmap.hot.x,
678eaef79e5Smrg		     (BW->bitmap.hot.y + 1) % BW->bitmap.image->height);
679eaef79e5Smrg}
680eaef79e5Smrg
681eaef79e5Smrgvoid
682eaef79e5SmrgBWLeft(Widget w)
683eaef79e5Smrg{
684eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
685eaef79e5Smrg    register Position x, y;
686eaef79e5Smrg    bit first, left, right=0;
687eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
688eaef79e5Smrg
689eaef79e5Smrg    if (BWQueryMarked(w)) {
690eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
691eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
692eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
693eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
694eaef79e5Smrg    }
695eaef79e5Smrg    else {
696eaef79e5Smrg	from_x = 0;
697eaef79e5Smrg	from_y = 0;
698eaef79e5Smrg	to_x = BW->bitmap.width - 1;
699eaef79e5Smrg	to_y = BW->bitmap.height - 1;
700eaef79e5Smrg    }
701eaef79e5Smrg
702eaef79e5Smrg    if ((to_x - from_x) == 0)
703eaef79e5Smrg	return;
704eaef79e5Smrg
705eaef79e5Smrg    for(y = from_y; y <= to_y; y++) {
706eaef79e5Smrg	first = left = GetBit(BW->bitmap.image, to_x, y);
707eaef79e5Smrg	for(x = to_x - 1; x >= from_x; x--) {
708eaef79e5Smrg	    right = GetBit(BW->bitmap.image, x, y);
709eaef79e5Smrg	    if (left != right)
710eaef79e5Smrg		InvertPoint(BW, x, y);
711eaef79e5Smrg	    left = right;
712eaef79e5Smrg	}
713eaef79e5Smrg	if(first != right)
714eaef79e5Smrg	    InvertPoint(BW, to_x, y);
715eaef79e5Smrg    }
716eaef79e5Smrg
717eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
718eaef79e5Smrg	&&
719eaef79e5Smrg	!BWQueryMarked(w))
720eaef79e5Smrg	BWSetHotSpot(w,
721eaef79e5Smrg		     (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) %
722eaef79e5Smrg		     BW->bitmap.image->width,
723eaef79e5Smrg		     BW->bitmap.hot.y);
724eaef79e5Smrg}
725eaef79e5Smrg
726eaef79e5Smrgvoid
727eaef79e5SmrgBWRight(Widget w)
728eaef79e5Smrg{
729eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
730eaef79e5Smrg    register Position x, y;
731eaef79e5Smrg    bit first, right, left=0;
732eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
733eaef79e5Smrg
734eaef79e5Smrg    if (BWQueryMarked(w)) {
735eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
736eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
737eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
738eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
739eaef79e5Smrg    }
740eaef79e5Smrg    else {
741eaef79e5Smrg	from_x = 0;
742eaef79e5Smrg	from_y = 0;
743eaef79e5Smrg	to_x = BW->bitmap.width - 1;
744eaef79e5Smrg	to_y = BW->bitmap.height - 1;
745eaef79e5Smrg    }
746eaef79e5Smrg
747eaef79e5Smrg    if ((to_x - from_x) == 0)
748eaef79e5Smrg	return;
749eaef79e5Smrg
750eaef79e5Smrg    for(y = from_y; y <= to_y; y++) {
751eaef79e5Smrg	first = right = GetBit(BW->bitmap.image, from_x, y);
752eaef79e5Smrg	for(x = from_x + 1; x <= to_x; x++) {
753eaef79e5Smrg	    left = GetBit(BW->bitmap.image, x, y);
754eaef79e5Smrg	    if (right != left)
755eaef79e5Smrg		InvertPoint(BW, x, y);
756eaef79e5Smrg	    right = left;
757eaef79e5Smrg	}
758eaef79e5Smrg	if(first != left)
759eaef79e5Smrg	    InvertPoint(BW, from_x, y);
760eaef79e5Smrg    }
761eaef79e5Smrg
762eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
763eaef79e5Smrg	&&
764eaef79e5Smrg	!BWQueryMarked(w))
765eaef79e5Smrg	BWSetHotSpot(w,
766eaef79e5Smrg		     (BW->bitmap.hot.x + 1) % BW->bitmap.image->width,
767eaef79e5Smrg		     BW->bitmap.hot.y);
768eaef79e5Smrg}
769eaef79e5Smrg
770eaef79e5Smrg/* void TransferImageData(); */
771eaef79e5Smrg
772eaef79e5Smrgvoid
773eaef79e5SmrgBWFold(Widget w)
774eaef79e5Smrg{
775eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
776eaef79e5Smrg    Position x, y, new_x, new_y;
777eaef79e5Smrg    Dimension horiz, vert;
778eaef79e5Smrg    char *storage_data;
779eaef79e5Smrg    XImage *storage;
780eaef79e5Smrg
781eaef79e5Smrg    storage_data = CreateCleanData(Length(BW->bitmap.image->width,
782eaef79e5Smrg					  BW->bitmap.image->height));
783eaef79e5Smrg
784eaef79e5Smrg    storage = CreateBitmapImage(BW, storage_data,
785eaef79e5Smrg				(Dimension) BW->bitmap.image->width,
786eaef79e5Smrg				(Dimension) BW->bitmap.image->height);
787eaef79e5Smrg
788eaef79e5Smrg    TransferImageData(BW->bitmap.image, storage);
789eaef79e5Smrg
790eaef79e5Smrg    BW->bitmap.fold ^= True;
791eaef79e5Smrg    horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2;
792eaef79e5Smrg    vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2;
793eaef79e5Smrg
794eaef79e5Smrg    for (x = 0; x < BW->bitmap.image->width; x++)
795eaef79e5Smrg	for (y = 0; y < BW->bitmap.image->height; y++) {
796eaef79e5Smrg	    new_x = (int)(x + horiz) % (int)BW->bitmap.image->width;
797eaef79e5Smrg	    new_y = (int)(y + vert) % (int)BW->bitmap.image->height;
798eaef79e5Smrg	    if(GetBit(BW->bitmap.image, new_x, new_y) !=
799eaef79e5Smrg	       GetBit(storage, x, y))
800eaef79e5Smrg		InvertPoint(BW, new_x, new_y);
801eaef79e5Smrg	}
802eaef79e5Smrg
803eaef79e5Smrg    DestroyBitmapImage(&storage);
804eaef79e5Smrg
805eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
806eaef79e5Smrg      BWSetHotSpot(w,
807eaef79e5Smrg		   (Position)
808eaef79e5Smrg		   ((int)(BW->bitmap.hot.x+horiz)
809eaef79e5Smrg		    %(int)BW->bitmap.image->width),
810eaef79e5Smrg		   (Position)
811eaef79e5Smrg		   ((int)(BW->bitmap.hot.y+vert)
812eaef79e5Smrg		    %(int)BW->bitmap.image->height)
813eaef79e5Smrg		   );
814eaef79e5Smrg}
815eaef79e5Smrg
816eaef79e5Smrg
817eaef79e5Smrgvoid
818eaef79e5SmrgBWClear(Widget w)
819eaef79e5Smrg{
820eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
821eaef79e5Smrg    register Position x, y;
822eaef79e5Smrg    int i, length;
823eaef79e5Smrg
824eaef79e5Smrg    length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
825eaef79e5Smrg
826eaef79e5Smrg    for (x = 0; x < BW->bitmap.image->width; x++)
827eaef79e5Smrg	for (y = 0; y < BW->bitmap.image->height; y++)
828eaef79e5Smrg	    if (GetBit(BW->bitmap.image, x, y))
829eaef79e5Smrg		DrawSquare(BW, x, y);
830eaef79e5Smrg
831eaef79e5Smrg    for (i = 0; i < length; i++)
832eaef79e5Smrg	BW->bitmap.image->data[i] = 0;
833eaef79e5Smrg
834eaef79e5Smrg}
835eaef79e5Smrg
836eaef79e5Smrgvoid
837eaef79e5SmrgBWSet(Widget w)
838eaef79e5Smrg{
839eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
840eaef79e5Smrg    register Position x, y;
841eaef79e5Smrg    int i, length;
842eaef79e5Smrg
843eaef79e5Smrg    length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
844eaef79e5Smrg
845eaef79e5Smrg    for (x = 0; x < BW->bitmap.image->width; x++)
846eaef79e5Smrg	for (y = 0; y < BW->bitmap.image->height; y++)
847eaef79e5Smrg	    if (!GetBit(BW->bitmap.image, x, y))
848eaef79e5Smrg		DrawSquare(BW, x, y);
849eaef79e5Smrg
850eaef79e5Smrg    for (i = 0; i < length; i++)
851eaef79e5Smrg	BW->bitmap.image->data[i] = (char)255;
852eaef79e5Smrg
853eaef79e5Smrg}
854eaef79e5Smrg
855eaef79e5Smrgvoid
856eaef79e5SmrgBWRedraw(Widget w)
857eaef79e5Smrg{
858eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
859eaef79e5Smrg
860eaef79e5Smrg    XClearArea(XtDisplay(BW), XtWindow(BW),
861eaef79e5Smrg	       0, 0, BW->core.width, BW->core.height,
862eaef79e5Smrg	       True);
863eaef79e5Smrg}
864eaef79e5Smrg
865eaef79e5Smrgvoid
866eaef79e5SmrgBWInvert(Widget w)
867eaef79e5Smrg{
868eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
869eaef79e5Smrg    int i, length;
870eaef79e5Smrg
871eaef79e5Smrg    length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
872eaef79e5Smrg
873eaef79e5Smrg    XFillRectangle(XtDisplay(BW), XtWindow(BW),
874eaef79e5Smrg		   BW->bitmap.drawing_gc,
875eaef79e5Smrg		   InWindowX(BW, 0), InWindowY(BW, 0),
876eaef79e5Smrg		   InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0),
877eaef79e5Smrg		   InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0));
878eaef79e5Smrg
879eaef79e5Smrg    for (i = 0; i < length; i++)
880eaef79e5Smrg	BW->bitmap.image->data[i] ^= 255;
881eaef79e5Smrg}
882eaef79e5Smrg
883eaef79e5Smrgvoid
884eaef79e5SmrgBWFlipHoriz(Widget w)
885eaef79e5Smrg{
886eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
887eaef79e5Smrg    register Position x, y;
888eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
889eaef79e5Smrg    float half;
890eaef79e5Smrg
891eaef79e5Smrg    if (BWQueryMarked(w)) {
892eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
893eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
894eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
895eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
896eaef79e5Smrg    }
897eaef79e5Smrg    else {
898eaef79e5Smrg	from_x = 0;
899eaef79e5Smrg	from_y = 0;
900eaef79e5Smrg	to_x = BW->bitmap.width - 1;
901eaef79e5Smrg	to_y = BW->bitmap.height - 1;
902eaef79e5Smrg    }
903eaef79e5Smrg    half = (float) (to_y - from_y) / 2.0 + 0.5;
904eaef79e5Smrg
905eaef79e5Smrg    if (half == 0.0)
906eaef79e5Smrg	return;
907eaef79e5Smrg
908eaef79e5Smrg    for (x = from_x; x <= to_x; x++)
909eaef79e5Smrg	for (y = 0; y <  half; y++)
910eaef79e5Smrg	    if (GetBit(BW->bitmap.image, x, from_y + y) !=
911eaef79e5Smrg		GetBit(BW->bitmap.image, x, to_y - y)) {
912eaef79e5Smrg		InvertPoint(BW, x, from_y + y);
913eaef79e5Smrg		InvertPoint(BW, x, to_y - y);
914eaef79e5Smrg	    }
915eaef79e5Smrg
916eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
917eaef79e5Smrg	&&
918eaef79e5Smrg	!BWQueryMarked(w))
919eaef79e5Smrg	BWSetHotSpot(w,
920eaef79e5Smrg		     BW->bitmap.hot.x,
921eaef79e5Smrg		     BW->bitmap.image->height - 1 - BW->bitmap.hot.y);
922eaef79e5Smrg}
923eaef79e5Smrg
924eaef79e5Smrgvoid
925eaef79e5SmrgBWFlipVert(Widget w)
926eaef79e5Smrg{
927eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
928eaef79e5Smrg    register Position x, y;
929eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
930eaef79e5Smrg    float half;
931eaef79e5Smrg
932eaef79e5Smrg    if (BWQueryMarked(w)) {
933eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
934eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
935eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
936eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
937eaef79e5Smrg    }
938eaef79e5Smrg    else {
939eaef79e5Smrg	from_x = 0;
940eaef79e5Smrg	from_y = 0;
941eaef79e5Smrg	to_x = BW->bitmap.width - 1;
942eaef79e5Smrg	to_y = BW->bitmap.height - 1;
943eaef79e5Smrg    }
944eaef79e5Smrg    half = (float) (to_x - from_x) / 2.0 + 0.5;
945eaef79e5Smrg
946eaef79e5Smrg    if (half == 0)
947eaef79e5Smrg	return;
948eaef79e5Smrg
949eaef79e5Smrg    for (y = from_y; y <= to_y; y++)
950eaef79e5Smrg	for (x = 0; x < half; x++)
951eaef79e5Smrg	    if (GetBit(BW->bitmap.image, from_x + x, y) !=
952eaef79e5Smrg		GetBit(BW->bitmap.image, to_x - x, y)) {
953eaef79e5Smrg		InvertPoint(BW, from_x + x, y);
954eaef79e5Smrg		InvertPoint(BW, to_x - x, y);
955eaef79e5Smrg	    }
956eaef79e5Smrg
957eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
958eaef79e5Smrg	&&
959eaef79e5Smrg	!BWQueryMarked(w))
960eaef79e5Smrg	BWSetHotSpot(w,
961eaef79e5Smrg		     BW->bitmap.image->width - 1 - BW->bitmap.hot.x,
962eaef79e5Smrg		     BW->bitmap.hot.y);
963eaef79e5Smrg}
964eaef79e5Smrg
965eaef79e5Smrg
966eaef79e5Smrgvoid
967eaef79e5SmrgBWRotateRight(Widget w)
968eaef79e5Smrg{
969eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
970eaef79e5Smrg    Position x, y, delta, shift, tmp;
971eaef79e5Smrg    Position half_width, half_height;
972eaef79e5Smrg    XPoint hot;
973eaef79e5Smrg    bit quad1, quad2, quad3, quad4;
974eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
975eaef79e5Smrg
976eaef79e5Smrg    if (BWQueryMarked(w)) {
977eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
978eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
979eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
980eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
981eaef79e5Smrg    }
982eaef79e5Smrg    else {
983eaef79e5Smrg	from_x = 0;
984eaef79e5Smrg	from_y = 0;
985eaef79e5Smrg	to_x = BW->bitmap.width - 1;
986eaef79e5Smrg	to_y = BW->bitmap.height - 1;
987eaef79e5Smrg    }
988eaef79e5Smrg
989eaef79e5Smrg    half_width = floor((to_x - from_x) / 2.0 + 0.5);
990eaef79e5Smrg    half_height = floor((to_y - from_y ) / 2.0 + 0.5);
991eaef79e5Smrg    shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
992eaef79e5Smrg    delta = min((Position) half_width, (Position) half_height) - shift;
993eaef79e5Smrg
994eaef79e5Smrg    for (x = 0; x <= delta; x++) {
995eaef79e5Smrg	for (y = 1 - shift; y <= delta; y++) {
996eaef79e5Smrg	    quad1 = GetBit(BW->bitmap.image,
997eaef79e5Smrg			   from_x + (Position)half_width + x,
998eaef79e5Smrg			   from_y + (Position)half_height + y);
999eaef79e5Smrg	    quad2 = GetBit(BW->bitmap.image,
1000eaef79e5Smrg			   from_x + (Position)half_width + y,
1001eaef79e5Smrg			   from_y + (Position)half_height - shift - x);
1002eaef79e5Smrg	    quad3 = GetBit(BW->bitmap.image,
1003eaef79e5Smrg			   from_x + (Position)half_width - shift - x,
1004eaef79e5Smrg			   from_y + (Position)half_height - shift - y);
1005eaef79e5Smrg	    quad4 = GetBit(BW->bitmap.image,
1006eaef79e5Smrg			   from_x + (Position)half_width - shift - y,
1007eaef79e5Smrg			   from_y + (Position)half_height + x);
1008eaef79e5Smrg
1009eaef79e5Smrg	    if (quad1 != quad2)
1010eaef79e5Smrg		InvertPoint(BW,
1011eaef79e5Smrg			    from_x + (Position)half_width + x,
1012eaef79e5Smrg			    from_y + (Position)half_height + y);
1013eaef79e5Smrg	    if (quad2 != quad3)
1014eaef79e5Smrg		InvertPoint(BW,
1015eaef79e5Smrg			    from_x + (Position)half_width + y,
1016eaef79e5Smrg			    from_y + (Position)half_height - shift - x);
1017eaef79e5Smrg	    if (quad3 != quad4)
1018eaef79e5Smrg		InvertPoint(BW,
1019eaef79e5Smrg			    from_x + (Position)half_width - shift - x,
1020eaef79e5Smrg			    from_y + (Position)half_height - shift - y);
1021eaef79e5Smrg	    if (quad4 != quad1)
1022eaef79e5Smrg		InvertPoint(BW,
1023eaef79e5Smrg			    from_x + (Position)half_width - shift - y,
1024eaef79e5Smrg			    from_y + (Position)half_height + x);
1025eaef79e5Smrg	}
1026eaef79e5Smrg    }
1027eaef79e5Smrg
1028eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
1029eaef79e5Smrg	&&
1030eaef79e5Smrg	!BWQueryMarked(w)) {
1031eaef79e5Smrg	hot.x = BW->bitmap.hot.x - half_width;
1032eaef79e5Smrg	hot.y = BW->bitmap.hot.y - half_height;
1033eaef79e5Smrg	if (hot.x >= 0) hot.x += shift;
1034eaef79e5Smrg	if (hot.y >= 0) hot.y += shift;
1035eaef79e5Smrg	tmp = hot.x;
1036eaef79e5Smrg	hot.x = - hot.y;
1037eaef79e5Smrg	hot.y = tmp;
1038eaef79e5Smrg	if (hot.x > 0) hot.x -= shift;
1039eaef79e5Smrg	if (hot.y > 0) hot.y -= shift;
1040eaef79e5Smrg	hot.x += half_width;
1041eaef79e5Smrg	hot.y += half_height;
1042eaef79e5Smrg	if (QueryInBitmap(BW, hot.x, hot.y))
1043eaef79e5Smrg	    BWSetHotSpot(w, hot.x, hot.y);
1044eaef79e5Smrg    }
1045eaef79e5Smrg
1046eaef79e5Smrg}
1047eaef79e5Smrg
1048eaef79e5Smrgvoid
1049eaef79e5SmrgBWRotateLeft(Widget w)
1050eaef79e5Smrg{
1051eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1052eaef79e5Smrg    Position x, y,delta, shift, tmp;
1053eaef79e5Smrg    Position half_width, half_height;
1054eaef79e5Smrg    XPoint hot;
1055eaef79e5Smrg    bit quad1, quad2, quad3, quad4;
1056eaef79e5Smrg    Position from_x, from_y, to_x, to_y;
1057eaef79e5Smrg
1058eaef79e5Smrg    if (BWQueryMarked(w)) {
1059eaef79e5Smrg	from_x = BW->bitmap.mark.from_x;
1060eaef79e5Smrg	from_y = BW->bitmap.mark.from_y;
1061eaef79e5Smrg	to_x = BW->bitmap.mark.to_x;
1062eaef79e5Smrg	to_y = BW->bitmap.mark.to_y;
1063eaef79e5Smrg    }
1064eaef79e5Smrg    else {
1065eaef79e5Smrg	from_x = 0;
1066eaef79e5Smrg	from_y = 0;
1067eaef79e5Smrg	to_x = BW->bitmap.width - 1;
1068eaef79e5Smrg	to_y = BW->bitmap.height - 1;
1069eaef79e5Smrg    }
1070eaef79e5Smrg
1071eaef79e5Smrg    half_width = floor((to_x - from_x) / 2.0 + 0.5);
1072eaef79e5Smrg    half_height = floor((to_y - from_y ) / 2.0 + 0.5);
1073eaef79e5Smrg    shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
1074eaef79e5Smrg    delta = min((Position) half_width, (Position) half_height) - shift;
1075eaef79e5Smrg
1076eaef79e5Smrg    for (x = 0; x <= delta; x++) {
1077eaef79e5Smrg	for (y = 1 - shift; y <= delta; y++) {
1078eaef79e5Smrg	    quad1 = GetBit(BW->bitmap.image,
1079eaef79e5Smrg			   from_x + (Position)half_width + x,
1080eaef79e5Smrg			   from_y + (Position)half_height + y);
1081eaef79e5Smrg	    quad2 = GetBit(BW->bitmap.image,
1082eaef79e5Smrg			   from_x + (Position)half_width + y,
1083eaef79e5Smrg			   from_y + (Position)half_height - shift - x);
1084eaef79e5Smrg	    quad3 = GetBit(BW->bitmap.image,
1085eaef79e5Smrg			   from_x + (Position)half_width - shift - x,
1086eaef79e5Smrg			   from_y + (Position)half_height - shift - y);
1087eaef79e5Smrg	    quad4 = GetBit(BW->bitmap.image,
1088eaef79e5Smrg			   from_x + (Position)half_width - shift - y,
1089eaef79e5Smrg			   from_y + (Position)half_height + x);
1090eaef79e5Smrg
1091eaef79e5Smrg	    if (quad1 != quad4)
1092eaef79e5Smrg		InvertPoint(BW,
1093eaef79e5Smrg			    from_x + (Position)half_width + x,
1094eaef79e5Smrg			    from_y + (Position)half_height + y);
1095eaef79e5Smrg	    if (quad2 != quad1)
1096eaef79e5Smrg		InvertPoint(BW,
1097eaef79e5Smrg			    from_x + (Position)half_width + y,
1098eaef79e5Smrg			    from_y + (Position)half_height - shift - x);
1099eaef79e5Smrg	    if (quad3 != quad2)
1100eaef79e5Smrg		InvertPoint(BW,
1101eaef79e5Smrg			    from_x + (Position)half_width - shift - x,
1102eaef79e5Smrg			    from_y + (Position)half_height - shift - y);
1103eaef79e5Smrg	    if (quad4 != quad3)
1104eaef79e5Smrg		InvertPoint(BW,
1105eaef79e5Smrg			    from_x + (Position)half_width - shift - y,
1106eaef79e5Smrg			    from_y + (Position)half_height + x);
1107eaef79e5Smrg	}
1108eaef79e5Smrg    }
1109eaef79e5Smrg
1110eaef79e5Smrg    if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
1111eaef79e5Smrg	&&
1112eaef79e5Smrg	!BWQueryMarked(w)) {
1113eaef79e5Smrg	hot.x = BW->bitmap.hot.x - half_width;
1114eaef79e5Smrg	hot.y = BW->bitmap.hot.y - half_height;
1115eaef79e5Smrg	if (hot.x >= 0) hot.x += shift;
1116eaef79e5Smrg	if (hot.y >= 0) hot.y += shift;
1117eaef79e5Smrg	tmp = hot.x;
1118eaef79e5Smrg	hot.x = hot.y;
1119eaef79e5Smrg	hot.y = - tmp;
1120eaef79e5Smrg	if (hot.x > 0) hot.x -= shift;
1121eaef79e5Smrg	if (hot.y > 0) hot.y -= shift;
1122eaef79e5Smrg	hot.x += half_width;
1123eaef79e5Smrg	hot.y += half_height;
1124eaef79e5Smrg	if (QueryInBitmap(BW, hot.x, hot.y))
1125eaef79e5Smrg	    BWSetHotSpot(w, hot.x, hot.y);
1126eaef79e5Smrg    }
1127eaef79e5Smrg}
1128eaef79e5Smrg
1129eaef79e5Smrg
1130eaef79e5Smrgvoid
1131eaef79e5SmrgCopyImageData(XImage *source, XImage *destination,
1132eaef79e5Smrg	      Position from_x, Position from_y,
1133eaef79e5Smrg	      Position to_x, Position to_y,
1134eaef79e5Smrg	      Position at_x, Position at_y)
1135eaef79e5Smrg{
1136eaef79e5Smrg    Position x, y, delta_x, delta_y;
1137eaef79e5Smrg
1138eaef79e5Smrg    delta_x = to_x - from_x + 1;
1139eaef79e5Smrg    delta_y = to_y - from_y + 1;
1140eaef79e5Smrg
1141eaef79e5Smrg    for (x = 0; x < delta_x; x++)
1142eaef79e5Smrg	for (y = 0; y < delta_y; y++)
1143eaef79e5Smrg	    if (GetBit(source, from_x + x, from_y + y))
1144eaef79e5Smrg		SetBit(destination, at_x + x, at_y + y);
1145eaef79e5Smrg	    else
1146eaef79e5Smrg		ClearBit(destination, at_x + x, at_y + y);
1147eaef79e5Smrg}
1148eaef79e5Smrg
1149eaef79e5SmrgXImage *
1150eaef79e5SmrgConvertToBitmapImage(BitmapWidget BW, XImage *image)
1151eaef79e5Smrg{
1152eaef79e5Smrg    XImage *bitmap_image;
1153eaef79e5Smrg    char   *data;
1154eaef79e5Smrg    Position x, y;
1155eaef79e5Smrg
1156eaef79e5Smrg    data = CreateCleanData(Length(image->width, image->height));
1157eaef79e5Smrg    bitmap_image = CreateBitmapImage(BW, data,
1158eaef79e5Smrg				     (Dimension) image->width,
1159eaef79e5Smrg				     (Dimension) image->height);
1160eaef79e5Smrg
1161eaef79e5Smrg    for (x = 0; x < min(image->width, bitmap_image->width); x++)
1162eaef79e5Smrg	for (y = 0; y < min(image->height, bitmap_image->height); y++)
1163eaef79e5Smrg	    if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y))
1164eaef79e5Smrg		InvertBit(bitmap_image, x, y);
1165eaef79e5Smrg
1166eaef79e5Smrg    return bitmap_image;
1167eaef79e5Smrg}
1168eaef79e5Smrg
1169eaef79e5Smrgvoid
1170eaef79e5SmrgTransferImageData(XImage *source, XImage *destination)
1171eaef79e5Smrg{
1172eaef79e5Smrg    Position x, y;
1173eaef79e5Smrg
1174eaef79e5Smrg    for (x = 0; x < min(source->width, destination->width); x++)
1175eaef79e5Smrg	for (y = 0; y < min(source->height, destination->height); y++)
1176eaef79e5Smrg	    if (GetBit(source, x, y) != GetBit(destination, x, y))
1177eaef79e5Smrg		InvertBit(destination, x, y);
1178eaef79e5Smrg}
1179eaef79e5Smrg
1180eaef79e5Smrgvoid
1181eaef79e5SmrgBWStore(Widget w)
1182eaef79e5Smrg{
1183eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1184eaef79e5Smrg    Dimension width, height;
1185eaef79e5Smrg    char *storage_data;
1186eaef79e5Smrg
1187eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1188eaef79e5Smrg
1189eaef79e5Smrg	DestroyBitmapImage(&BW->bitmap.storage);
1190eaef79e5Smrg
1191eaef79e5Smrg	width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1192eaef79e5Smrg	height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1193eaef79e5Smrg
1194eaef79e5Smrg	storage_data = CreateCleanData(Length(width, height));
1195eaef79e5Smrg
1196eaef79e5Smrg	BW->bitmap.storage = CreateBitmapImage(BW,
1197eaef79e5Smrg					       storage_data,
1198eaef79e5Smrg					       width, height);
1199eaef79e5Smrg
1200eaef79e5Smrg	CopyImageData(BW->bitmap.image, BW->bitmap.storage,
1201eaef79e5Smrg		      BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
1202eaef79e5Smrg		      BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
1203eaef79e5Smrg		      0, 0);
1204eaef79e5Smrg    }
1205eaef79e5Smrg}
1206eaef79e5Smrg
1207eaef79e5Smrgvoid
1208eaef79e5SmrgBWClearMarked(Widget w)
1209eaef79e5Smrg{
1210eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1211eaef79e5Smrg
1212eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1213eaef79e5Smrg	BWDrawFilledRectangle(w,
1214eaef79e5Smrg			      BW->bitmap.mark.from_x,
1215eaef79e5Smrg			      BW->bitmap.mark.from_y,
1216eaef79e5Smrg			      BW->bitmap.mark.to_x,
1217eaef79e5Smrg			      BW->bitmap.mark.to_y,
1218eaef79e5Smrg			      Clear);
1219eaef79e5Smrg}
1220eaef79e5Smrg
1221eaef79e5Smrg
1222eaef79e5Smrgvoid
1223eaef79e5SmrgBWDragMarked(Widget w, Position at_x, Position at_y)
1224eaef79e5Smrg{
1225eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1226eaef79e5Smrg
1227eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1228eaef79e5Smrg	BWDrawRectangle(w,
1229eaef79e5Smrg			at_x, at_y,
1230eaef79e5Smrg			at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
1231eaef79e5Smrg			at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y,
1232eaef79e5Smrg			Highlight);
1233eaef79e5Smrg}
1234eaef79e5Smrg
1235eaef79e5Smrgvoid
1236eaef79e5SmrgBWDragStored(Widget w, Position at_x, Position at_y)
1237eaef79e5Smrg{
1238eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1239eaef79e5Smrg
1240eaef79e5Smrg    if (BW->bitmap.storage)
1241eaef79e5Smrg	BWDrawRectangle(w,
1242eaef79e5Smrg			at_x, at_y,
1243eaef79e5Smrg			at_x + BW->bitmap.storage->width - 1,
1244eaef79e5Smrg			at_y + BW->bitmap.storage->height - 1,
1245eaef79e5Smrg			Highlight);
1246eaef79e5Smrg}
1247eaef79e5Smrg
1248eaef79e5Smrgstatic void
1249eaef79e5SmrgDrawImageData(BitmapWidget BW, XImage *image,
1250eaef79e5Smrg	      Position at_x, Position at_y, int value)
1251eaef79e5Smrg{
1252eaef79e5Smrg    Position x, y;
1253eaef79e5Smrg    Boolean  C, S, I, H;
1254eaef79e5Smrg    bit      A, B;
1255eaef79e5Smrg
1256eaef79e5Smrg    C = value == Clear;
1257eaef79e5Smrg    S = value == Set;
1258eaef79e5Smrg    I = value == Invert;
1259eaef79e5Smrg    H = value == Highlight;
1260eaef79e5Smrg
1261eaef79e5Smrg    for (x = 0; x < image->width; x++)
1262eaef79e5Smrg	for (y = 0; y < image->height; y++) {
1263eaef79e5Smrg	    A = GetBit(image, x, y);
1264eaef79e5Smrg	    B = GetBit(BW->bitmap.image, at_x + x, at_y + y);
1265eaef79e5Smrg	    if ((A & C) | ((A | B) & S) | ((A ^ B) & I) | ((A | B) & H))
1266eaef79e5Smrg		value = (A & H) ? Highlight : Set;
1267eaef79e5Smrg	    else
1268eaef79e5Smrg		value = Clear;
1269eaef79e5Smrg	    BWDrawPoint((Widget) BW,
1270eaef79e5Smrg			 at_x + x, at_y + y,
1271eaef79e5Smrg			 value);
1272eaef79e5Smrg	}
1273eaef79e5Smrg}
1274eaef79e5Smrg
1275eaef79e5Smrgvoid
1276eaef79e5SmrgBWRestore(Widget w, Position at_x, Position at_y, int value)
1277eaef79e5Smrg{
1278eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1279eaef79e5Smrg
1280eaef79e5Smrg    if (BW->bitmap.storage) {
1281eaef79e5Smrg      DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value);
1282eaef79e5Smrg      /*DestroyBitmapImage(&BW->bitmap.storage);*/
1283eaef79e5Smrg    }
1284eaef79e5Smrg}
1285eaef79e5Smrg
1286eaef79e5Smrgvoid
1287eaef79e5SmrgBWCopy(Widget w, Position at_x, Position at_y, int value)
1288eaef79e5Smrg{
1289eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1290eaef79e5Smrg    XImage *storage;
1291eaef79e5Smrg    char *storage_data;
1292eaef79e5Smrg    Dimension width, height;
1293eaef79e5Smrg
1294eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1295eaef79e5Smrg
1296eaef79e5Smrg	width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1297eaef79e5Smrg	height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1298eaef79e5Smrg
1299eaef79e5Smrg	storage_data = CreateCleanData(Length(width, height));
1300eaef79e5Smrg
1301eaef79e5Smrg	storage = CreateBitmapImage(BW, storage_data, width, height);
1302eaef79e5Smrg
1303eaef79e5Smrg	CopyImageData(BW->bitmap.image, storage,
1304eaef79e5Smrg		      BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
1305eaef79e5Smrg		      BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
1306eaef79e5Smrg		      0, 0);
1307eaef79e5Smrg
1308eaef79e5Smrg	DrawImageData(BW, storage, at_x, at_y, value);
1309eaef79e5Smrg
1310eaef79e5Smrg	DestroyBitmapImage(&storage);
1311eaef79e5Smrg    }
1312eaef79e5Smrg}
1313eaef79e5Smrg
1314eaef79e5Smrg/* void BWMark(); */
1315eaef79e5Smrg
1316eaef79e5Smrgvoid
1317eaef79e5SmrgBWMove(Widget w, Position at_x, Position at_y, int value)
1318eaef79e5Smrg{
1319eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1320eaef79e5Smrg    XImage *storage;
1321eaef79e5Smrg    char *storage_data;
1322eaef79e5Smrg    Dimension width, height;
1323eaef79e5Smrg
1324eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1325eaef79e5Smrg
1326eaef79e5Smrg	width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
1327eaef79e5Smrg	height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
1328eaef79e5Smrg
1329eaef79e5Smrg	storage_data = CreateCleanData(Length(width, height));
1330eaef79e5Smrg
1331eaef79e5Smrg	storage = CreateBitmapImage(BW, storage_data, width, height);
1332eaef79e5Smrg
1333eaef79e5Smrg	CopyImageData(BW->bitmap.image, storage,
1334eaef79e5Smrg		      BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
1335eaef79e5Smrg		      BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
1336eaef79e5Smrg		      0, 0);
1337eaef79e5Smrg
1338eaef79e5Smrg	BWDrawFilledRectangle(w,
1339eaef79e5Smrg			      BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
1340eaef79e5Smrg			      BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
1341eaef79e5Smrg			      Clear);
1342eaef79e5Smrg
1343eaef79e5Smrg	DrawImageData(BW, storage, at_x, at_y, value);
1344eaef79e5Smrg
1345eaef79e5Smrg	BWMark(w, at_x, at_y,
1346eaef79e5Smrg	     at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
1347eaef79e5Smrg	     at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y);
1348eaef79e5Smrg
1349eaef79e5Smrg	DestroyBitmapImage(&storage);
1350eaef79e5Smrg    }
1351eaef79e5Smrg}
1352eaef79e5Smrg
1353eaef79e5Smrgvoid
1354eaef79e5SmrgBWRedrawMark(Widget w)
1355eaef79e5Smrg{
1356eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1357eaef79e5Smrg
1358eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
1359eaef79e5Smrg	XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1360eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1361eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y),
1362eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1363eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1364eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.to_y + 1) -
1365eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y));
1366eaef79e5Smrg}
1367eaef79e5Smrg
1368eaef79e5Smrgvoid
1369eaef79e5SmrgBWStoreToBuffer(Widget w)
1370eaef79e5Smrg{
1371eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1372eaef79e5Smrg
1373eaef79e5Smrg    memmove( BW->bitmap.buffer->data, BW->bitmap.image->data,
1374eaef79e5Smrg	  Length(BW->bitmap.image->width, BW->bitmap.image->height));
1375eaef79e5Smrg
1376eaef79e5Smrg    BW->bitmap.buffer_hot = BW->bitmap.hot;
1377eaef79e5Smrg    BW->bitmap.buffer_mark = BW->bitmap.mark;
1378eaef79e5Smrg}
1379eaef79e5Smrg
1380eaef79e5Smrgvoid
1381eaef79e5SmrgBWUnmark(Widget w)
1382eaef79e5Smrg{
1383eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1384eaef79e5Smrg
1385eaef79e5Smrg    BW->bitmap.buffer_mark = BW->bitmap.mark;
1386eaef79e5Smrg
1387eaef79e5Smrg    if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
1388eaef79e5Smrg	XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1389eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1390eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y),
1391eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1392eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1393eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.to_y + 1) -
1394eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y));
1395eaef79e5Smrg
1396eaef79e5Smrg	BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet;
1397eaef79e5Smrg	BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet;
1398eaef79e5Smrg    }
1399eaef79e5Smrg}
1400eaef79e5Smrg
1401eaef79e5Smrgvoid
1402eaef79e5SmrgBWMark(Widget w, Position from_x, Position from_y,
1403eaef79e5Smrg       Position to_x, Position to_y)
1404eaef79e5Smrg{
1405eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1406eaef79e5Smrg
1407eaef79e5Smrg    BWUnmark(w);
1408eaef79e5Smrg
1409eaef79e5Smrg    if (QuerySet(from_x, from_y)) {
1410eaef79e5Smrg	if ((from_x == to_x) && (from_y == to_y)) {
1411eaef79e5Smrg	    /*
1412eaef79e5Smrg	      BW->bitmap.mark.from_x = 0;
1413eaef79e5Smrg	      BW->bitmap.mark.from_y = 0;
1414eaef79e5Smrg	      BW->bitmap.mark.to_x = BW->bitmap.image->width - 1;
1415eaef79e5Smrg	      BW->bitmap.mark.to_y = BW->bitmap.image->height - 1;
1416eaef79e5Smrg	      */
1417eaef79e5Smrg	    return;
1418eaef79e5Smrg	}
1419eaef79e5Smrg	else {
1420eaef79e5Smrg	    QuerySwap(from_x, to_x);
1421eaef79e5Smrg	    QuerySwap(from_y, to_y);
1422eaef79e5Smrg	    from_x = max(0, from_x);
1423eaef79e5Smrg	    from_y = max(0, from_y);
1424eaef79e5Smrg	    to_x = min(BW->bitmap.image->width - 1, to_x);
1425eaef79e5Smrg	    to_y = min(BW->bitmap.image->height - 1, to_y);
1426eaef79e5Smrg
1427eaef79e5Smrg	    BW->bitmap.mark.from_x = from_x;
1428eaef79e5Smrg	    BW->bitmap.mark.from_y = from_y;
1429eaef79e5Smrg	    BW->bitmap.mark.to_x = to_x;
1430eaef79e5Smrg	    BW->bitmap.mark.to_y = to_y;
1431eaef79e5Smrg	}
1432eaef79e5Smrg
1433eaef79e5Smrg	XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
1434eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1435eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y),
1436eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.to_x + 1) -
1437eaef79e5Smrg		       InWindowX(BW, BW->bitmap.mark.from_x),
1438eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.to_y +1) -
1439eaef79e5Smrg		       InWindowY(BW, BW->bitmap.mark.from_y));
1440eaef79e5Smrg    }
1441eaef79e5Smrg}
1442eaef79e5Smrg
1443eaef79e5Smrgvoid
1444eaef79e5SmrgBWMarkAll(Widget w)
1445eaef79e5Smrg{
1446eaef79e5Smrg  BitmapWidget BW = (BitmapWidget) w;
1447eaef79e5Smrg
1448eaef79e5Smrg  BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
1449eaef79e5Smrg}
1450eaef79e5Smrg
1451eaef79e5Smrgvoid
1452eaef79e5SmrgBWUndo(Widget w)
1453eaef79e5Smrg{
1454eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1455eaef79e5Smrg    Position x, y;
1456eaef79e5Smrg    char *tmp_data;
1457eaef79e5Smrg    XPoint tmp_hot;
1458eaef79e5Smrg    BWArea tmp_mark;
1459eaef79e5Smrg
1460eaef79e5Smrg    tmp_data = BW->bitmap.image->data;
1461eaef79e5Smrg    BW->bitmap.image->data = BW->bitmap.buffer->data;
1462eaef79e5Smrg    BW->bitmap.buffer->data = tmp_data;
1463eaef79e5Smrg
1464eaef79e5Smrg    tmp_hot = BW->bitmap.hot;
1465eaef79e5Smrg    tmp_mark = BW->bitmap.mark;
1466eaef79e5Smrg
1467eaef79e5Smrg    for (x = 0; x < BW->bitmap.image->width; x++)
1468eaef79e5Smrg	for (y = 0; y < BW->bitmap.image->height; y++)
1469eaef79e5Smrg	 if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y))
1470eaef79e5Smrg	     DrawSquare(BW, x, y);
1471eaef79e5Smrg
1472eaef79e5Smrg    BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y);
1473eaef79e5Smrg/*
1474eaef79e5Smrg    BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y,
1475eaef79e5Smrg	   BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y);
1476eaef79e5Smrg*/
1477eaef79e5Smrg    BW->bitmap.buffer_hot = tmp_hot;
1478eaef79e5Smrg    BW->bitmap.buffer_mark= tmp_mark;
1479eaef79e5Smrg
1480eaef79e5Smrg}
1481eaef79e5Smrg
1482eaef79e5Smrgvoid
1483eaef79e5SmrgBWHighlightAxes(Widget w)
1484eaef79e5Smrg{
1485eaef79e5Smrg    BitmapWidget BW = (BitmapWidget) w;
1486eaef79e5Smrg
1487eaef79e5Smrg    XDrawLine(XtDisplay(BW), XtWindow(BW),
1488eaef79e5Smrg	      BW->bitmap.axes_gc,
1489eaef79e5Smrg	      InWindowX(BW, 0),
1490eaef79e5Smrg	      InWindowY(BW, 0),
1491eaef79e5Smrg	      InWindowX(BW, BW->bitmap.width),
1492eaef79e5Smrg	      InWindowY(BW, BW->bitmap.height));
1493eaef79e5Smrg    XDrawLine(XtDisplay(BW), XtWindow(BW),
1494eaef79e5Smrg	      BW->bitmap.axes_gc,
1495eaef79e5Smrg	      InWindowX(BW, BW->bitmap.width),
1496eaef79e5Smrg	      InWindowY(BW, 0),
1497eaef79e5Smrg	      InWindowX(BW, 0),
1498eaef79e5Smrg	      InWindowY(BW, BW->bitmap.height));
1499eaef79e5Smrg    XDrawLine(XtDisplay(BW), XtWindow(BW),
1500eaef79e5Smrg	      BW->bitmap.axes_gc,
1501eaef79e5Smrg	      InWindowX(BW, 0),
1502eaef79e5Smrg	      InWindowY(BW, (float)BW->bitmap.height / 2.0),
1503eaef79e5Smrg	      InWindowX(BW, BW->bitmap.width),
1504eaef79e5Smrg	      InWindowY(BW, (float)BW->bitmap.height / 2.0));
1505eaef79e5Smrg    XDrawLine(XtDisplay(BW), XtWindow(BW),
1506eaef79e5Smrg	      BW->bitmap.axes_gc,
1507eaef79e5Smrg	      InWindowX(BW, (float)BW->bitmap.width / 2.0),
1508eaef79e5Smrg	      InWindowY(BW, 0),
1509eaef79e5Smrg	      InWindowX(BW, (float)BW->bitmap.width / 2.0),
1510eaef79e5Smrg	      InWindowY(BW, BW->bitmap.height));
1511eaef79e5Smrg}
1512eaef79e5Smrg
1513eaef79e5Smrgtypedef struct {
1514eaef79e5Smrg    Position *x, *y;
1515eaef79e5Smrg    Dimension *width, *height;
1516eaef79e5Smrg} Table;
1517eaef79e5Smrg
1518eaef79e5SmrgXImage *
1519eaef79e5SmrgScaleBitmapImage(BitmapWidget BW, XImage *src,
1520eaef79e5Smrg		 double scale_x, double scale_y)
1521eaef79e5Smrg{
1522eaef79e5Smrg    char *data;
1523eaef79e5Smrg    XImage *dst;
1524eaef79e5Smrg    Table table;
1525eaef79e5Smrg    Position x, y, w, h;
1526eaef79e5Smrg    Dimension width, height;
1527eaef79e5Smrg    bit pixel;
1528eaef79e5Smrg
1529eaef79e5Smrg    width = max(rint(scale_x * src->width), 1);
1530eaef79e5Smrg    height = max(rint(scale_y * src->height), 1);
1531eaef79e5Smrg
1532eaef79e5Smrg    data = CreateCleanData(Length(width, height));
1533eaef79e5Smrg    dst = CreateBitmapImage(BW, data, width, height);
1534eaef79e5Smrg
1535eaef79e5Smrg    /*
1536eaef79e5Smrg     * It would be nice to check if width or height < 1.0 and
1537eaef79e5Smrg     * average the skipped pixels. But, it is slow as it is now.
1538eaef79e5Smrg     */
1539eaef79e5Smrg    if (scale_x == 1.0 && scale_y == 1.0)
1540eaef79e5Smrg	memmove( dst->data, src->data, Length(width, height));
1541eaef79e5Smrg    else {
1542eaef79e5Smrg	table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
1543eaef79e5Smrg	table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
1544eaef79e5Smrg	table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
1545eaef79e5Smrg	table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
1546eaef79e5Smrg
1547eaef79e5Smrg	for (x = 0; x < src->width; x++) {
1548eaef79e5Smrg	    table.x[x] = rint(scale_x * x);
1549eaef79e5Smrg	    table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
1550eaef79e5Smrg	}
1551eaef79e5Smrg	for (y = 0; y < src->height; y++) {
1552eaef79e5Smrg	    table.y[y] = rint(scale_y * y);
1553eaef79e5Smrg	    table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
1554eaef79e5Smrg	}
1555eaef79e5Smrg
1556eaef79e5Smrg	for (x = 0; x < src->width; x++)
1557eaef79e5Smrg	    for (y = 0; y < src->height; y++) {
1558eaef79e5Smrg	        pixel = GetBit(src, x, y);
1559eaef79e5Smrg		for (w = 0; (int)w < (int)table.width[x]; w++)
1560eaef79e5Smrg		    for (h = 0; (int)h < (int)table.height[y]; h++)
1561eaef79e5Smrg			if (pixel) SetBit(dst,
1562eaef79e5Smrg					table.x[x] + w,
1563eaef79e5Smrg					table.y[y] + h);
1564eaef79e5Smrg	    }
1565eaef79e5Smrg
1566eaef79e5Smrg	XtFree((char *)table.x);
1567eaef79e5Smrg	XtFree((char *)table.y);
1568eaef79e5Smrg	XtFree((char *)table.width);
1569eaef79e5Smrg	XtFree((char *)table.height);
1570eaef79e5Smrg    }
1571eaef79e5Smrg
1572eaef79e5Smrg    return (dst);
1573eaef79e5Smrg}
1574eaef79e5Smrg
1575eaef79e5Smrg/*****************************************************************************/
1576