~ubuntu-branches/debian/sid/acfax/sid

« back to all changes in this revision

Viewing changes to Canvas.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2001-12-27 12:07:46 UTC
  • Revision ID: james.westby@ubuntu.com-20011227120746-iz2p5k757bcla8ov
Tags: upstream-981011
ImportĀ upstreamĀ versionĀ 981011

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Header: /home/orchestra5/davy/stuff/misc/xsat/RCS/Canvas.c,v 1.1 92/04/10 14:08:02 davy Exp $
 
3
 *
 
4
 * Copyright 1992 by David A. Curry
 
5
 * Adapted for use with ACfax by Andreas Czechanowski
 
6
 *
 
7
 * Permission to use, copy, modify, distribute, and sell this software and its
 
8
 * documentation for any purpose is hereby granted without fee, provided that
 
9
 * the above copyright notice appear in all copies and that both that copyright
 
10
 * notice and this permission notice appear in supporting documentation.  The
 
11
 * author makes no representations about the suitability of this software for
 
12
 * any purpose.  It is provided "as is" without express or implied warranty.
 
13
 *
 
14
 * Code for the Canvas widget.  Based in part on the Template widget from
 
15
 * the X11R5 distribution; I also looked quite a bit at the code from the
 
16
 * "xproof" program to figure out how to set things up.
 
17
 *
 
18
 * David A. Curry
 
19
 * Purdue University
 
20
 * Engineering Computer Network
 
21
 * 1285 Electrical Engineering Building
 
22
 * West Lafayette, IN 47907
 
23
 * davy@ecn.purdue.edu
 
24
 *
 
25
 * $Log:        Canvas.c,v $
 
26
 * Revision 1.1  92/04/10  14:08:02  davy
 
27
 * Initial revision
 
28
 * 
 
29
 */
 
30
#include <X11/IntrinsicP.h>
 
31
#include <X11/StringDefs.h>
 
32
#include <X11/cursorfont.h>
 
33
#include <X11/Xlib.h>
 
34
#include <stdio.h>
 
35
 
 
36
#include "CanvasP.h"
 
37
 
 
38
static void     Destroy();
 
39
static void     Realize();
 
40
static void     Redisplay();
 
41
static void     Resize();
 
42
static XtGeometryResult QueryGeometry();
 
43
static Boolean  SetValues();
 
44
static XtGeometryResult Geometry_manager();
 
45
static void     Initialize();
 
46
static void     Notify();
 
47
void    canvasIdle();
 
48
void    canvasBusy();
 
49
void    canvasClearPicture();
 
50
void    canvasUpdateArea();
 
51
 
 
52
/*
 
53
 * Canvas widget translations
 
54
 */
 
55
static char defaultTranslations[] =
 
56
    "<Btn1Down>:        notify()";
 
57
/*
 
58
 * Canvas widget actions
 
59
 */
 
60
static XtActionsRec actionsList[] = {
 
61
  {"notify",    Notify}
 
62
};
 
63
/*
 
64
 * Canvas widget resources.
 
65
 */
 
66
/* offset to a canvas-element in the widget-structure */
 
67
#define offset(field) XtOffsetOf(CanvasRec,canvas.field)
 
68
/* offset to a core-element in the widget-stucture */
 
69
#define goffset(field) XtOffsetOf(CanvasRec,core.field)
 
70
static XtResource resources[] = {
 
71
        { XtNbackground,        XtCBackground,  XtRPixel,       sizeof(Pixel),
 
72
                goffset(background_pixel),      XtRString,      "white" },
 
73
        { XtNidleCursor,        XtCCursor,      XtRCursor,      sizeof(Cursor),
 
74
                offset(idle_cursor),            XtRString,      "left_ptr" },
 
75
        { XtNbusyCursor,        XtCCursor,      XtRCursor,      sizeof(Cursor),
 
76
                offset(busy_cursor),            XtRString,      "watch" },
 
77
        { XtNcallback,          XtCCallback,     XtRCallback,   sizeof(XtPointer),
 
78
                offset(callbacks),              XtRCallback,    (XtPointer)NULL},
 
79
/*
 
80
        { XtNfont,              XtCFont,        XtRFontStruct,  sizeof(XFontStruct *),
 
81
                offset(font),                   XtRString,      XtDefaultFont },
 
82
*/
 
83
};
 
84
#undef offset
 
85
#undef goffset
 
86
 
 
87
CanvasClassRec canvasClassRec = {
 
88
  { /* core fields */
 
89
    /* superclass               */      (WidgetClass) &compositeClassRec,
 
90
    /* class_name               */      "Canvas",
 
91
    /* widget_size              */      sizeof(CanvasRec),
 
92
    /* class_initialize         */      NULL,
 
93
    /* class_part_initialize    */      NULL,
 
94
    /* class_inited             */      FALSE,
 
95
    /* initialize               */      Initialize,
 
96
    /* initialize_hook          */      NULL,
 
97
    /* realize                  */      Realize,
 
98
    /* actions                  */      actionsList,
 
99
    /* num_actions              */      XtNumber(actionsList),
 
100
    /* resources                */      resources,
 
101
    /* num_resources            */      XtNumber(resources),
 
102
    /* xrm_class                */      NULLQUARK,
 
103
    /* compress_motion          */      TRUE,
 
104
    /* compress_exposure        */      TRUE,
 
105
    /* compress_enterleave      */      TRUE,
 
106
    /* visible_interest         */      FALSE,
 
107
    /* destroy                  */      Destroy,
 
108
    /* resize                   */      Resize,
 
109
    /* expose                   */      Redisplay,
 
110
    /* set_values               */      SetValues,
 
111
    /* set_values_hook          */      NULL,
 
112
    /* set_values_almost        */      XtInheritSetValuesAlmost,
 
113
    /* get_values_hook          */      NULL,
 
114
    /* accept_focus             */      NULL,
 
115
    /* version                  */      XtVersion,
 
116
    /* callback_private         */      NULL,
 
117
    /* tm_table                 */      defaultTranslations,
 
118
    /* query_geometry           */      QueryGeometry,
 
119
    /* display_accelerator      */      XtInheritDisplayAccelerator,
 
120
    /* extension                */      NULL
 
121
  },
 
122
  { /* composite fields */
 
123
    /* geometry_manager         */      Geometry_manager,
 
124
    /* change_managed           */      XtInheritChangeManaged,
 
125
    /* insert_child             */      XtInheritInsertChild,
 
126
    /* delete_child             */      XtInheritDeleteChild,
 
127
    /* extension                */      NULL
 
128
  },
 
129
  { /* canvas fields */
 
130
    /* empty                    */      0
 
131
  }
 
132
};
 
133
 
 
134
WidgetClass canvasWidgetClass = (WidgetClass)&canvasClassRec;
 
135
 
 
136
/*
 
137
 * Initialize a widget instance by allocating graphics contexts.
 
138
 */
 
139
static void
 
140
Initialize(request, new)
 
141
Widget request, new;
 
142
{
 
143
        Display *d;
 
144
        XGCValues gcv;
 
145
        CanvasWidget w = (CanvasWidget) new;
 
146
 
 
147
        gcv.function = GXcopy;
 
148
        gcv.plane_mask = AllPlanes;
 
149
        /* the drawGC has function GXcopy as function set, that clears all
 
150
           the previous contents of the drawable used with it. */
 
151
        w->canvas.copyGC = XtGetGC((Widget) w, GCFunction | GCPlaneMask, &gcv);
 
152
 
 
153
        /* gcv.font = w->canvas.font->fid; */
 
154
        gcv.function = GXcopy;
 
155
        gcv.plane_mask = AllPlanes;
 
156
        w->canvas.drawGC = XtGetGC((Widget) w, GCFunction | GCPlaneMask, &gcv);
 
157
 
 
158
        /* finally, the clearGC simply allows to clear the drawable by
 
159
           using XFillRectangle. foreground is set equal to background */
 
160
        gcv.foreground = w->core.background_pixel;
 
161
        w->canvas.clearGC = XtGetGC((Widget) w, GCForeground, &gcv);
 
162
 
 
163
        /* create pixmap, that is copied to the window on exposes
 
164
           or on request by CanvasUpdateArea */
 
165
        d = XtDisplay(w);
 
166
        w->canvas.pxmw = w->core.width;
 
167
        w->canvas.pxmh = w->core.height;
 
168
        w->canvas.picture = XCreatePixmap(d, DefaultRootWindow(d),
 
169
                                        w->core.width, w->core.height,
 
170
                                        DefaultDepth(d, DefaultScreen(d)));
 
171
 
 
172
}
 
173
 
 
174
/*
 
175
 * Realize a widget instance.  Allocate pixmaps, create the window, etc.
 
176
 */
 
177
static void
 
178
Realize(gw, valueMask, attr)
 
179
XSetWindowAttributes *attr;
 
180
XtValueMask *valueMask;
 
181
Widget gw;
 
182
{
 
183
        CanvasWidget w = (CanvasWidget) gw;
 
184
 
 
185
        /* look if we have an idle-cursor set in the resources,
 
186
           and if so, tell the window we create about it. */
 
187
        if ((attr->cursor = w->canvas.idle_cursor) != None)
 
188
                *valueMask |= CWCursor;
 
189
 
 
190
        /* create our window */
 
191
        XtCreateWindow(gw, InputOutput, (Visual *) CopyFromParent,
 
192
                       *valueMask, attr);
 
193
 
 
194
        /* clear the cpixmap */
 
195
        canvasClearPicture(w);
 
196
}
 
197
 
 
198
/*
 
199
 * Destroy a widget instance.
 
200
 */
 
201
static void
 
202
Destroy(gw)
 
203
Widget gw;
 
204
{
 
205
        CanvasWidget w = (CanvasWidget) gw;
 
206
 
 
207
        /* release the allocated space for all the GCs... */
 
208
        XtReleaseGC((Widget) w, w->canvas.drawGC);
 
209
        XtReleaseGC((Widget) w, w->canvas.copyGC);
 
210
        XtReleaseGC((Widget) w, w->canvas.clearGC);
 
211
 
 
212
        /* ...and for the pixmaps */
 
213
        XFreePixmap(XtDisplay(w), w->canvas.picture);
 
214
}
 
215
 
 
216
/*
 
217
 * Widget was resized
 
218
 */
 
219
static void
 
220
Resize(w)
 
221
Widget w;
 
222
{
 
223
  CanvasWidget cw = (CanvasWidget) w;
 
224
 
 
225
  fprintf(stderr, "Canvas: Resize called ! wid=%u, height=%u\n",
 
226
        (unsigned)cw->core.width, (unsigned)cw->core.height);
 
227
}
 
228
 
 
229
/*
 
230
 * Geometry is queried by parent
 
231
 */
 
232
static XtGeometryResult
 
233
QueryGeometry(w, intended, preferred)
 
234
Widget w;
 
235
XtWidgetGeometry *intended, *preferred;
 
236
{
 
237
  CanvasWidget cw = (CanvasWidget) w;
 
238
 
 
239
  preferred->request_mode = CWWidth | CWHeight;
 
240
  preferred->width = cw->canvas.pxmw;
 
241
  preferred->height = cw->canvas.pxmh;
 
242
  if (preferred->width == w->core.width &&
 
243
      preferred->height == w->core.height)
 
244
    return XtGeometryNo;
 
245
  if (((intended->request_mode & (CWWidth|CWHeight)) == (CWWidth|CWHeight)) &&
 
246
        intended->width == preferred->width &&
 
247
        intended->height == preferred->height)
 
248
    return XtGeometryYes;
 
249
  return XtGeometryAlmost;
 
250
}
 
251
 
 
252
/*
 
253
 * Redisplay a widget after an expose event by copying data from the pixmaps.
 
254
 */
 
255
static void
 
256
Redisplay(gw, event, region)
 
257
Region region;
 
258
XEvent *event;
 
259
Widget gw;
 
260
{
 
261
        CanvasWidget w = (CanvasWidget) gw;
 
262
        XExposeEvent *e = (XExposeEvent *) event;
 
263
        
 
264
        canvasBusy(w);
 
265
 
 
266
        /* copy the bounding box of the exposed area from the pixmaps
 
267
           into the window to redraw the destroyed contents. */
 
268
 
 
269
        /* underlay the picture at first.... */
 
270
        XCopyArea(XtDisplay(gw), w->canvas.picture, XtWindow(gw),
 
271
                  w->canvas.copyGC, e->x, e->y,
 
272
                  (Dimension) e->width, (Dimension) e->height,
 
273
                  e->x, e->y);
 
274
  
 
275
        canvasIdle(w);
 
276
}
 
277
 
 
278
static void
 
279
Notify(w,event,params,num_params)
 
280
Widget w;
 
281
XEvent *event;
 
282
String *params;         /* unused */
 
283
Cardinal *num_params;   /* unused */
 
284
{
 
285
    static XPoint xp;
 
286
    CanvasWidget cw = (CanvasWidget)w;
 
287
 
 
288
    switch (event->type) {
 
289
        case ButtonPress:
 
290
            xp.x = event->xbutton.x;
 
291
            xp.y = event->xbutton.y;
 
292
            XtCallCallbackList(w, cw->canvas.callbacks, (XtPointer) &xp);
 
293
            break;
 
294
        default:
 
295
            XtCallCallbackList(w, cw->canvas.callbacks, (XtPointer) NULL);
 
296
            break;
 
297
    }
 
298
}
 
299
 
 
300
static Boolean
 
301
SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args)
 
302
{
 
303
  CanvasWidget curcw = (CanvasWidget) current;
 
304
  CanvasWidget reqcw = (CanvasWidget) request;
 
305
  CanvasWidget newcw = (CanvasWidget) new;
 
306
  Pixmap pxm;
 
307
  Display *d;
 
308
  Dimension oldw, oldh, neww, newh;
 
309
 
 
310
  fprintf(stderr, "Canvas: SetValues called\n");
 
311
  /* if the geometry is changed, we have to create a new pixmap. */
 
312
  oldw = curcw->canvas.pxmw;
 
313
  oldh = curcw->canvas.pxmh;
 
314
  neww = reqcw->core.width;
 
315
  newh = reqcw->core.height;
 
316
  if ((oldw != neww) || (oldh != newh)) {
 
317
    d = XtDisplay(current);
 
318
    pxm = XCreatePixmap(d, DefaultRootWindow(d),
 
319
                        neww, newh,
 
320
                        DefaultDepth(d, DefaultScreen(d)));
 
321
    /* we don't need this here because the main-program must redraw
 
322
       the screen anyway if geometry has changed. */
 
323
    /* XCopyArea(d, curcw->canvas.picture, pxm, curcw->canvas.copyGC,
 
324
                0, 0, min(neww, oldw), min(newh, oldh), 0, 0); */
 
325
    /* now free the old pixmap */
 
326
    XFreePixmap(d, curcw->canvas.picture);
 
327
    /* and set the changed values. */
 
328
    newcw->canvas.picture = pxm;
 
329
    newcw->canvas.pxmw = neww;
 
330
    newcw->canvas.pxmh = newh;
 
331
  }
 
332
  /* Redisplay needed ? I think not... */
 
333
  return False;
 
334
}
 
335
 
 
336
static XtGeometryResult
 
337
Geometry_manager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *new)
 
338
{
 
339
/*  use the following to allow geometry-changes by the child - ACZ
 
340
    if (request->request_mode & CWX)
 
341
        w->core.x = request->x;
 
342
    if (request->request_mode & CWY)
 
343
        w->core.y = request->y;
 
344
    if (request->request_mode & CWWidth)
 
345
        w->core.width = request->width;
 
346
    if (request->request_mode & CWHeight)
 
347
        w->core.height = request->height;
 
348
    if (request->request_mode & CWBorderWidth)
 
349
        w->core.border_width = request->border_width;
 
350
    return XtGeometryNo;
 
351
*/
 
352
    fprintf(stderr, "geometry manager called !\n");
 
353
    return XtGeometryYes;
 
354
}
 
355
 
 
356
/*
 
357
 * Draw line segments on the "picture" pixmap of the widget.
 
358
 */
 
359
void
 
360
canvasDrawSegmentsPicture(w, segments, nsegments)
 
361
XSegment *segments;
 
362
CanvasWidget w;
 
363
int nsegments;
 
364
{
 
365
        XDrawSegments(XtDisplay(w), w->canvas.picture, w->canvas.drawGC,
 
366
                      segments, nsegments);
 
367
}
 
368
 
 
369
/*
 
370
 * Draw a line on the "picture" pixmap of the widget.
 
371
 */
 
372
void
 
373
canvasDrawLinePicture(w, x1, y1, x2, y2)
 
374
int x1, y1, x2, y2;
 
375
CanvasWidget w;
 
376
{
 
377
        XDrawLine(XtDisplay(w), w->canvas.picture, w->canvas.drawGC,
 
378
                  x1, y1, x2, y2);
 
379
}
 
380
 
 
381
/*
 
382
 * Draw text on the "picture" pixmap of the widget.
 
383
 */
 
384
void
 
385
canvasDrawTextPicture(w, x, y, str)
 
386
CanvasWidget w;
 
387
char *str;
 
388
int x, y;
 
389
{
 
390
        XDrawString(XtDisplay(w), w->canvas.picture, w->canvas.drawGC,
 
391
                    x, y, str, strlen(str));
 
392
}
 
393
 
 
394
/*
 
395
 * Clear the "picture" pixmap of the widget.
 
396
 */
 
397
void
 
398
canvasClearPicture(w)
 
399
CanvasWidget w;
 
400
{
 
401
        XFillRectangle(XtDisplay(w), w->canvas.picture, w->canvas.clearGC,
 
402
                       0, 0, w->core.width, w->core.height);
 
403
}
 
404
 
 
405
/*
 
406
 * Update the window of the widget with the "picture" and "scratch" pixmaps.
 
407
 */
 
408
void
 
409
canvasUpdateArea(w, x, y, width, height)
 
410
CanvasWidget w;
 
411
unsigned x, y, width, height;
 
412
{
 
413
        unsigned cw, ch;
 
414
 
 
415
        cw = w->core.width;
 
416
        ch = w->core.height;
 
417
        if (x >= cw) x = cw-1;
 
418
        if (y >= ch) y = ch-1;
 
419
        if (x + width > cw) width = cw - x;
 
420
        if (y + height > ch) height = ch - y;
 
421
        /* copy the picture-pixmap onto the window */
 
422
        XCopyArea(XtDisplay(w), w->canvas.picture, XtWindow(w),
 
423
                  w->canvas.copyGC, x, y, width, height,
 
424
                  x, y);
 
425
}
 
426
 
 
427
/*
 
428
 * Get one of the GCs of the Widget
 
429
 */
 
430
GC
 
431
canvasGetGC(w, type)
 
432
CanvasWidget w;
 
433
unsigned type;
 
434
{
 
435
    switch(type) {
 
436
        case CanvasDrawGC:  return (w->canvas.drawGC);
 
437
        case CanvasCopyGC:  return (w->canvas.copyGC);
 
438
        case CanvasClearGC: return (w->canvas.clearGC);
 
439
        default: return (GC)NULL;
 
440
    }
 
441
}
 
442
 
 
443
/*
 
444
 * Get one of the Pixmaps of the Widget
 
445
 */
 
446
Pixmap
 
447
canvasGetPixmap(w, type)
 
448
CanvasWidget w;
 
449
unsigned type;
 
450
{
 
451
    switch(type) {
 
452
        case CanvasPicture:   return (w->canvas.picture);
 
453
        default: return (Pixmap)NULL;
 
454
    }
 
455
}
 
456
 
 
457
/*
 
458
 * Set the cursor to the busy cursor.
 
459
 */
 
460
void
 
461
canvasBusy(w)
 
462
CanvasWidget w;
 
463
{
 
464
        XSetWindowAttributes attr;
 
465
 
 
466
        if ((attr.cursor = w->canvas.busy_cursor) != None) {
 
467
                XChangeWindowAttributes(XtDisplay(w), XtWindow(w),
 
468
                                        CWCursor, &attr);
 
469
                XFlush(XtDisplay(w));
 
470
        }
 
471
}
 
472
 
 
473
/*
 
474
 * Set the cursor to the idle cursor.
 
475
 */
 
476
void
 
477
canvasIdle(w)
 
478
CanvasWidget w;
 
479
{
 
480
        XSetWindowAttributes attr;
 
481
 
 
482
        if ((attr.cursor = w->canvas.idle_cursor) != None) {
 
483
                XChangeWindowAttributes(XtDisplay(w), XtWindow(w),
 
484
                                        CWCursor, &attr);
 
485
                XFlush(XtDisplay(w));
 
486
        }
 
487
}