~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to lefty/ws/x11/gcanvas.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#pragma prototyped
 
2
/* Lefteris Koutsofios - AT&T Bell Laboratories */
 
3
 
 
4
#include "common.h"
 
5
#include "g.h"
 
6
#include "gcommon.h"
 
7
#include "mem.h"
 
8
#ifdef FEATURE_GMAP
 
9
#include <gmap.h>
 
10
#endif
 
11
 
 
12
#define WCU widget->u.c
 
13
#define WINDOW widget->u.c->window
 
14
#define GC widget->u.c->gc
 
15
#define ISVISIBLE(r) ( \
 
16
    (r.o.x <= WCU->clip.c.x) && (r.c.x >= WCU->clip.o.x) && \
 
17
    (r.o.y <= WCU->clip.c.y) && (r.c.y >= WCU->clip.o.y) \
 
18
)
 
19
 
 
20
#define IS8BIT(font) ((font)->min_byte1 == 0 && (font)->max_byte1 == 0)
 
21
 
 
22
static struct cursormap_t {
 
23
    Cursor id;
 
24
    char name[40];
 
25
} cursormap[XC_num_glyphs];
 
26
static int curcursori = -1;
 
27
 
 
28
#define max(a, b) (((a) >= (b)) ? (a) : (b))
 
29
#define min(a, b) (((a) <= (b)) ? (a) : (b))
 
30
 
 
31
static char gstyles[][2] = {
 
32
    /* G_SOLID */       { 16,  0, },
 
33
    /* G_DASHED */      {  4,  4, },
 
34
    /* G_DOTTED */      {  2,  2, },
 
35
    /* G_LONGDASHED */  {  4, 12, },
 
36
    /* G_SHORTDASHED */ { 12,  4, },
 
37
};
 
38
 
 
39
static char grays[][4] = {
 
40
  { 0x00,0x00,0x00,0x00, },
 
41
  { 0x08,0x00,0x00,0x00, },
 
42
  { 0x08,0x00,0x02,0x00, },
 
43
  { 0x0A,0x00,0x02,0x00, },
 
44
  { 0x0A,0x00,0x0A,0x00, },
 
45
  { 0x0A,0x04,0x0A,0x00, },
 
46
  { 0x0A,0x04,0x0A,0x01, },
 
47
  { 0x0A,0x05,0x0A,0x01, },
 
48
  { 0x0A,0x05,0x0A,0x05, },
 
49
  { 0x0E,0x05,0x0A,0x05, },
 
50
  { 0x0E,0x05,0x0B,0x05, },
 
51
  { 0x0F,0x05,0x0B,0x05, },
 
52
  { 0x0F,0x05,0x0F,0x05, },
 
53
  { 0x0F,0x0D,0x0F,0x05, },
 
54
  { 0x0F,0x0D,0x0F,0x07, },
 
55
  { 0x0F,0x0F,0x0F,0x07, },
 
56
  { 0x0F,0x0F,0x0F,0x0F, },
 
57
};
 
58
 
 
59
static void bezier (PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t);
 
60
static XFontStruct *findfont (char *, int);
 
61
static int scalebitmap (Gwidget_t *, Gbitmap_t *, Gsize_t, int, int);
 
62
static void setgattr (Gwidget_t *, Ggattr_t *);
 
63
 
 
64
static PIXrect_t  rdrawtopix (Gwidget_t *, Grect_t);
 
65
static PIXpoint_t pdrawtopix (Gwidget_t *, Gpoint_t);
 
66
static PIXsize_t  sdrawtopix (Gwidget_t *, Gsize_t);
 
67
static Gpoint_t   Gppixtodraw (Gwidget_t *, PIXpoint_t);
 
68
static Gsize_t    spixtodraw (Gwidget_t *, PIXsize_t);
 
69
static Grect_t    rpixtodraw (Gwidget_t *, PIXrect_t);
 
70
static PIXrect_t  rdrawtobpix (Gbitmap_t *, Grect_t);
 
71
static PIXpoint_t pdrawtobpix (Gbitmap_t *, Gpoint_t);
 
72
static void       adjustclip (Gwidget_t *);
 
73
 
 
74
static Bool cwvpredicate (Display *, XEvent *, XPointer);
 
75
static void cweventhandler (Widget, XtPointer, XEvent *, Boolean *);
 
76
static Bool cwepredicate (Display *, XEvent *, XPointer);
 
77
 
 
78
int GCcreatewidget (Gwidget_t *parent, Gwidget_t *widget,
 
79
        int attrn, Gwattr_t *attrp) {
 
80
    PIXsize_t ps;
 
81
    Dimension width, height;
 
82
#ifdef FEATURE_BACKINGSTORE
 
83
    XSetWindowAttributes xswa;
 
84
#endif
 
85
    XEvent ev;
 
86
    XColor *cp;
 
87
    XGCValues gcv;
 
88
    int curi, color, ai, r, g, b, i;
 
89
#ifdef FEATURE_GMAP
 
90
    XVisualInfo *vip;
 
91
    int gmapmode = FALSE;
 
92
#endif
 
93
 
 
94
    if (!parent) {
 
95
        Gerr (POS, G_ERRNOPARENTWIDGET);
 
96
        return -1;
 
97
    }
 
98
    WCU->func = NULL;
 
99
    WCU->needredraw = FALSE;
 
100
    WCU->buttonsdown = 0;
 
101
    WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0;
 
102
    ps.x = ps.y = MINCWSIZE;
 
103
    RESETARGS;
 
104
    for (ai = 0; ai < attrn; ai++) {
 
105
        switch (attrp[ai].id) {
 
106
        case G_ATTRSIZE:
 
107
            GETSIZE (attrp[ai].u.s, ps, MINCWSIZE);
 
108
            break;
 
109
        case G_ATTRBORDERWIDTH:
 
110
            ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
 
111
            break;
 
112
#ifdef FEATURE_GMAP
 
113
        case G_ATTRMODE:
 
114
            if (Strcmp ("gmap", attrp[ai].u.t) == 0) {
 
115
                gmapmode = TRUE;
 
116
            } else {
 
117
                Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
 
118
                return -1;
 
119
            }
 
120
            break;
 
121
#endif
 
122
        case G_ATTRCURSOR:
 
123
            /* will do it after the widget is created */
 
124
            break;
 
125
        case G_ATTRCOLOR:
 
126
            /* will do it after the widget is created */
 
127
            break;
 
128
        case G_ATTRVIEWPORT:
 
129
            /* will do it after the widget is created */
 
130
            break;
 
131
        case G_ATTRWINDOW:
 
132
            /* will do it after the widget is created */
 
133
            break;
 
134
        case G_ATTRWINDOWID:
 
135
            Gerr (POS, G_ERRCANNOTSETATTR1, "windowid");
 
136
            return -1;
 
137
        case G_ATTREVENTCB:
 
138
            WCU->func = (Gcanvascb) attrp[ai].u.func;
 
139
            break;
 
140
        case G_ATTRUSERDATA:
 
141
            widget->udata = attrp[ai].u.u;
 
142
            break;
 
143
        default:
 
144
            Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
 
145
            return -1;
 
146
        }
 
147
    }
 
148
    ADD2ARGS (XtNwidth, ps.x);
 
149
    ADD2ARGS (XtNheight, ps.y);
 
150
#ifdef FEATURE_GMAP
 
151
    if (gmapmode) {
 
152
        vip = pfChooseFBConfig (Gdisplay, -1, NULL);
 
153
        ADD2ARGS (GLwNvisualInfo, vip);
 
154
        if (!(widget->w = XtCreateWidget ("graphics", glwDrawingAreaWidgetClass,
 
155
                parent->w, argp, argn))) {
 
156
            Gerr (POS, G_ERRCANNOTCREATEWIDGET);
 
157
            return -1;
 
158
        }
 
159
    } else {
 
160
        if (!(widget->w = XtCreateWidget ("graphics", coreWidgetClass,
 
161
                parent->w, argp, argn))) {
 
162
            Gerr (POS, G_ERRCANNOTCREATEWIDGET);
 
163
            return -1;
 
164
        }
 
165
    }
 
166
    WCU->gmapmode = gmapmode;
 
167
#else
 
168
    if (!(widget->w = XtCreateWidget ("graphics", coreWidgetClass,
 
169
            parent->w, argp, argn))) {
 
170
        Gerr (POS, G_ERRCANNOTCREATEWIDGET);
 
171
        return -1;
 
172
    }
 
173
#endif
 
174
    XtOverrideTranslations (widget->w, Gcwanytable);
 
175
    XtAddEventHandler (widget->w, VisibilityChangeMask | ExposureMask,
 
176
            FALSE, cweventhandler, (XtPointer) 0);
 
177
    Glazymanage (widget->w);
 
178
    Gflushlazyq ();
 
179
#ifdef FEATURE_BACKINGSTORE
 
180
    xswa.backing_store = WhenMapped;
 
181
    XChangeWindowAttributes (Gdisplay, XtWindow (widget->w),
 
182
            CWBackingStore, &xswa);
 
183
#endif
 
184
    /* wait for window to become visible */
 
185
    XPeekIfEvent (Gdisplay, &ev, cwvpredicate, (XPointer) XtWindow (widget->w));
 
186
    RESETARGS;
 
187
    ADD2ARGS (XtNwidth, &width);
 
188
    ADD2ARGS (XtNheight, &height);
 
189
    XtGetValues (widget->w, argp, argn);
 
190
    ps.x = width, ps.y = height;
 
191
    WCU->window = XtWindow (widget->w);
 
192
    WCU->cmap = DefaultColormap (Gdisplay, Gscreenn);
 
193
    WCU->gc = XCreateGC (Gdisplay, WCU->window, 0, NULL);
 
194
    RESETARGS;
 
195
    WCU->colors[0].color.pixel = WCU->colors[1].color.pixel = 1000000;
 
196
    ADD2ARGS (XtNbackground, &WCU->colors[0].color.pixel);
 
197
    ADD2ARGS (XtNforeground, &WCU->colors[1].color.pixel);
 
198
    XtGetValues (widget->w, argp, argn);
 
199
    if (WCU->colors[0].color.pixel == 1000000) {
 
200
        if (XGetGCValues (Gdisplay, GC, GCBackground, &gcv) != 0)
 
201
            WCU->colors[0].color.pixel = gcv.background;
 
202
        else
 
203
            WCU->colors[0].color.pixel = WhitePixel (Gdisplay, Gscreenn);
 
204
    }
 
205
    if (WCU->colors[1].color.pixel == 1000000) {
 
206
        if (XGetGCValues (Gdisplay, GC, GCForeground, &gcv) != 0)
 
207
            WCU->colors[1].color.pixel = gcv.foreground;
 
208
        else
 
209
            WCU->colors[1].color.pixel = BlackPixel (Gdisplay, Gscreenn);
 
210
    }
 
211
    XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[0].color);
 
212
    WCU->colors[0].inuse = TRUE;
 
213
    XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[1].color);
 
214
    WCU->colors[1].inuse = TRUE;
 
215
    WCU->allocedcolor[0] = WCU->allocedcolor[1] = FALSE;
 
216
    for (i = 2; i < G_MAXCOLORS; i++)
 
217
        WCU->colors[i].inuse = FALSE;
 
218
    WCU->gattr.color = 1;
 
219
    XSetBackground (Gdisplay, GC, WCU->colors[0].color.pixel);
 
220
    XSetForeground (Gdisplay, GC, WCU->colors[1].color.pixel);
 
221
    WCU->gattr.width = 0;
 
222
    WCU->gattr.mode = G_SRC;
 
223
    WCU->gattr.fill = 0;
 
224
    WCU->gattr.style = 0;
 
225
    WCU->defgattr = WCU->gattr;
 
226
    WCU->font = NULL;
 
227
    WCU->wrect.o.x = 0.0, WCU->wrect.o.y = 0.0;
 
228
    WCU->wrect.c.x = 1.0, WCU->wrect.c.y = 1.0;
 
229
    WCU->vsize.x = ps.x, WCU->vsize.y = ps.y;
 
230
    if (Gdepth == 1) {
 
231
        XSetFillStyle (Gdisplay, GC, FillTiled);
 
232
        for (i = 0; i < 17; i++)
 
233
            WCU->grays[i] = XCreatePixmapFromBitmapData (Gdisplay, WCU->window,
 
234
                    &grays[i][0], 4, 4, BlackPixel (Gdisplay, Gscreenn),
 
235
                    WhitePixel (Gdisplay, Gscreenn), 1);
 
236
    }
 
237
    for (ai = 0; ai < attrn; ai++) {
 
238
        switch (attrp[ai].id) {
 
239
        case G_ATTRCURSOR:
 
240
            if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) {
 
241
                if (Strcmp (attrp[ai].u.t, "default") == 0) {
 
242
                    XUndefineCursor (Gdisplay, XtWindow (widget->w));
 
243
                    curcursori = -1;
 
244
                } else {
 
245
                    Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t);
 
246
                    return -1;
 
247
                }
 
248
            } else {
 
249
                if (!cursormap[curi].id) {
 
250
                    cursormap[curi].id = XCreateFontCursor (Gdisplay, curi);
 
251
                    strcpy (cursormap[curi].name, attrp[ai].u.t);
 
252
                }
 
253
                XDefineCursor (Gdisplay, XtWindow (widget->w),
 
254
                        cursormap[curi].id);
 
255
                curcursori = curi;
 
256
            }
 
257
            break;
 
258
        case G_ATTRCOLOR:
 
259
            color = attrp[ai].u.c.index;
 
260
            if (color < 0 || color > G_MAXCOLORS) {
 
261
                Gerr (POS, G_ERRBADCOLORINDEX, color);
 
262
                return -1;
 
263
            }
 
264
            r = attrp[ai].u.c.r * 257;
 
265
            g = attrp[ai].u.c.g * 257;
 
266
            b = attrp[ai].u.c.b * 257;
 
267
            cp = &WCU->colors[color].color;
 
268
            if (WCU->colors[color].inuse)
 
269
                if (cp->red != r || cp->green != g || cp->blue != b)
 
270
                     if (color > 1 || WCU->allocedcolor[color])
 
271
                         XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0);
 
272
            cp->red = r, cp->green = g, cp->blue = b;
 
273
            if (XAllocColor (Gdisplay, WCU->cmap, cp)) {
 
274
                WCU->colors[color].inuse = TRUE;
 
275
                if (color <= 1)
 
276
                    WCU->allocedcolor[color] = TRUE;
 
277
            }
 
278
            /* XAllocColor may change the rgb values */
 
279
            cp->red = r, cp->green = g, cp->blue = b;
 
280
            if (color == WCU->gattr.color)
 
281
                WCU->gattr.color = -1;
 
282
            if (color == 0 || color == 1) {
 
283
                RESETARGS;
 
284
                if (color == 0)
 
285
                    ADD2ARGS (XtNbackground, cp->pixel);
 
286
                else
 
287
                    ADD2ARGS (XtNforeground, cp->pixel);
 
288
                XtSetValues (widget->w, argp, argn);
 
289
            }
 
290
            break;
 
291
        case G_ATTRVIEWPORT:
 
292
            WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);
 
293
            WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);
 
294
            RESETARGS;
 
295
            ADD2ARGS (XtNwidth, WCU->vsize.x);
 
296
            ADD2ARGS (XtNheight, WCU->vsize.y);
 
297
            XtSetValues (widget->w, argp, argn);
 
298
            break;
 
299
        case G_ATTRWINDOW:
 
300
            WCU->wrect = attrp[ai].u.r;
 
301
            break;
 
302
        }
 
303
    }
 
304
    adjustclip (widget);
 
305
    return 0;
 
306
}
 
307
 
 
308
int GCsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
 
309
    PIXsize_t ps;
 
310
    XColor *cp;
 
311
    int curi, color, ai, r, g, b;
 
312
 
 
313
    RESETARGS;
 
314
    for (ai = 0; ai < attrn; ai++) {
 
315
        switch (attrp[ai].id) {
 
316
        case G_ATTRSIZE:
 
317
            GETSIZE (attrp[ai].u.s, ps, MINCWSIZE);
 
318
            ADD2ARGS (XtNwidth, ps.x);
 
319
            ADD2ARGS (XtNheight, ps.y);
 
320
            break;
 
321
        case G_ATTRBORDERWIDTH:
 
322
            ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
 
323
            break;
 
324
        case G_ATTRCURSOR:
 
325
            if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) {
 
326
                if (Strcmp (attrp[ai].u.t, "default") == 0) {
 
327
                    XUndefineCursor (Gdisplay, XtWindow (widget->w));
 
328
                    curcursori = -1;
 
329
                } else {
 
330
                    Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t);
 
331
                    return -1;
 
332
                }
 
333
            } else {
 
334
                if (!cursormap[curi].id) {
 
335
                    cursormap[curi].id = XCreateFontCursor (Gdisplay, curi);
 
336
                    strcpy (cursormap[curi].name, attrp[ai].u.t);
 
337
                }
 
338
                XDefineCursor (Gdisplay, XtWindow (widget->w),
 
339
                        cursormap[curi].id);
 
340
                curcursori = curi;
 
341
            }
 
342
            Gsync ();
 
343
            break;
 
344
        case G_ATTRCOLOR:
 
345
            color = attrp[ai].u.c.index;
 
346
            if (color < 0 || color > G_MAXCOLORS) {
 
347
                Gerr (POS, G_ERRBADCOLORINDEX, color);
 
348
                return -1;
 
349
            }
 
350
            r = attrp[ai].u.c.r * 257;
 
351
            g = attrp[ai].u.c.g * 257;
 
352
            b = attrp[ai].u.c.b * 257;
 
353
            cp = &WCU->colors[color].color;
 
354
            if (WCU->colors[color].inuse)
 
355
                if (cp->red != r || cp->green != g || cp->blue != b)
 
356
                     if (color > 1 || WCU->allocedcolor[color])
 
357
                         XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0);
 
358
            cp->red = r, cp->green = g, cp->blue = b;
 
359
            if (XAllocColor (Gdisplay, WCU->cmap, cp)) {
 
360
                WCU->colors[color].inuse = TRUE;
 
361
                if (color <= 1)
 
362
                    WCU->allocedcolor[color] = TRUE;
 
363
            }
 
364
            /* XAllocColor may change the rgb values */
 
365
            cp->red = r, cp->green = g, cp->blue = b;
 
366
            if (color == WCU->gattr.color)
 
367
                WCU->gattr.color = -1;
 
368
            break;
 
369
        case G_ATTRVIEWPORT:
 
370
            WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);
 
371
            WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);
 
372
            ADD2ARGS (XtNwidth, WCU->vsize.x);
 
373
            ADD2ARGS (XtNheight, WCU->vsize.y);
 
374
            XtSetValues (widget->w, argp, argn);
 
375
            adjustclip (widget);
 
376
            RESETARGS;
 
377
            break;
 
378
        case G_ATTRWINDOW:
 
379
            WCU->wrect = attrp[ai].u.r;
 
380
            XtSetValues (widget->w, argp, argn);
 
381
            adjustclip (widget);
 
382
            RESETARGS;
 
383
            break;
 
384
        case G_ATTRWINDOWID:
 
385
            Gerr (POS, G_ERRCANNOTSETATTR2, "windowid");
 
386
            return -1;
 
387
        case G_ATTREVENTCB:
 
388
            WCU->func = (Gcanvascb) attrp[ai].u.func;
 
389
            break;
 
390
        case G_ATTRUSERDATA:
 
391
            widget->udata = attrp[ai].u.u;
 
392
            break;
 
393
        default:
 
394
            Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
 
395
            return -1;
 
396
        }
 
397
    }
 
398
    XtSetValues (widget->w, argp, argn);
 
399
    return 0;
 
400
}
 
401
 
 
402
int GCgetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
 
403
    XColor *cp;
 
404
    Dimension width, height;
 
405
    int ai, color;
 
406
 
 
407
    for (ai = 0; ai < attrn; ai++) {
 
408
        RESETARGS;
 
409
        switch (attrp[ai].id) {
 
410
        case G_ATTRSIZE:
 
411
            ADD2ARGS (XtNwidth, &width);
 
412
            ADD2ARGS (XtNheight, &height);
 
413
            XtGetValues (widget->w, argp, argn);
 
414
            attrp[ai].u.s.x = width, attrp[ai].u.s.y = height;
 
415
            break;
 
416
        case G_ATTRBORDERWIDTH:
 
417
            ADD2ARGS (XtNborderWidth, &width);
 
418
            XtGetValues (widget->w, argp, argn);
 
419
            attrp[ai].u.i = width;
 
420
            break;
 
421
        case G_ATTRCURSOR:
 
422
            attrp[ai].u.t = (curcursori == -1) ?
 
423
                    "default" : cursormap[curcursori].name;
 
424
            break;
 
425
        case G_ATTRCOLOR:
 
426
            color = attrp[ai].u.c.index;
 
427
            if (color < 0 || color > G_MAXCOLORS) {
 
428
                Gerr (POS, G_ERRBADCOLORINDEX, color);
 
429
                return -1;
 
430
            }
 
431
            if (WCU->colors[color].inuse) {
 
432
                cp = &WCU->colors[color].color;
 
433
                attrp[ai].u.c.r = cp->red / 257.0;
 
434
                attrp[ai].u.c.g = cp->green / 257.0;
 
435
                attrp[ai].u.c.b = cp->blue / 257.0;
 
436
            } else {
 
437
                attrp[ai].u.c.r = -1;
 
438
                attrp[ai].u.c.g = -1;
 
439
                attrp[ai].u.c.b = -1;
 
440
            }
 
441
            break;
 
442
        case G_ATTRVIEWPORT:
 
443
            attrp[ai].u.s = WCU->vsize;
 
444
            break;
 
445
        case G_ATTRWINDOW:
 
446
            attrp[ai].u.r = WCU->wrect;
 
447
            break;
 
448
        case G_ATTRWINDOWID:
 
449
            sprintf (&Gbufp[0], "0x%lx", XtWindow (widget->w));
 
450
            attrp[ai].u.t = &Gbufp[0];
 
451
            break;
 
452
        case G_ATTREVENTCB:
 
453
            attrp[ai].u.func = WCU->func;
 
454
            break;
 
455
        case G_ATTRUSERDATA:
 
456
            attrp[ai].u.u = widget->udata;
 
457
            break;
 
458
        default:
 
459
            Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
 
460
            return -1;
 
461
        }
 
462
    }
 
463
    return 0;
 
464
}
 
465
 
 
466
int GCdestroywidget (Gwidget_t *widget) {
 
467
    XtDestroyWidget (widget->w);
 
468
    return 0;
 
469
}
 
470
 
 
471
int GCcanvasclear (Gwidget_t *widget) {
 
472
    XEvent ev;
 
473
    int gotit;
 
474
 
 
475
    XClearWindow (Gdisplay, WINDOW);
 
476
    /* avoid a redraw */
 
477
    WCU->needredraw = FALSE;
 
478
    XSync (Gdisplay, False);
 
479
    gotit = FALSE;
 
480
    while (XCheckIfEvent (Gdisplay,
 
481
            &ev, cwepredicate, (XPointer) WINDOW) == True)
 
482
        gotit = TRUE;
 
483
    if (gotit)
 
484
        adjustclip (widget);
 
485
    return 0;
 
486
}
 
487
 
 
488
int GCsetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
 
489
    setgattr (widget, ap);
 
490
    WCU->defgattr = WCU->gattr;
 
491
    return 0;
 
492
}
 
493
 
 
494
int GCgetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
 
495
    if ((ap->flags & G_GATTRCOLOR))
 
496
        ap->color = WCU->gattr.color;
 
497
    if ((ap->flags & G_GATTRWIDTH))
 
498
        ap->width = WCU->gattr.width;
 
499
    if ((ap->flags & G_GATTRMODE))
 
500
        ap->mode = WCU->gattr.mode;
 
501
    if ((ap->flags & G_GATTRFILL))
 
502
        ap->fill = WCU->gattr.fill;
 
503
    if ((ap->flags & G_GATTRSTYLE))
 
504
        ap->style = WCU->gattr.style;
 
505
    return 0;
 
506
}
 
507
 
 
508
int GCarrow (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
 
509
    PIXpoint_t pp1, pp2, pa, pb, pd;
 
510
    Grect_t gr;
 
511
    double tangent, l;
 
512
 
 
513
    if (gp1.x < gp2.x)
 
514
        gr.o.x = gp1.x, gr.c.x = gp2.x;
 
515
    else
 
516
        gr.o.x = gp2.x, gr.c.x = gp1.x;
 
517
    if (gp1.y < gp2.y)
 
518
        gr.o.y = gp1.y, gr.c.y = gp2.y;
 
519
    else
 
520
        gr.o.y = gp2.y, gr.c.y = gp1.y;
 
521
    if (!ISVISIBLE (gr))
 
522
        return 1;
 
523
    pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
 
524
    pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y;
 
525
    if (pd.x == 0 && pd.y == 0)
 
526
        return 0;
 
527
    tangent = atan2 ((double) pd.y, (double) pd.x);
 
528
    if ((l = sqrt ((double) (pd.x * pd.x + pd.y * pd.y))) > 30)
 
529
        l = 30;
 
530
    pa.x = l * cos (tangent + M_PI / 7) + pp2.x;
 
531
    pa.y = l * sin (tangent + M_PI / 7) + pp2.y;
 
532
    pb.x = l * cos (tangent - M_PI / 7) + pp2.x;
 
533
    pb.y = l * sin (tangent - M_PI / 7) + pp2.y;
 
534
    setgattr (widget, ap);
 
535
    XDrawLine (Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y);
 
536
    XDrawLine (Gdisplay, WINDOW, GC, pa.x, pa.y, pp2.x, pp2.y);
 
537
    XDrawLine (Gdisplay, WINDOW, GC, pb.x, pb.y, pp2.x, pp2.y);
 
538
    return 0;
 
539
}
 
540
 
 
541
int GCline (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
 
542
    PIXpoint_t pp1, pp2;
 
543
    Grect_t gr;
 
544
 
 
545
    if (gp1.x < gp2.x)
 
546
        gr.o.x = gp1.x, gr.c.x = gp2.x;
 
547
    else
 
548
        gr.o.x = gp2.x, gr.c.x = gp1.x;
 
549
    if (gp1.y < gp2.y)
 
550
        gr.o.y = gp1.y, gr.c.y = gp2.y;
 
551
    else
 
552
        gr.o.y = gp2.y, gr.c.y = gp1.y;
 
553
    if (!ISVISIBLE (gr))
 
554
        return 1;
 
555
    pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
 
556
    setgattr (widget, ap);
 
557
    XDrawLine (Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y);
 
558
    return 0;
 
559
}
 
560
 
 
561
int GCbox (Gwidget_t *widget, Grect_t gr, Ggattr_t *ap) {
 
562
    PIXrect_t pr;
 
563
    Gxy_t p;
 
564
 
 
565
    if (gr.o.x > gr.c.x)
 
566
        p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;
 
567
    if (gr.o.y > gr.c.y)
 
568
        p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;
 
569
    if (!ISVISIBLE (gr))
 
570
        return 1;
 
571
    pr = rdrawtopix (widget, gr);
 
572
    setgattr (widget, ap);
 
573
    if (WCU->gattr.fill)
 
574
        XFillRectangle (Gdisplay, WINDOW, GC,
 
575
                pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y);
 
576
    else
 
577
        XDrawRectangle (Gdisplay, WINDOW, GC,
 
578
                pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y);
 
579
    return 0;
 
580
}
 
581
 
 
582
int GCpolygon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
 
583
    Grect_t gr;
 
584
    int n, i;
 
585
 
 
586
    if (gpn == 0)
 
587
        return 0;
 
588
    gr.o = gpp[0], gr.c = gpp[0];
 
589
    for (i = 1; i < gpn; i++) {
 
590
        gr.o.x = min (gr.o.x, gpp[i].x);
 
591
        gr.o.y = min (gr.o.y, gpp[i].y);
 
592
        gr.c.x = max (gr.c.x, gpp[i].x);
 
593
        gr.c.y = max (gr.c.y, gpp[i].y);
 
594
    }
 
595
    if (!ISVISIBLE (gr))
 
596
        return 1;
 
597
    if (gpn + 1 > Gppn) {
 
598
        n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR;
 
599
        Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
 
600
        Gppn = n;
 
601
    }
 
602
    for (i = 0; i < gpn; i++)
 
603
        Gppp[i] = pdrawtopix (widget, gpp[i]);
 
604
    setgattr (widget, ap);
 
605
    if (WCU->gattr.fill) {
 
606
        if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y)
 
607
            Gppp[gpn] = Gppp[0], gpn++;
 
608
        XFillPolygon (Gdisplay, WINDOW, GC, Gppp, gpn,
 
609
                Complex, CoordModeOrigin);
 
610
    } else
 
611
        XDrawLines (Gdisplay, WINDOW, GC, Gppp, gpn, CoordModeOrigin);
 
612
    return 0;
 
613
}
 
614
 
 
615
int GCsplinegon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
 
616
    PIXpoint_t p0, p1, p2, p3;
 
617
    Grect_t gr;
 
618
    int n, i;
 
619
 
 
620
    if (gpn == 0)
 
621
        return 0;
 
622
    gr.o = gpp[0], gr.c = gpp[0];
 
623
    for (i = 1; i < gpn; i++) {
 
624
        gr.o.x = min (gr.o.x, gpp[i].x);
 
625
        gr.o.y = min (gr.o.y, gpp[i].y);
 
626
        gr.c.x = max (gr.c.x, gpp[i].x);
 
627
        gr.c.y = max (gr.c.y, gpp[i].y);
 
628
    }
 
629
    if (!ISVISIBLE (gr))
 
630
        return 1;
 
631
    Gppi = 1;
 
632
    if (Gppi >= Gppn) {
 
633
        n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
 
634
        Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
 
635
        Gppn = n;
 
636
    }
 
637
    Gppp[0] = p3 = pdrawtopix (widget, gpp[0]);
 
638
    for (i = 1; i < gpn; i += 3) {
 
639
        p0 = p3;
 
640
        p1 = pdrawtopix (widget, gpp[i]);
 
641
        p2 = pdrawtopix (widget, gpp[i + 1]);
 
642
        p3 = pdrawtopix (widget, gpp[i + 2]);
 
643
        bezier (p0, p1, p2, p3);
 
644
    }
 
645
    setgattr (widget, ap);
 
646
    if (WCU->gattr.fill) {
 
647
        if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y)
 
648
            Gppp[Gppi] = Gppp[0], Gppi++;
 
649
        XFillPolygon (Gdisplay, WINDOW, GC, Gppp, Gppi,
 
650
                Complex, CoordModeOrigin);
 
651
    } else
 
652
        XDrawLines (Gdisplay, WINDOW, GC, Gppp, Gppi, CoordModeOrigin);
 
653
    return 0;
 
654
}
 
655
 
 
656
static void bezier (PIXpoint_t p0, PIXpoint_t p1,
 
657
        PIXpoint_t p2, PIXpoint_t p3) {
 
658
    Gpoint_t gp0, gp1, gp2;
 
659
    Gsize_t s;
 
660
    PIXpoint_t p;
 
661
    double t;
 
662
    int n, i, steps;
 
663
 
 
664
    if ((s.x = p3.x - p0.x) < 0)
 
665
        s.x = - s.x;
 
666
    if ((s.y = p3.y - p0.y) < 0)
 
667
        s.y = - s.y;
 
668
    if (s.x > s.y)
 
669
        steps = s.x / 5 + 1;
 
670
    else
 
671
        steps = s.y / 5 + 1;
 
672
    for (i = 0; i <= steps; i++) {
 
673
        t = i / (double) steps;
 
674
        gp0.x = p0.x + t * (p1.x - p0.x);
 
675
        gp0.y = p0.y + t * (p1.y - p0.y);
 
676
        gp1.x = p1.x + t * (p2.x - p1.x);
 
677
        gp1.y = p1.y + t * (p2.y - p1.y);
 
678
        gp2.x = p2.x + t * (p3.x - p2.x);
 
679
        gp2.y = p2.y + t * (p3.y - p2.y);
 
680
        gp0.x = gp0.x + t * (gp1.x - gp0.x);
 
681
        gp0.y = gp0.y + t * (gp1.y - gp0.y);
 
682
        gp1.x = gp1.x + t * (gp2.x - gp1.x);
 
683
        gp1.y = gp1.y + t * (gp2.y - gp1.y);
 
684
        p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5;
 
685
        p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5;
 
686
        if (Gppi >= Gppn) {
 
687
            n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
 
688
            Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
 
689
            Gppn = n;
 
690
        }
 
691
        Gppp[Gppi++] = p;
 
692
    }
 
693
}
 
694
 
 
695
int GCarc (Gwidget_t *widget, Gpoint_t gc, Gsize_t gs, double ang1,
 
696
        double ang2, Ggattr_t *ap) {
 
697
    PIXpoint_t pc;
 
698
    PIXsize_t ps;
 
699
    Grect_t gr;
 
700
 
 
701
    gr.o.x = gc.x - gs.x, gr.o.y = gc.y - gs.y;
 
702
    gr.c.x = gc.x + gs.x, gr.c.y = gc.y + gs.y;
 
703
    if (!ISVISIBLE (gr))
 
704
        return 1;
 
705
    pc = pdrawtopix (widget, gc), ps = sdrawtopix (widget, gs);
 
706
    setgattr (widget, ap);
 
707
    if (WCU->gattr.fill)
 
708
        XFillArc (Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y,
 
709
                ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64));
 
710
    else
 
711
        XDrawArc (Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y,
 
712
                ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64));
 
713
    return 0;
 
714
}
 
715
 
 
716
int GCtext (Gwidget_t *widget, Gtextline_t *tlp, int n, Gpoint_t go,
 
717
        char *fn, double fs, char *justs, Ggattr_t *ap) {
 
718
    Gsize_t gs;
 
719
    PIXpoint_t po;
 
720
    PIXsize_t ps;
 
721
    PIXrect_t pr;
 
722
    Grect_t gr;
 
723
    XFontStruct *font;
 
724
    int dir, asc, des, x, y, w, h, i;
 
725
    XCharStruct txtinfo;
 
726
 
 
727
    po = pdrawtopix (widget, go);
 
728
    gs.x = 0, gs.y = fs;
 
729
    ps = sdrawtopix (widget, gs);
 
730
    if (!(font = findfont (fn, ps.y))) {
 
731
        XDrawRectangle (Gdisplay, WINDOW, GC, po.x, po.y, 1, 1);
 
732
        return 0;
 
733
    }
 
734
    setgattr (widget, ap);
 
735
    SETFONT (font);
 
736
    for (w = h = 0, i = 0; i < n; i++) {
 
737
        if (IS8BIT (font))
 
738
            XTextExtents (font, tlp[i].p, tlp[i].n, &dir, &asc, &des, &txtinfo);
 
739
        else
 
740
            XTextExtents16 (font, (XChar2b *) tlp[i].p, tlp[i].n / 2,
 
741
                    &dir, &asc, &des, &txtinfo);
 
742
        tlp[i].w = txtinfo.width, tlp[i].h = asc + des;
 
743
        w = max (w, txtinfo.width), h += asc + des;
 
744
    }
 
745
    switch (justs[0]) {
 
746
    case 'l': po.x += w / 2; break;
 
747
    case 'r': po.x -= w / 2; break;
 
748
    }
 
749
    switch (justs[1]) {
 
750
    case 'd': po.y -= h; break;
 
751
    case 'c': po.y -= h / 2; break;
 
752
    }
 
753
    pr.o.x = po.x - w / 2, pr.o.y = po.y;
 
754
    pr.c.x = po.x + w / 2, pr.c.y = po.y + h;
 
755
    gr = rpixtodraw (widget, pr);
 
756
    if (!ISVISIBLE (gr))
 
757
        return 1;
 
758
    for (i = 0; i < n; i++) {
 
759
        switch (tlp[i].j) {
 
760
        case 'l': x = po.x - w / 2; break;
 
761
        case 'n': x = po.x - tlp[i].w / 2; break;
 
762
        case 'r': x = po.x - (tlp[i].w - w / 2); break;
 
763
        }
 
764
        y = po.y + (i + 1) * tlp[i].h - des;
 
765
        if (IS8BIT (font))
 
766
            XDrawString (Gdisplay, WINDOW, GC, x, y, tlp[i].p, tlp[i].n);
 
767
        else
 
768
            XDrawString16 (Gdisplay, WINDOW, GC, x, y,
 
769
                    (XChar2b *) tlp[i].p, tlp[i].n / 2);
 
770
    }
 
771
    return 0;
 
772
}
 
773
 
 
774
int GCgettextsize (Gwidget_t *widget, Gtextline_t *tlp, int n, char *fn,
 
775
        double fs, Gsize_t *gsp) {
 
776
    Gsize_t gs;
 
777
    PIXsize_t ps;
 
778
    XFontStruct *font;
 
779
    int i, dir, asc, des;
 
780
    XCharStruct txtinfo;
 
781
 
 
782
    gs.x = 0, gs.y = fs;
 
783
    ps = sdrawtopix (widget, gs);
 
784
    if (!(font = findfont (fn, ps.y))) {
 
785
        gsp->x = 1, gsp->y = 1;
 
786
        return 0;
 
787
    }
 
788
    SETFONT (font);
 
789
    for (ps.x = ps.y = 0, i = 0; i < n; i++) {
 
790
        if (IS8BIT (font))
 
791
            XTextExtents (font, tlp[i].p, tlp[i].n, &dir, &asc, &des, &txtinfo);
 
792
        else
 
793
        XTextExtents16 (font, (XChar2b *) tlp[i].p, tlp[i].n / 2,
 
794
                &dir, &asc, &des, &txtinfo);
 
795
        ps.x = max (ps.x, txtinfo.width), ps.y += asc + des;
 
796
    }
 
797
    *gsp = spixtodraw (widget, ps);
 
798
    return 0;
 
799
}
 
800
 
 
801
static XFontStruct *findfont (char *name, int size) {
 
802
    XFontStruct *font;
 
803
    int fi, n, i;
 
804
 
 
805
    if (name[0] == '\000')
 
806
        return Gfontp[0].font;
 
807
 
 
808
    sprintf (&Gbufp[0], name, size);
 
809
    for (fi = 0; fi < Gfontn; fi++)
 
810
        if (Strcmp (&Gbufp[0], Gfontp[fi].name) == 0)
 
811
            return Gfontp[fi].font;
 
812
    if (!(font = XLoadQueryFont (Gdisplay, &Gbufp[0]))) {
 
813
        n = strlen (&Gbufp[0]) + 1;
 
814
        for (i = 1; i < size; i++) {
 
815
            sprintf (&Gbufp[n], name, size - i);
 
816
            if ((font = XLoadQueryFont (Gdisplay, &Gbufp[n])))
 
817
                break;
 
818
            sprintf (&Gbufp[n], name, size + i);
 
819
            if ((font = XLoadQueryFont (Gdisplay, &Gbufp[n])))
 
820
                break;
 
821
        }
 
822
    }
 
823
    if (!font)
 
824
        font = Gfontp[0].font;
 
825
 
 
826
    Gfontp = Marraygrow (Gfontp, (long) (Gfontn + 1) * FONTSIZE);
 
827
    Gfontp[Gfontn].name = strdup (&Gbufp[0]);
 
828
    Gfontp[Gfontn].font = font;
 
829
    Gfontn++;
 
830
    return font;
 
831
}
 
832
 
 
833
int GCcreatebitmap (Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t s) {
 
834
    if (!widget) {
 
835
        Gerr (POS, G_ERRNOPARENTWIDGET);
 
836
        return -1;
 
837
    }
 
838
    if (!bitmap) {
 
839
        Gerr (POS, G_ERRNOBITMAP);
 
840
        return -1;
 
841
    }
 
842
    if (!(bitmap->u.bmap.orig = XCreatePixmap (Gdisplay, XtWindow (widget->w),
 
843
            (int) s.x, (int) s.y, Gdepth))) {
 
844
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
845
        return -1;
 
846
    }
 
847
    bitmap->u.bmap.scaled = 0;
 
848
    bitmap->scale.x = bitmap->scale.y = 1;
 
849
    bitmap->ctype = widget->type;
 
850
    bitmap->canvas = widget - &Gwidgets[0];
 
851
    bitmap->size = s;
 
852
    return 0;
 
853
}
 
854
 
 
855
int GCdestroybitmap (Gbitmap_t *bitmap) {
 
856
    if (!bitmap) {
 
857
        Gerr (POS, G_ERRNOBITMAP);
 
858
        return -1;
 
859
    }
 
860
    XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
 
861
    if (bitmap->u.bmap.scaled)
 
862
        XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
 
863
    return 0;
 
864
}
 
865
 
 
866
#define COMPDIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
 
867
#define CDIFF(a, b) (COMPDIFF (a.red, b[0]) + COMPDIFF (a.green, b[1]) + \
 
868
        COMPDIFF (a.blue, b[2]))
 
869
#define CMINMAXDIFF 20000
 
870
 
 
871
int GCreadbitmap (Gwidget_t *widget, Gbitmap_t *bitmap, FILE *fp) {
 
872
    Gsize_t s;
 
873
    XImage *img;
 
874
    XColor colors[G_MAXCOLORS];
 
875
    char bufp[2048];
 
876
    int rgb[3];
 
877
    char *s1, *s2;
 
878
    char c;
 
879
    int cmaxdiff, colori, colorn, bufn, bufi, step, x, y, k;
 
880
 
 
881
    if (!widget) {
 
882
        Gerr (POS, G_ERRNOPARENTWIDGET);
 
883
        return -1;
 
884
    }
 
885
    if (!bitmap) {
 
886
        Gerr (POS, G_ERRNOBITMAP);
 
887
        return -1;
 
888
    }
 
889
    step = 0;
 
890
    while (step < 3) {
 
891
l1:
 
892
        if (!fgets (bufp, 2048, fp)) {
 
893
            Gerr (POS, G_ERRCANNOTREADBITMAP);
 
894
            return -1;
 
895
        }
 
896
        s1 = &bufp[0];
 
897
l2:
 
898
        for (; *s1 && isspace (*s1); s1++)
 
899
            ;
 
900
        if (!*s1 || *s1 == '#')
 
901
            goto l1;
 
902
        switch (step) {
 
903
        case 0:
 
904
            if (strncmp (s1, "P6", 2) != 0) {
 
905
                Gerr (POS, G_ERRCANNOTREADBITMAP);
 
906
                return -1;
 
907
            }
 
908
            step++, s1 += 2;
 
909
            goto l2;
 
910
        case 1:
 
911
            for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
 
912
                ;
 
913
            c = *s2, *s2 = 0;
 
914
            if (s2 == s1 || (s.x = atoi (s1)) <= 0) {
 
915
                *s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
 
916
                return -1;
 
917
            }
 
918
            *s2 = c, step++, s1 = s2;
 
919
            goto l2;
 
920
        case 2:
 
921
            for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
 
922
                ;
 
923
            c = *s2, *s2 = 0;
 
924
            if (s2 == s1 || (s.y = atoi (s1)) <= 0) {
 
925
                *s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
 
926
                return -1;
 
927
            }
 
928
            *s2 = c, step++, s1 = s2;
 
929
            goto l2;
 
930
        }
 
931
    }
 
932
    if (!(bitmap->u.bmap.orig = XCreatePixmap (Gdisplay, XtWindow (widget->w),
 
933
            (int) s.x, (int) s.y, Gdepth))) {
 
934
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
935
        return -1;
 
936
    }
 
937
    bitmap->u.bmap.scaled = 0;
 
938
    bitmap->scale.x = bitmap->scale.y = 1;
 
939
    bitmap->ctype = widget->type;
 
940
    bitmap->canvas = widget - &Gwidgets[0];
 
941
    bitmap->size = s;
 
942
    if ((img = XCreateImage (Gdisplay, DefaultVisual (Gdisplay, Gscreenn),
 
943
            Gdepth, ZPixmap, 0, NULL, (int) s.x, (int) s.y, 32, 0)) == NULL) {
 
944
        XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
 
945
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
946
        return -1;
 
947
    }
 
948
    if ((img->data = malloc (img->bytes_per_line * img->height)) == NULL) {
 
949
        XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
 
950
        XDestroyImage (img);
 
951
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
952
        return -1;
 
953
    }
 
954
    colorn = 0;
 
955
    for (colori = 0; colori < G_MAXCOLORS; colori++) {
 
956
        if (widget->u.c->colors[colori].inuse) {
 
957
            colors[colorn] = widget->u.c->colors[colori].color;
 
958
            colorn++;
 
959
        }
 
960
    }
 
961
    bufi = bufn = 0;
 
962
    bufp[bufi] = 0;
 
963
    for (y = 0; y < s.y; y++) {
 
964
        for (x = 0; x < s.x; x++) {
 
965
            for (k = 0; k < 3; k++) {
 
966
                if (bufi == bufn) {
 
967
                    if ((bufn = fread (bufp, 1, 2047, fp)) == 0) {
 
968
                        XFreePixmap (Gdisplay, bitmap->u.bmap.orig);
 
969
                        XDestroyImage (img);
 
970
                        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
971
                        return -1;
 
972
                    }
 
973
                    bufi = 0;
 
974
                }
 
975
                rgb[k] = 257 * (unsigned char) bufp[bufi++];
 
976
            }
 
977
            cmaxdiff = CMINMAXDIFF;
 
978
l3:
 
979
            for (colori = 0; colori < colorn; colori++)
 
980
                if (CDIFF (colors[colori], rgb) < cmaxdiff)
 
981
                    break;
 
982
            if (colori == colorn && colorn < G_MAXCOLORS &&
 
983
                    cmaxdiff == CMINMAXDIFF) {
 
984
                colors[colorn].red = rgb[0];
 
985
                colors[colorn].green = rgb[1];
 
986
                colors[colorn].blue = rgb[2];
 
987
                if (XAllocColor (Gdisplay, widget->u.c->cmap, &colors[colorn]))
 
988
                    colorn++;
 
989
            }
 
990
            if (colori == colorn) {
 
991
                cmaxdiff *= 10;
 
992
                goto l3;
 
993
            }
 
994
            XPutPixel (img, x, y, colors[colori].pixel);
 
995
        }
 
996
    }
 
997
    for (colori = 0; colori < G_MAXCOLORS && colori < colorn; colori++) {
 
998
        if (!widget->u.c->colors[colori].inuse) {
 
999
            widget->u.c->colors[colori].color = colors[colori];
 
1000
            widget->u.c->colors[colori].inuse = TRUE;
 
1001
        }
 
1002
    }
 
1003
    XPutImage (Gdisplay, bitmap->u.bmap.orig, widget->u.c->gc, img,
 
1004
            0, 0, 0, 0, (int) s.x, (int) s.y);
 
1005
    XDestroyImage (img);
 
1006
    return 0;
 
1007
}
 
1008
 
 
1009
int GCwritebitmap (Gbitmap_t *bitmap, FILE *fp) {
 
1010
    Gwidget_t *widget;
 
1011
    XImage *img;
 
1012
    XColor colors[G_MAXCOLORS];
 
1013
    char bufp[2048];
 
1014
    int colori, bufi, x, y, w, h;
 
1015
 
 
1016
    if (!bitmap) {
 
1017
        Gerr (POS, G_ERRNOBITMAP);
 
1018
        return -1;
 
1019
    }
 
1020
    if (bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn ||
 
1021
            !Gwidgets[bitmap->canvas].inuse) {
 
1022
        Gerr (POS, G_ERRBADWIDGETID, bitmap->canvas);
 
1023
        return -1;
 
1024
    }
 
1025
    widget = &Gwidgets[bitmap->canvas];
 
1026
    if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
 
1027
        Gerr (POS, G_ERRNOTACANVAS, bitmap->canvas);
 
1028
        return -1;
 
1029
    }
 
1030
    for (colori = 0; colori < G_MAXCOLORS; colori++)
 
1031
        colors[colori].pixel = colori;
 
1032
    XQueryColors (Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS);
 
1033
    if (!(img = XGetImage (Gdisplay, bitmap->u.bmap.orig, 0, 0,
 
1034
            bitmap->size.x, bitmap->size.y, AllPlanes, ZPixmap))) {
 
1035
        Gerr (POS, G_ERRNOBITMAP);
 
1036
        return -1;
 
1037
    }
 
1038
    fprintf (fp, "P6\n%d %d 255\n", (int) bitmap->size.x, (int) bitmap->size.y);
 
1039
    bufi = 0;
 
1040
    w = bitmap->size.x;
 
1041
    h = bitmap->size.y;
 
1042
    for (y = 0; y < h; y++) {
 
1043
        for (x = 0; x < w; x++) {
 
1044
            colori = XGetPixel (img, x, y);
 
1045
            bufp[bufi++] = colors[colori].red / 257;
 
1046
            bufp[bufi++] = colors[colori].green / 257;
 
1047
            bufp[bufi++] = colors[colori].blue / 257;
 
1048
            if (bufi + 3 >= 2048) {
 
1049
                fwrite (bufp, 1, bufi, fp);
 
1050
                bufi = 0;
 
1051
            }
 
1052
        }
 
1053
    }
 
1054
    if (bufi > 0)
 
1055
        fwrite (bufp, 1, bufi, fp);
 
1056
    XDestroyImage (img);
 
1057
    return 0;
 
1058
}
 
1059
 
 
1060
int GCbitblt (Gwidget_t *widget, Gpoint_t gp, Grect_t gr, Gbitmap_t *bitmap,
 
1061
        char *mode, Ggattr_t *ap) {
 
1062
    PIXrect_t pr;
 
1063
    PIXpoint_t pp;
 
1064
    Gsize_t scale;
 
1065
    Gxy_t p;
 
1066
    Pixmap pix;
 
1067
    double tvx, tvy, twx, twy;
 
1068
 
 
1069
    if (gr.o.x > gr.c.x)
 
1070
        p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;
 
1071
    if (gr.o.y > gr.c.y)
 
1072
        p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;
 
1073
    if (strcmp (mode, "b2c") == 0) {
 
1074
        if (!ISVISIBLE (gr))
 
1075
            return 1;
 
1076
        tvx = WCU->vsize.x, tvy = WCU->vsize.y;
 
1077
        twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1078
        twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1079
        scale.x = tvx / twx, scale.y = tvy / twy;
 
1080
        if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 &&
 
1081
                scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) {
 
1082
            pix = bitmap->u.bmap.orig;
 
1083
            bitmap->scale = scale;
 
1084
        } else {
 
1085
            if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
 
1086
                scalebitmap (widget, bitmap, scale, TRUE, 1);
 
1087
            pix = bitmap->u.bmap.scaled;
 
1088
        }
 
1089
        pr = rdrawtopix (widget, gr);
 
1090
        pp = pdrawtobpix (bitmap, gp);
 
1091
        setgattr (widget, ap);
 
1092
        XCopyArea (Gdisplay, pix, WINDOW, GC, pp.x, pp.y - pr.c.y + pr.o.y,
 
1093
                pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, pr.o.y);
 
1094
    } else if (strcmp (mode, "c2b") == 0) {
 
1095
        tvx = WCU->vsize.x, tvy = WCU->vsize.y;
 
1096
        twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1097
        twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1098
        scale.x = tvx / twx, scale.y = tvy / twy;
 
1099
        if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 &&
 
1100
                scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) {
 
1101
            pix = bitmap->u.bmap.orig;
 
1102
            bitmap->scale = scale;
 
1103
        } else {
 
1104
            if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
 
1105
                scalebitmap (widget, bitmap, scale, FALSE, 1);
 
1106
            pix = bitmap->u.bmap.scaled;
 
1107
        }
 
1108
        pr = rdrawtobpix (bitmap, gr);
 
1109
        pp = pdrawtopix (widget, gp);
 
1110
        setgattr (widget, ap);
 
1111
        XCopyArea (Gdisplay, WINDOW, pix, GC, pp.x, pp.y - pr.c.y + pr.o.y,
 
1112
                pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, pr.o.y);
 
1113
        if (pix != bitmap->u.bmap.orig)
 
1114
            scalebitmap (widget, bitmap, scale, TRUE, -1);
 
1115
    }
 
1116
    return 0;
 
1117
}
 
1118
 
 
1119
static int scalebitmap (Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t scale,
 
1120
        int copybits, int dir) {
 
1121
    Gsize_t nsize, o2n;
 
1122
    Pixmap spix;
 
1123
    XImage *oimg, *simg;
 
1124
    XColor colors[G_MAXCOLORS];
 
1125
    int cmaxdiff, colorn, colori, x, y, x2, y2, xp, yp;
 
1126
    double prod, rgb[3], xr2, yr2, xl2, yl2, xf2, yf2, xr, yr, xl, yl;
 
1127
 
 
1128
    if (!copybits) {
 
1129
        if (dir == 1) {
 
1130
            nsize.x = (int) (bitmap->size.x * scale.x);
 
1131
            nsize.y = (int) (bitmap->size.y * scale.y);
 
1132
            if (!(spix = XCreatePixmap (Gdisplay, XtWindow (widget->w),
 
1133
                    (int) nsize.x, (int) nsize.y, Gdepth))) {
 
1134
                Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
1135
                return -1;
 
1136
            }
 
1137
            if (bitmap->u.bmap.scaled)
 
1138
                XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
 
1139
            bitmap->u.bmap.scaled = spix;
 
1140
            bitmap->scale = scale;
 
1141
        }
 
1142
        return 0;
 
1143
    }
 
1144
    for (colori = 0; colori < G_MAXCOLORS; colori++)
 
1145
        colors[colori].pixel = colori;
 
1146
    colorn = G_MAXCOLORS;
 
1147
    XQueryColors (Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS);
 
1148
    if (dir == 1) {
 
1149
        nsize.x = (int) (bitmap->size.x * scale.x);
 
1150
        nsize.y = (int) (bitmap->size.y * scale.y);
 
1151
        o2n.x = 1 / scale.x, o2n.y = 1 / scale.y;
 
1152
        if (!(oimg = XGetImage (Gdisplay, bitmap->u.bmap.orig, 0, 0,
 
1153
                (int) bitmap->size.x, (int) bitmap->size.y, AllPlanes,
 
1154
                ZPixmap))) {
 
1155
            Gerr (POS, G_ERRNOBITMAP);
 
1156
            return -1;
 
1157
        }
 
1158
        if (!(spix = XCreatePixmap (Gdisplay, XtWindow (widget->w),
 
1159
                (int) nsize.x, (int) nsize.y, Gdepth))) {
 
1160
            XDestroyImage (oimg);
 
1161
            Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
1162
            return -1;
 
1163
        }
 
1164
    } else {
 
1165
        nsize.x = (int) bitmap->size.x;
 
1166
        nsize.y = (int) bitmap->size.y;
 
1167
        o2n.x = scale.x, o2n.y = scale.y;
 
1168
        if (!(oimg = XGetImage (Gdisplay, bitmap->u.bmap.scaled, 0, 0,
 
1169
                (int) (bitmap->size.x * scale.x), (int) (bitmap->size.y *
 
1170
                scale.y), AllPlanes, ZPixmap))) {
 
1171
            Gerr (POS, G_ERRNOBITMAP);
 
1172
            return -1;
 
1173
        }
 
1174
        spix = bitmap->u.bmap.orig;
 
1175
    }
 
1176
    prod = o2n.x * o2n.y;
 
1177
    if (!(simg = XCreateImage (Gdisplay, DefaultVisual (Gdisplay, Gscreenn),
 
1178
            Gdepth, ZPixmap, 0, NULL, (int) nsize.x, (int) nsize.y, 32, 0))) {
 
1179
        XFreePixmap (Gdisplay, spix);
 
1180
        XDestroyImage (oimg);
 
1181
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
1182
        return -1;
 
1183
    }
 
1184
    if ((simg->data = malloc (simg->bytes_per_line * simg->height)) == NULL) {
 
1185
        XFreePixmap (Gdisplay, spix);
 
1186
        XDestroyImage (oimg);
 
1187
        XDestroyImage (simg);
 
1188
        Gerr (POS, G_ERRCANNOTCREATEBITMAP);
 
1189
        return -1;
 
1190
    }
 
1191
    y = 0;
 
1192
    yr = o2n.y;
 
1193
    yl = 0;
 
1194
    for (yp = 0; yp < nsize.y; yp++) {
 
1195
        x = 0;
 
1196
        xr = o2n.x;
 
1197
        xl = 0;
 
1198
        for (xp = 0; xp < nsize.x; xp++) {
 
1199
            y2 = y;
 
1200
            yr2 = yr;
 
1201
            yl2 = yl;
 
1202
            rgb[0] = rgb[1] = rgb[2] = 0;
 
1203
            do {
 
1204
                x2 = x;
 
1205
                xr2 = xr;
 
1206
                xl2 = xl;
 
1207
                yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2;
 
1208
                do {
 
1209
                    xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2;
 
1210
                    colori = XGetPixel (oimg, x2, y2);
 
1211
                    rgb[0] += (colors[colori].red * xf2 * yf2 / prod);
 
1212
                    rgb[1] += (colors[colori].green * xf2 * yf2 / prod);
 
1213
                    rgb[2] += (colors[colori].blue * xf2 * yf2 / prod);
 
1214
                    xl2 += xf2;
 
1215
                    if (xl2 >= 1)
 
1216
                        x2++, xl2 -= 1;
 
1217
                } while (xr2 > 0);
 
1218
                xr2 = o2n.x;
 
1219
                yl2 += yf2;
 
1220
                if (yl2 >= 1)
 
1221
                    y2++, yl2 -= 1;
 
1222
            } while (yr2 > 0);
 
1223
            yr2 = o2n.y;
 
1224
            cmaxdiff = CMINMAXDIFF;
 
1225
l4:
 
1226
            for (colori = 0; colori < colorn; colori++)
 
1227
                if (CDIFF (colors[colori], rgb) < cmaxdiff)
 
1228
                    break;
 
1229
            if (colori == colorn) {
 
1230
                cmaxdiff *= 10;
 
1231
                goto l4;
 
1232
            }
 
1233
            XPutPixel (simg, xp, yp, colors[colori].pixel);
 
1234
            x = x2;
 
1235
            xr = xr2;
 
1236
            xl = xl2;
 
1237
        }
 
1238
        y = y2;
 
1239
        yr = yr2;
 
1240
        yl = yl2;
 
1241
    }
 
1242
    XPutImage (Gdisplay, spix, widget->u.c->gc, simg, 0, 0, 0, 0,
 
1243
            (int) nsize.x, (int) nsize.y);
 
1244
    XDestroyImage (simg);
 
1245
    XDestroyImage (oimg);
 
1246
    if (dir == 1) {
 
1247
        if (bitmap->u.bmap.scaled)
 
1248
            XFreePixmap (Gdisplay, bitmap->u.bmap.scaled);
 
1249
        bitmap->u.bmap.scaled = spix;
 
1250
        bitmap->scale = scale;
 
1251
    }
 
1252
    return 0;
 
1253
}
 
1254
 
 
1255
int GCgetmousecoords (Gwidget_t *widget, Gpoint_t *gpp, int *count) {
 
1256
    PIXpoint_t pp;
 
1257
    Window rwin, cwin;
 
1258
    int rx, ry, x, y;
 
1259
    unsigned int mask;
 
1260
 
 
1261
    XQueryPointer (Gdisplay, WINDOW, &rwin, &cwin, &rx, &ry, &x, &y, &mask);
 
1262
    pp.x = x, pp.y = y;
 
1263
    *gpp = Gppixtodraw (widget, pp);
 
1264
    *count = ((mask & Button1Mask) ? 1 : 0) + ((mask & Button2Mask) ? 1 : 0) +
 
1265
            ((mask & Button3Mask) ? 1 : 0);
 
1266
    return 0;
 
1267
}
 
1268
 
 
1269
void Gcwbutaction (Widget w, XEvent *evp, char **app, unsigned int *anp) {
 
1270
    Gwidget_t *widget;
 
1271
    Gevent_t gev;
 
1272
    PIXpoint_t pp;
 
1273
    int wi, xtype, bn;
 
1274
 
 
1275
    widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
 
1276
    switch ((xtype = evp->type)) {
 
1277
    case ButtonPress:
 
1278
    case ButtonRelease:
 
1279
        gev.type = G_MOUSE;
 
1280
        gev.code = (xtype == ButtonPress) ? G_DOWN : G_UP;
 
1281
        gev.data = evp->xbutton.button - Button1;
 
1282
        pp.x = evp->xbutton.x, pp.y = evp->xbutton.y;
 
1283
        gev.p = Gppixtodraw (widget, pp);
 
1284
        bn = WCU->bstate[gev.data];
 
1285
        WCU->bstate[gev.data] = (xtype == ButtonPress) ? 1 : 0;
 
1286
        bn = WCU->bstate[gev.data] - bn;
 
1287
        WCU->buttonsdown += bn;
 
1288
        Gbuttonsdown += bn;
 
1289
        break;
 
1290
    default:
 
1291
        return;
 
1292
    }
 
1293
    wi = gev.wi = widget - &Gwidgets[0];
 
1294
    Gpopdownflag = FALSE;
 
1295
    if (WCU->func)
 
1296
        (*WCU->func) (&gev);
 
1297
    if (Gpopdownflag) {
 
1298
        Gpopdownflag = FALSE;
 
1299
        if (gev.code == G_DOWN) {
 
1300
            gev.code = G_UP;
 
1301
            widget = &Gwidgets[wi];
 
1302
            WCU->bstate[gev.data] = 0;
 
1303
            WCU->buttonsdown--;
 
1304
            Gbuttonsdown--;
 
1305
            if (widget->inuse && WCU->func)
 
1306
                (*WCU->func) (&gev);
 
1307
        }
 
1308
    }
 
1309
}
 
1310
 
 
1311
void Gcwkeyaction (Widget w, XEvent *evp, char **app, unsigned int *anp) {
 
1312
    Gwidget_t *widget;
 
1313
    Gevent_t gev;
 
1314
    PIXpoint_t pp;
 
1315
    Window rwin, cwin;
 
1316
    int xtype, rx, ry, x, y;
 
1317
    unsigned int mask;
 
1318
    char c;
 
1319
 
 
1320
    widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
 
1321
    switch ((xtype = evp->type)) {
 
1322
    case KeyPress:
 
1323
    case KeyRelease:
 
1324
        if (!XLookupString ((XKeyEvent *) evp, &c, 1, NULL, NULL))
 
1325
            return;
 
1326
        XQueryPointer (Gdisplay, WCU->window, &rwin, &cwin,
 
1327
                &rx, &ry, &x, &y, &mask);
 
1328
        gev.type = G_KEYBD;
 
1329
        gev.code = (xtype == KeyPress) ? G_DOWN : G_UP;
 
1330
        gev.data = c;
 
1331
        pp.x = x, pp.y = y;
 
1332
        gev.p = Gppixtodraw (widget, pp);
 
1333
        break;
 
1334
    default:
 
1335
        return;
 
1336
    }
 
1337
    gev.wi = widget - &Gwidgets[0];
 
1338
    Gpopdownflag = FALSE;
 
1339
    if (WCU->func)
 
1340
        (*WCU->func) (&gev);
 
1341
    if (Gpopdownflag)
 
1342
        Gpopdownflag = FALSE;
 
1343
}
 
1344
 
 
1345
static void setgattr (Gwidget_t *widget, Ggattr_t *ap) {
 
1346
    XGCValues gcv;
 
1347
    XColor *cp;
 
1348
    int color, width, mode, style, pati;
 
1349
    double intens;
 
1350
 
 
1351
    if (!(ap->flags & G_GATTRCOLOR))
 
1352
        ap->color = WCU->defgattr.color;
 
1353
    if (!(ap->flags & G_GATTRWIDTH))
 
1354
        ap->width = WCU->defgattr.width;
 
1355
    if (!(ap->flags & G_GATTRMODE))
 
1356
        ap->mode = WCU->defgattr.mode;
 
1357
    if (!(ap->flags & G_GATTRFILL))
 
1358
        ap->fill = WCU->defgattr.fill;
 
1359
    if (!(ap->flags & G_GATTRSTYLE))
 
1360
        ap->style = WCU->defgattr.style;
 
1361
    color = ap->color;
 
1362
    if (color >= G_MAXCOLORS || !(WCU->colors[color].inuse))
 
1363
        color = 1;
 
1364
    if (color != WCU->gattr.color) {
 
1365
        WCU->gattr.color = color;
 
1366
        if (ap->mode == G_XOR)
 
1367
            XSetForeground (Gdisplay, GC,
 
1368
                    WCU->colors[WCU->gattr.color].color.pixel ^
 
1369
                    WCU->colors[0].color.pixel);
 
1370
        else
 
1371
            XSetForeground (Gdisplay, GC,
 
1372
                    WCU->colors[WCU->gattr.color].color.pixel);
 
1373
        if (Gdepth == 1) {
 
1374
            cp = &WCU->colors[color].color;
 
1375
            intens = (0.3 * cp->blue + 0.59 * cp->red +
 
1376
                    0.11 * cp->green) / 65535.0;
 
1377
            pati = (intens <= 0.0625) ? 16 :
 
1378
                    -16.0 * (log (intens) / 2.7725887222);
 
1379
            XSetTile (Gdisplay, GC, WCU->grays[pati]);
 
1380
        }
 
1381
    }
 
1382
    mode = ap->mode;
 
1383
    if (mode != WCU->gattr.mode) {
 
1384
        WCU->gattr.mode = mode;
 
1385
        XSetFunction (Gdisplay, GC, WCU->gattr.mode);
 
1386
        if (mode == G_XOR)
 
1387
            XSetForeground (Gdisplay, GC,
 
1388
                    WCU->colors[WCU->gattr.color].color.pixel ^
 
1389
                    WCU->colors[0].color.pixel);
 
1390
        else
 
1391
            XSetForeground (Gdisplay, GC,
 
1392
                    WCU->colors[WCU->gattr.color].color.pixel);
 
1393
    }
 
1394
    width = ap->width;
 
1395
    if (width != WCU->gattr.width) {
 
1396
        gcv.line_width = WCU->gattr.width = width;
 
1397
        XChangeGC (Gdisplay, GC, GCLineWidth, &gcv);
 
1398
    }
 
1399
    WCU->gattr.fill = ap->fill;
 
1400
    style = ap->style;
 
1401
    if (style != WCU->gattr.style) {
 
1402
        WCU->gattr.style = style;
 
1403
        if (style == G_SOLID) {
 
1404
            gcv.line_style = LineSolid;
 
1405
            XChangeGC (Gdisplay, GC, GCLineStyle, &gcv);
 
1406
        } else {
 
1407
            XSetDashes (Gdisplay, GC, 0, gstyles[style], 2);
 
1408
            gcv.line_style = LineOnOffDash;
 
1409
            XChangeGC (Gdisplay, GC, GCLineStyle, &gcv);
 
1410
        }
 
1411
    }
 
1412
}
 
1413
 
 
1414
static PIXrect_t rdrawtopix (Gwidget_t *widget, Grect_t gr) {
 
1415
    PIXrect_t pr;
 
1416
    double tvx, tvy, twx, twy;
 
1417
 
 
1418
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1419
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1420
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1421
    pr.o.x = tvx * (gr.o.x - WCU->wrect.o.x) / twx + 0.5;
 
1422
    pr.o.y = tvy * (1.0  - (gr.c.y - WCU->wrect.o.y) / twy) + 0.5;
 
1423
    pr.c.x = tvx * (gr.c.x - WCU->wrect.o.x) / twx + 0.5;
 
1424
    pr.c.y = tvy * (1.0  - (gr.o.y - WCU->wrect.o.y) / twy) + 0.5;
 
1425
    return pr;
 
1426
}
 
1427
 
 
1428
static PIXpoint_t pdrawtopix (Gwidget_t *widget, Gpoint_t gp) {
 
1429
    PIXpoint_t pp;
 
1430
    double tvx, tvy, twx, twy;
 
1431
 
 
1432
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1433
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1434
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1435
    pp.x = tvx * (gp.x - WCU->wrect.o.x) / twx + 0.5;
 
1436
    pp.y = tvy * (1.0  - (gp.y - WCU->wrect.o.y) / twy) + 0.5;
 
1437
    return pp;
 
1438
}
 
1439
 
 
1440
static PIXsize_t sdrawtopix (Gwidget_t *widget, Gsize_t gs) {
 
1441
    PIXsize_t ps;
 
1442
    double tvx, tvy, twx, twy;
 
1443
 
 
1444
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1445
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1446
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1447
    ps.x = tvx * (gs.x - 1) / twx + 1.5;
 
1448
    ps.y = tvy * (gs.y - 1) / twy + 1.5;
 
1449
    return ps;
 
1450
}
 
1451
 
 
1452
static Gpoint_t Gppixtodraw (Gwidget_t *widget, PIXpoint_t pp) {
 
1453
    Gpoint_t gp;
 
1454
    double tvx, tvy, twx, twy;
 
1455
 
 
1456
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1457
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1458
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1459
    gp.x = (pp.x / tvx) * twx + WCU->wrect.o.x;
 
1460
    gp.y = (1.0 - pp.y / tvy) * twy + WCU->wrect.o.y;
 
1461
    return gp;
 
1462
}
 
1463
 
 
1464
static Gsize_t spixtodraw (Gwidget_t *widget, PIXsize_t ps) {
 
1465
    Gsize_t gs;
 
1466
    double tvx, tvy, twx, twy;
 
1467
 
 
1468
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1469
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1470
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1471
    gs.x = ((ps.x - 1) / tvx) * twx + 1;
 
1472
    gs.y = ((ps.y - 1) / tvy) * twy + 1;
 
1473
    return gs;
 
1474
}
 
1475
 
 
1476
static Grect_t rpixtodraw (Gwidget_t *widget, PIXrect_t pr) {
 
1477
    Grect_t gr;
 
1478
    double tvx, tvy, twx, twy, n;
 
1479
 
 
1480
    tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1;
 
1481
    twx = WCU->wrect.c.x - WCU->wrect.o.x;
 
1482
    twy = WCU->wrect.c.y - WCU->wrect.o.y;
 
1483
    gr.o.x = (pr.o.x / tvx) * twx + WCU->wrect.o.x;
 
1484
    gr.o.y = (1.0 - pr.c.y / tvy) * twy + WCU->wrect.o.y;
 
1485
    gr.c.x = (pr.c.x / tvx) * twx + WCU->wrect.o.x;
 
1486
    gr.c.y = (1.0 - pr.o.y / tvy) * twy + WCU->wrect.o.y;
 
1487
    if (gr.o.x > gr.c.x)
 
1488
        n = gr.o.x, gr.o.x = gr.c.x, gr.c.x = n;
 
1489
    if (gr.o.y > gr.c.y)
 
1490
        n = gr.o.y, gr.o.y = gr.c.y, gr.c.y = n;
 
1491
    return gr;
 
1492
}
 
1493
 
 
1494
static PIXrect_t rdrawtobpix (Gbitmap_t *bitmap, Grect_t gr) {
 
1495
    PIXrect_t pr;
 
1496
    double tvy;
 
1497
 
 
1498
    tvy = (bitmap->size.y - 1) * bitmap->scale.y;
 
1499
    pr.o.x = gr.o.x + 0.5;
 
1500
    pr.o.y = tvy - gr.c.y + 0.5;
 
1501
    pr.c.x = gr.c.x + 0.5;
 
1502
    pr.c.y = tvy - gr.o.y + 0.5;
 
1503
    return pr;
 
1504
}
 
1505
 
 
1506
static PIXpoint_t pdrawtobpix (Gbitmap_t *bitmap, Gpoint_t gp) {
 
1507
    PIXpoint_t pp;
 
1508
    double tvy;
 
1509
 
 
1510
    tvy = (bitmap->size.y - 1) * bitmap->scale.y;
 
1511
    pp.x = gp.x + 0.5;
 
1512
    pp.y = tvy - gp.y + 0.5;
 
1513
    return pp;
 
1514
}
 
1515
 
 
1516
static void adjustclip (Gwidget_t *widget) {
 
1517
    Gwidget_t *parent;
 
1518
    Dimension width, height, pwidth, pheight;
 
1519
    Position x, y;
 
1520
    PIXrect_t pr;
 
1521
 
 
1522
    parent = &Gwidgets[widget->pwi];
 
1523
    RESETARGS;
 
1524
    ADD2ARGS (XtNx, &x);
 
1525
    ADD2ARGS (XtNy, &y);
 
1526
    ADD2ARGS (XtNwidth, &width);
 
1527
    ADD2ARGS (XtNheight, &height);
 
1528
    XtGetValues (widget->w, argp, argn);
 
1529
    RESETARGS;
 
1530
    ADD2ARGS (XtNwidth, &pwidth);
 
1531
    ADD2ARGS (XtNheight, &pheight);
 
1532
    XtGetValues (parent->w, argp, argn);
 
1533
    pr.o.x = max (0, -x);
 
1534
    pr.o.y = max (0, -y);
 
1535
    pr.c.x = min (width, pr.o.x + pwidth);
 
1536
    pr.c.y = min (height, pr.o.y + pheight);
 
1537
    pr.c.x = max (pr.o.x, pr.c.x);
 
1538
    pr.c.y = max (pr.o.y, pr.c.y);
 
1539
    WCU->clip = rpixtodraw (widget, pr);
 
1540
#ifdef FEATURE_GMAP
 
1541
    if (WCU->gmapmode) {
 
1542
        GMAPwinsetsize (XtWindow (widget->w), width, height);
 
1543
        GMAPchansetaspect (XtWindow (widget->w), width, height);
 
1544
    }
 
1545
#endif
 
1546
}
 
1547
 
 
1548
static Bool cwepredicate (Display *display, XEvent *evp, XPointer data) {
 
1549
    if (evp->type == Expose && ((XAnyEvent *) evp)->window == (Window) data)
 
1550
        return True;
 
1551
    return False;
 
1552
}
 
1553
 
 
1554
static void cweventhandler (Widget w, XtPointer data, XEvent *evp,
 
1555
        Boolean *cont) {
 
1556
    Gwidget_t *widget;
 
1557
 
 
1558
    widget = findwidget ((unsigned long) w, G_CANVASWIDGET);
 
1559
    Gneedredraw = WCU->needredraw = TRUE;
 
1560
    adjustclip (widget);
 
1561
#ifdef FEATURE_GMAP
 
1562
    if (WCU->gmapmode)
 
1563
        GMAPneedupdate = TRUE;
 
1564
#endif
 
1565
}
 
1566
 
 
1567
static Bool cwvpredicate (Display *display, XEvent *evp, XPointer data) {
 
1568
    if (evp->type == VisibilityNotify &&
 
1569
            ((XAnyEvent *) evp)->window == (Window) data)
 
1570
        return True;
 
1571
    return False;
 
1572
}