~ubuntu-branches/ubuntu/karmic/scilab/karmic

« back to all changes in this revision

Viewing changes to routines/X11/Xaw/StripChart.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-21 16:57:43 UTC
  • Revision ID: james.westby@ubuntu.com-20020321165743-e9mv12c1tb1plztg
Tags: upstream-2.6
ImportĀ upstreamĀ versionĀ 2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XConsortium: StripChart.c,v 1.20 91/05/24 17:20:42 converse Exp $ */
 
2
 
 
3
/***********************************************************
 
4
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
 
5
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
 
6
 
 
7
                        All Rights Reserved
 
8
 
 
9
Permission to use, copy, modify, and distribute this software and its 
 
10
documentation for any purpose and without fee is hereby granted, 
 
11
provided that the above copyright notice appear in all copies and that
 
12
both that copyright notice and this permission notice appear in 
 
13
supporting documentation, and that the names of Digital or MIT not be
 
14
used in advertising or publicity pertaining to distribution of the
 
15
software without specific, written prior permission.  
 
16
 
 
17
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
18
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
19
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
20
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
21
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
22
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
23
SOFTWARE.
 
24
 
 
25
******************************************************************/
 
26
 
 
27
#include <stdio.h>
 
28
#include <X11/IntrinsicP.h>
 
29
#include <X11/StringDefs.h>
 
30
#include <X11/Xaw/XawInit.h>
 
31
#include <X11/Xaw/StripCharP.h>
 
32
#include <X11/Xfuncs.h>
 
33
 
 
34
#define MS_PER_SEC 1000
 
35
 
 
36
/* Private Data */
 
37
 
 
38
#define offset(field) XtOffsetOf(StripChartRec, field)
 
39
 
 
40
static XtResource resources[] = {
 
41
    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
 
42
        offset(core.width), XtRImmediate, (XtPointer) 120},
 
43
    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
 
44
        offset(core.height), XtRImmediate, (XtPointer) 120},
 
45
    {XtNupdate, XtCInterval, XtRInt, sizeof(int),
 
46
        offset(strip_chart.update), XtRImmediate, (XtPointer) 10},
 
47
    {XtNminScale, XtCScale, XtRInt, sizeof(int),
 
48
        offset(strip_chart.min_scale), XtRImmediate, (XtPointer) 1},
 
49
    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
 
50
        offset(strip_chart.fgpixel), XtRString, XtDefaultForeground},
 
51
    {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
 
52
        offset(strip_chart.hipixel), XtRString, XtDefaultForeground},
 
53
    {XtNgetValue, XtCCallback, XtRCallback, sizeof(XtPointer),
 
54
        offset(strip_chart.get_value), XtRImmediate, (XtPointer) NULL},
 
55
    {XtNjumpScroll, XtCJumpScroll, XtRInt, sizeof(int),
 
56
        offset(strip_chart.jump_val), XtRImmediate, (XtPointer) DEFAULT_JUMP},
 
57
};
 
58
 
 
59
#undef offset
 
60
 
 
61
static void Initialize(), Destroy(), Redisplay(), MoveChart(), SetPoints();
 
62
static Boolean SetValues();
 
63
static int repaint_window();
 
64
 
 
65
StripChartClassRec stripChartClassRec = {
 
66
    { /* core fields */
 
67
    /* superclass               */      (WidgetClass) &simpleClassRec,
 
68
    /* class_name               */      "StripChart",
 
69
    /* size                     */      sizeof(StripChartRec),
 
70
    /* class_initialize         */      XawInitializeWidgetSet,
 
71
    /* class_part_initialize    */      NULL,
 
72
    /* class_inited             */      FALSE,
 
73
    /* initialize               */      Initialize,
 
74
    /* initialize_hook          */      NULL,
 
75
    /* realize                  */      XtInheritRealize,
 
76
    /* actions                  */      NULL,
 
77
    /* num_actions              */      0,
 
78
    /* resources                */      resources,
 
79
    /* num_resources            */      XtNumber(resources),
 
80
    /* xrm_class                */      NULLQUARK,
 
81
    /* compress_motion          */      TRUE,
 
82
    /* compress_exposure        */      XtExposeCompressMultiple |
 
83
                                        XtExposeGraphicsExposeMerged,
 
84
    /* compress_enterleave      */      TRUE,
 
85
    /* visible_interest         */      FALSE,
 
86
    /* destroy                  */      Destroy,
 
87
    /* resize                   */      SetPoints,
 
88
    /* expose                   */      Redisplay,
 
89
    /* set_values               */      SetValues,
 
90
    /* set_values_hook          */      NULL,
 
91
    /* set_values_almost        */      NULL,
 
92
    /* get_values_hook          */      NULL,
 
93
    /* accept_focus             */      NULL,
 
94
    /* version                  */      XtVersion,
 
95
    /* callback_private         */      NULL,
 
96
    /* tm_table                 */      NULL,
 
97
    /* query_geometry           */      XtInheritQueryGeometry,
 
98
    /* display_accelerator      */      XtInheritDisplayAccelerator,
 
99
    /* extension                */      NULL
 
100
    },
 
101
    { /* Simple class fields */
 
102
    /* change_sensitive         */      XtInheritChangeSensitive
 
103
    }
 
104
};
 
105
 
 
106
WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec;
 
107
 
 
108
/****************************************************************
 
109
 *
 
110
 * Private Procedures
 
111
 *
 
112
 ****************************************************************/
 
113
 
 
114
static void draw_it();
 
115
 
 
116
/*      Function Name: CreateGC
 
117
 *      Description: Creates the GC's
 
118
 *      Arguments: w - the strip chart widget.
 
119
 *                 which - which GC's to create.
 
120
 *      Returns: none
 
121
 */
 
122
 
 
123
static void
 
124
CreateGC(w, which)
 
125
StripChartWidget w;
 
126
unsigned int which;
 
127
{
 
128
  XGCValues     myXGCV;
 
129
 
 
130
  if (which & FOREGROUND) {
 
131
    myXGCV.foreground = w->strip_chart.fgpixel;
 
132
    w->strip_chart.fgGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
 
133
  }
 
134
 
 
135
  if (which & HIGHLIGHT) {
 
136
    myXGCV.foreground = w->strip_chart.hipixel;
 
137
    w->strip_chart.hiGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
 
138
  }
 
139
}
 
140
 
 
141
/*      Function Name: DestroyGC
 
142
 *      Description: Destroys the GC's
 
143
 *      Arguments: w - the strip chart widget.
 
144
 *                 which - which GC's to destroy.
 
145
 *      Returns: none
 
146
 */
 
147
 
 
148
static void
 
149
DestroyGC(w, which)
 
150
StripChartWidget w;
 
151
unsigned int which;
 
152
{
 
153
  if (which & FOREGROUND) 
 
154
    XtReleaseGC((Widget) w, w->strip_chart.fgGC);
 
155
 
 
156
  if (which & HIGHLIGHT) 
 
157
    XtReleaseGC((Widget) w, w->strip_chart.hiGC);
 
158
}
 
159
 
 
160
/* ARGSUSED */
 
161
static void Initialize (greq, gnew)
 
162
    Widget greq, gnew;
 
163
{
 
164
    StripChartWidget w = (StripChartWidget)gnew;
 
165
 
 
166
    if (w->strip_chart.update > 0)
 
167
        w->strip_chart.interval_id = XtAppAddTimeOut( 
 
168
                                        XtWidgetToApplicationContext(gnew),
 
169
                                        w->strip_chart.update * MS_PER_SEC, 
 
170
                                        draw_it, (XtPointer) gnew);
 
171
    CreateGC(w, (unsigned int) ALL_GCS);
 
172
 
 
173
    w->strip_chart.scale = w->strip_chart.min_scale;
 
174
    w->strip_chart.interval = 0;
 
175
    w->strip_chart.max_value = 0.0;
 
176
    w->strip_chart.points = NULL;
 
177
    SetPoints(w);
 
178
}
 
179
 
 
180
static void Destroy (gw)
 
181
     Widget gw;
 
182
{
 
183
     StripChartWidget w = (StripChartWidget)gw;
 
184
 
 
185
     if (w->strip_chart.update > 0)
 
186
         XtRemoveTimeOut (w->strip_chart.interval_id);
 
187
     if (w->strip_chart.points)
 
188
         XtFree((char *) w->strip_chart.points);
 
189
     DestroyGC(w, (unsigned int) ALL_GCS);
 
190
}
 
191
 
 
192
/*
 
193
 * NOTE: This function really needs to recieve graphics exposure 
 
194
 *       events, but since this is not easily supported until R4 I am
 
195
 *       going to hold off until then.
 
196
 */
 
197
 
 
198
/* ARGSUSED */
 
199
static void Redisplay(w, event, region)
 
200
     Widget w;
 
201
     XEvent *event;
 
202
     Region region;
 
203
{
 
204
    if (event->type == GraphicsExpose)
 
205
        (void) repaint_window ((StripChartWidget)w, event->xgraphicsexpose.x,
 
206
                               event->xgraphicsexpose.width);
 
207
    else
 
208
        (void) repaint_window ((StripChartWidget)w, event->xexpose.x,
 
209
                               event->xexpose.width);
 
210
}
 
211
 
 
212
/* ARGSUSED */
 
213
static void 
 
214
draw_it(client_data, id)
 
215
XtPointer client_data;
 
216
XtIntervalId *id;               /* unused */
 
217
{
 
218
   StripChartWidget w = (StripChartWidget)client_data;
 
219
   double value;
 
220
   
 
221
   if (w->strip_chart.update > 0)
 
222
       w->strip_chart.interval_id =
 
223
       XtAppAddTimeOut(XtWidgetToApplicationContext( (Widget) w),
 
224
                       w->strip_chart.update * MS_PER_SEC,draw_it,client_data);
 
225
 
 
226
   if (w->strip_chart.interval >= (int)w->core.width)
 
227
       MoveChart( (StripChartWidget) w, TRUE);
 
228
 
 
229
   /* Get the value, stash the point and draw corresponding line. */
 
230
 
 
231
   if (w->strip_chart.get_value == NULL)
 
232
       return;
 
233
 
 
234
   XtCallCallbacks( (Widget)w, XtNgetValue, (XtPointer)&value );
 
235
 
 
236
   /* 
 
237
    * Keep w->strip_chart.max_value up to date, and if this data 
 
238
    * point is off the graph, change the scale to make it fit. 
 
239
    */
 
240
   
 
241
   if (value > w->strip_chart.max_value) {
 
242
       w->strip_chart.max_value = value;
 
243
       if (w->strip_chart.max_value > w->strip_chart.scale) {
 
244
           XClearWindow( XtDisplay (w), XtWindow (w));
 
245
           w->strip_chart.interval = repaint_window(w, 0, (int) w->core.width);
 
246
       }
 
247
   }
 
248
 
 
249
   w->strip_chart.valuedata[w->strip_chart.interval] = value;
 
250
   if (XtIsRealized((Widget)w)) {
 
251
       int y = (int) (w->core.height
 
252
                      - (int)(w->core.height * value) / w->strip_chart.scale);
 
253
 
 
254
       XFillRectangle(XtDisplay(w), XtWindow(w), w->strip_chart.fgGC,
 
255
                      w->strip_chart.interval, y, 
 
256
                      (unsigned int) 1, w->core.height - y);
 
257
       /*
 
258
        * Fill in the graph lines we just painted over.
 
259
        */
 
260
 
 
261
       if (w->strip_chart.points != NULL) {
 
262
           w->strip_chart.points[0].x = w->strip_chart.interval;
 
263
           XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC,
 
264
                       w->strip_chart.points, w->strip_chart.scale - 1,
 
265
                       CoordModePrevious);
 
266
       }
 
267
 
 
268
       XFlush(XtDisplay(w));                /* Flush output buffers */
 
269
   }
 
270
   w->strip_chart.interval++;               /* Next point */
 
271
} /* draw_it */
 
272
 
 
273
/* Blts data according to current size, then redraws the stripChart window.
 
274
 * Next represents the number of valid points in data.  Returns the (possibly)
 
275
 * adjusted value of next.  If next is 0, this routine draws an empty window
 
276
 * (scale - 1 lines for graph).  If next is less than the current window width,
 
277
 * the returned value is identical to the initial value of next and data is
 
278
 * unchanged.  Otherwise keeps half a window's worth of data.  If data is
 
279
 * changed, then w->strip_chart.max_value is updated to reflect the
 
280
 * largest data point.
 
281
 */
 
282
 
 
283
static int 
 
284
repaint_window(w, left, width)
 
285
StripChartWidget w;
 
286
int left, width;
 
287
{
 
288
    register int i, j;
 
289
    register int next = w->strip_chart.interval;
 
290
    int scale = w->strip_chart.scale;
 
291
    int scalewidth = 0;
 
292
 
 
293
    /* Compute the minimum scale required to graph the data, but don't go
 
294
       lower than min_scale. */
 
295
    if (w->strip_chart.interval != 0 || scale <= (int)w->strip_chart.max_value)
 
296
      scale = ((int) (w->strip_chart.max_value)) + 1;
 
297
    if (scale < w->strip_chart.min_scale)
 
298
      scale = w->strip_chart.min_scale;
 
299
 
 
300
    if (scale != w->strip_chart.scale) {
 
301
      w->strip_chart.scale = scale;
 
302
      left = 0;
 
303
      width = next;
 
304
      scalewidth = w->core.width;
 
305
 
 
306
      SetPoints(w);
 
307
 
 
308
      if (XtIsRealized ((Widget) w)) 
 
309
        XClearWindow (XtDisplay (w), XtWindow (w));
 
310
 
 
311
    }
 
312
 
 
313
    if (XtIsRealized((Widget)w)) {
 
314
        Display *dpy = XtDisplay(w);
 
315
        Window win = XtWindow(w);
 
316
 
 
317
        width += left - 1;
 
318
        if (!scalewidth) scalewidth = width;
 
319
 
 
320
        if (next < ++width) width = next;
 
321
 
 
322
        /* Draw data point lines. */
 
323
        for (i = left; i < width; i++) {
 
324
            int y = (int) (w->core.height -
 
325
                           (int)(w->core.height * w->strip_chart.valuedata[i]) /
 
326
                           w->strip_chart.scale);
 
327
 
 
328
            XFillRectangle(dpy, win, w->strip_chart.fgGC, 
 
329
                           i, y, (unsigned int) 1,
 
330
                           (unsigned int) (w->core.height - y));
 
331
        }
 
332
 
 
333
        /* Draw graph reference lines */
 
334
        for (i = 1; i < w->strip_chart.scale; i++) {
 
335
            j = i * ((int)w->core.height / w->strip_chart.scale);
 
336
            XDrawLine(dpy, win, w->strip_chart.hiGC, left, j, scalewidth, j);
 
337
        }
 
338
    }
 
339
    return(next);
 
340
}
 
341
 
 
342
/*      Function Name: MoveChart
 
343
 *      Description: moves the chart over when it would run off the end.
 
344
 *      Arguments: w - the load widget.
 
345
 *                 blit - blit the bits? (TRUE/FALSE).
 
346
 *      Returns: none.
 
347
 */
 
348
 
 
349
static void
 
350
MoveChart(w, blit)
 
351
StripChartWidget w;
 
352
Boolean blit;
 
353
{
 
354
    double old_max;
 
355
    int left, i, j;
 
356
    register int next = w->strip_chart.interval;
 
357
 
 
358
    if (!XtIsRealized((Widget) w)) return;
 
359
 
 
360
    if (w->strip_chart.jump_val == DEFAULT_JUMP)
 
361
        j = w->core.width >> 1; /* Half the window width. */
 
362
    else {
 
363
        j = w->core.width - w->strip_chart.jump_val;
 
364
        if (j < 0) j = 0;
 
365
    }
 
366
 
 
367
    bcopy((char *)(w->strip_chart.valuedata + next - j),
 
368
          (char *)(w->strip_chart.valuedata), j * sizeof(double));
 
369
    next = w->strip_chart.interval = j;
 
370
        
 
371
    /*
 
372
     * Since we just lost some data, recompute the 
 
373
     * w->strip_chart.max_value. 
 
374
     */
 
375
 
 
376
    old_max = w->strip_chart.max_value;
 
377
    w->strip_chart.max_value = 0.0;
 
378
    for (i = 0; i < next; i++) {
 
379
      if (w->strip_chart.valuedata[i] > w->strip_chart.max_value) 
 
380
        w->strip_chart.max_value = w->strip_chart.valuedata[i];
 
381
    }
 
382
 
 
383
    if (!blit) return;          /* we are done... */
 
384
 
 
385
    if ( ((int) old_max) != ( (int) w->strip_chart.max_value) ) {
 
386
      XClearWindow(XtDisplay(w), XtWindow(w));
 
387
      repaint_window(w, 0, (int) w->core.width);
 
388
      return;
 
389
    }
 
390
 
 
391
    XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w),
 
392
              w->strip_chart.hiGC, (int) w->core.width - j, 0,
 
393
              (unsigned int) j, (unsigned int) w->core.height,
 
394
              0, 0);
 
395
 
 
396
    XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w), 
 
397
               (int) j, 0, 
 
398
               (unsigned int) w->core.width - j, (unsigned int)w->core.height,
 
399
               FALSE);
 
400
 
 
401
    /* Draw graph reference lines */
 
402
    left = j;
 
403
    for (i = 1; i < w->strip_chart.scale; i++) {
 
404
      j = i * ((int)w->core.height / w->strip_chart.scale);
 
405
      XDrawLine(XtDisplay((Widget) w), XtWindow( (Widget) w),
 
406
                w->strip_chart.hiGC, left, j, (int)w->core.width, j);
 
407
    }
 
408
    return;
 
409
}
 
410
 
 
411
/* ARGSUSED */
 
412
static Boolean SetValues (current, request, new)
 
413
    Widget current, request, new;
 
414
{
 
415
    StripChartWidget old = (StripChartWidget)current;
 
416
    StripChartWidget w = (StripChartWidget)new;
 
417
    Boolean ret_val = FALSE;
 
418
    unsigned int new_gc = NO_GCS;
 
419
 
 
420
    if (w->strip_chart.update != old->strip_chart.update) {
 
421
        if (old->strip_chart.update > 0)
 
422
            XtRemoveTimeOut (old->strip_chart.interval_id);
 
423
        if (w->strip_chart.update > 0)
 
424
            w->strip_chart.interval_id =
 
425
                XtAppAddTimeOut(XtWidgetToApplicationContext(new),
 
426
                                w->strip_chart.update * MS_PER_SEC,
 
427
                                draw_it, (XtPointer)w);
 
428
    }
 
429
 
 
430
    if ( w->strip_chart.min_scale > (int) ((w->strip_chart.max_value) + 1) )
 
431
      ret_val = TRUE;
 
432
     
 
433
    if ( w->strip_chart.fgpixel != old->strip_chart.fgpixel ) {
 
434
      new_gc |= FOREGROUND;
 
435
      ret_val = True;
 
436
    }
 
437
    
 
438
    if ( w->strip_chart.hipixel != old->strip_chart.hipixel ) {
 
439
      new_gc |= HIGHLIGHT;
 
440
      ret_val = True;
 
441
    }
 
442
    
 
443
    DestroyGC(old, new_gc);
 
444
    CreateGC(w, new_gc);
 
445
 
 
446
    return( ret_val );
 
447
}
 
448
 
 
449
/*      Function Name: SetPoints
 
450
 *      Description: Sets up the polypoint that will be used to draw in
 
451
 *                   the graph lines.
 
452
 *      Arguments: w - the StripChart widget.
 
453
 *      Returns: none.
 
454
 */
 
455
 
 
456
#define HEIGHT ( (unsigned int) w->core.height)
 
457
 
 
458
static void
 
459
SetPoints(w)
 
460
StripChartWidget w;
 
461
{
 
462
    XPoint * points;
 
463
    Cardinal size;
 
464
    int i;
 
465
 
 
466
    if (w->strip_chart.scale <= 1) { /* no scale lines. */
 
467
        XtFree ((char *) w->strip_chart.points);
 
468
        w->strip_chart.points = NULL;
 
469
        return;
 
470
    }
 
471
    
 
472
    size = sizeof(XPoint) * (w->strip_chart.scale - 1);
 
473
 
 
474
    points = (XPoint *) XtRealloc( (XtPointer) w->strip_chart.points, size);
 
475
    w->strip_chart.points = points;
 
476
 
 
477
    /* Draw graph reference lines into clip mask */
 
478
 
 
479
    for (i = 1; i < w->strip_chart.scale; i++) {
 
480
        points[i - 1].x = 0;
 
481
        points[i - 1].y = HEIGHT / w->strip_chart.scale;
 
482
    }
 
483
}