summaryrefslogtreecommitdiff
path: root/src/StripChart.c
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2011-08-01 21:22:31 -0400
committerMatt Turner <mattst88@gmail.com>2011-08-01 21:22:31 -0400
commit9814d1217f19449b59ff0c1de1b8e7850e95d0fa (patch)
treeb2832ae672ce14807efe23d3be12418595b5d88d /src/StripChart.c
parent7bbcf240f6c6999715db6e1f4c530939cf91340e (diff)
Move sources to src/.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Diffstat (limited to 'src/StripChart.c')
-rw-r--r--src/StripChart.c556
1 files changed, 556 insertions, 0 deletions
diff --git a/src/StripChart.c b/src/StripChart.c
new file mode 100644
index 0000000..5344f97
--- /dev/null
+++ b/src/StripChart.c
@@ -0,0 +1,556 @@
+/* $XConsortium: StripChart.c,v 1.25 94/04/17 20:12:56 kaleb Exp $ */
+
+/***********************************************************
+
+Copyright (c) 1987, 1988, 1994 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#include <stdio.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw3d/XawInit.h>
+#include <X11/Xaw3d/StripCharP.h>
+#include <X11/Xfuncs.h>
+
+#define MS_PER_SEC 1000
+
+/* Private Data */
+
+#define offset(field) XtOffsetOf(StripChartRec, field)
+
+static XtResource resources[] = {
+ {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
+ offset(core.width), XtRImmediate, (XtPointer) 120},
+ {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
+ offset(core.height), XtRImmediate, (XtPointer) 120},
+ {XtNupdate, XtCInterval, XtRInt, sizeof(int),
+ offset(strip_chart.update), XtRImmediate, (XtPointer) 10},
+ {XtNminScale, XtCScale, XtRInt, sizeof(int),
+ offset(strip_chart.min_scale), XtRImmediate, (XtPointer) 1},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ offset(strip_chart.fgpixel), XtRString, XtDefaultForeground},
+ {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
+ offset(strip_chart.hipixel), XtRString, XtDefaultForeground},
+ {XtNgetValue, XtCCallback, XtRCallback, sizeof(XtPointer),
+ offset(strip_chart.get_value), XtRImmediate, (XtPointer) NULL},
+ {XtNjumpScroll, XtCJumpScroll, XtRInt, sizeof(int),
+ offset(strip_chart.jump_val), XtRImmediate, (XtPointer) DEFAULT_JUMP},
+};
+
+#undef offset
+
+static void Initialize(), Destroy(), Redisplay(), MoveChart(), SetPoints();
+static Boolean SetValues();
+static int repaint_window();
+
+StripChartClassRec stripChartClassRec = {
+ { /* core fields */
+ /* superclass */ (WidgetClass) &threeDClassRec,
+ /* class_name */ "StripChart",
+ /* size */ sizeof(StripChartRec),
+ /* class_initialize */ XawInitializeWidgetSet,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ XtInheritRealize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ XtExposeCompressMultiple |
+ XtExposeGraphicsExposeMerged,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ SetPoints,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ NULL,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ { /* Simple class fields */
+ /* change_sensitive */ XtInheritChangeSensitive
+ },
+ { /* ThreeD fields */
+ /* shadowdraw */ XtInheritXaw3dShadowDraw
+ },
+ { /* Stripchart fields */
+ /* ignore */ 0
+ }
+};
+
+WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec;
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+static void draw_it();
+
+/* Function Name: CreateGC
+ * Description: Creates the GC's
+ * Arguments: w - the strip chart widget.
+ * which - which GC's to create.
+ * Returns: none
+ */
+
+static void
+CreateGC(w, which)
+StripChartWidget w;
+unsigned int which;
+{
+ XGCValues myXGCV;
+
+ if (which & FOREGROUND) {
+ myXGCV.foreground = w->strip_chart.fgpixel;
+ w->strip_chart.fgGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
+ }
+
+ if (which & HIGHLIGHT) {
+ myXGCV.foreground = w->strip_chart.hipixel;
+ w->strip_chart.hiGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
+ }
+}
+
+/* Function Name: DestroyGC
+ * Description: Destroys the GC's
+ * Arguments: w - the strip chart widget.
+ * which - which GC's to destroy.
+ * Returns: none
+ */
+
+static void
+DestroyGC(w, which)
+StripChartWidget w;
+unsigned int which;
+{
+ if (which & FOREGROUND)
+ XtReleaseGC((Widget) w, w->strip_chart.fgGC);
+
+ if (which & HIGHLIGHT)
+ XtReleaseGC((Widget) w, w->strip_chart.hiGC);
+}
+
+/* ARGSUSED */
+static void Initialize (greq, gnew, args, num_args)
+ Widget greq, gnew;
+ ArgList args;
+ Cardinal *num_args;
+{
+ StripChartWidget w = (StripChartWidget)gnew;
+
+ if (w->strip_chart.update > 0)
+ w->strip_chart.interval_id =
+ XtAppAddTimeOut( XtWidgetToApplicationContext(gnew),
+ (unsigned long) w->strip_chart.update * MS_PER_SEC,
+ draw_it, (XtPointer) gnew);
+ CreateGC(w, (unsigned int) ALL_GCS);
+
+ w->strip_chart.scale = w->strip_chart.min_scale;
+ w->strip_chart.interval = 0;
+ w->strip_chart.max_value = 0.0;
+ w->strip_chart.points = NULL;
+ SetPoints((Widget)w);
+}
+
+static void Destroy (gw)
+ Widget gw;
+{
+ StripChartWidget w = (StripChartWidget)gw;
+
+ if (w->strip_chart.update > 0)
+ XtRemoveTimeOut (w->strip_chart.interval_id);
+ if (w->strip_chart.points)
+ XtFree((char *) w->strip_chart.points);
+ DestroyGC(w, (unsigned int) ALL_GCS);
+}
+
+/*
+ * NOTE: This function really needs to recieve graphics exposure
+ * events, but since this is not easily supported until R4 I am
+ * going to hold off until then.
+ */
+
+/* ARGSUSED */
+static void Redisplay(gw, event, region)
+ Widget gw;
+ XEvent *event;
+ Region region;
+{
+
+ StripChartWidget w = (StripChartWidget)gw;
+ StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass (gw);
+ Dimension x, width, s = w->threeD.shadow_width;
+
+ (*swclass->threeD_class.shadowdraw) (gw, event, region, w->threeD.relief, FALSE);
+
+ if (event->type == GraphicsExpose) {
+ x = event->xgraphicsexpose.x;
+ width = event->xgraphicsexpose.width;
+ } else {
+ x = event->xexpose.x;
+ width = event->xexpose.width;
+ }
+ if (x > s) x -= s; /* respect shadow width, but don't become negative */
+ else x = 0;
+ if (x + width > w->core.width - 2 * s) /* ditto for right boundary */
+ width = w->core.width - 2 * s - x;
+
+ (void) repaint_window (gw, x, width);
+}
+
+/* ARGSUSED */
+static void
+draw_it(client_data, id)
+XtPointer client_data;
+XtIntervalId *id; /* unused */
+{
+ StripChartWidget w = (StripChartWidget)client_data;
+ StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w);
+ Dimension s = w->threeD.shadow_width;
+ double value;
+
+ if (w->strip_chart.update > 0)
+ w->strip_chart.interval_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext( (Widget) w),
+ (unsigned long) w->strip_chart.update * MS_PER_SEC,
+ draw_it, client_data);
+
+ if (w->strip_chart.interval >= (int)( w->core.width - 2 * s))
+ MoveChart( (StripChartWidget) w, TRUE);
+
+ /* Get the value, stash the point and draw corresponding line. */
+
+ if (w->strip_chart.get_value == NULL)
+ return;
+
+ XtCallCallbacks( (Widget)w, XtNgetValue, (XtPointer)&value );
+
+ /*
+ * Keep w->strip_chart.max_value up to date, and if this data
+ * point is off the graph, change the scale to make it fit.
+ */
+
+ if (value > w->strip_chart.max_value) {
+ w->strip_chart.max_value = value;
+ if (XtIsRealized((Widget)w) &&
+ w->strip_chart.max_value > w->strip_chart.scale) {
+ XClearWindow(XtDisplay ((Widget) w), XtWindow ((Widget) w));
+ w->strip_chart.interval = repaint_window((Widget)w, 0, (int) w->core.width - 2 * s);
+ (*swclass->threeD_class.shadowdraw) ((Widget) w,
+ (XEvent *)0, (Region)0,
+ w->threeD.relief, FALSE);
+ }
+ }
+
+ w->strip_chart.valuedata[w->strip_chart.interval] = value;
+ if (XtIsRealized((Widget)w)) {
+ int y = (int) (( w->core.height - 2 * s)
+ - (int)(( w->core.height - 2 * s) * value) / w->strip_chart.scale);
+
+ XFillRectangle(XtDisplay((Widget) w), XtWindow((Widget) w), w->strip_chart.fgGC,
+ w->strip_chart.interval + s,
+ y + s, (unsigned int) 1,
+ (w->core.height - 2 * s) - y);
+ /*
+ * Fill in the graph lines we just painted over.
+ */
+
+ if (w->strip_chart.points != NULL) {
+ w->strip_chart.points[0].x = w->strip_chart.interval + s;
+ XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC,
+ w->strip_chart.points, w->strip_chart.scale,
+ CoordModePrevious);
+ }
+
+ XFlush(XtDisplay(w)); /* Flush output buffers */
+ }
+ w->strip_chart.interval++; /* Next point */
+} /* draw_it */
+
+/* Blts data according to current size, then redraws the stripChart window.
+ * Next represents the number of valid points in data. Returns the (possibly)
+ * adjusted value of next. If next is 0, this routine draws an empty window
+ * (scale - 1 lines for graph). If next is less than the current window width,
+ * the returned value is identical to the initial value of next and data is
+ * unchanged. Otherwise keeps half a window's worth of data. If data is
+ * changed, then w->strip_chart.max_value is updated to reflect the
+ * largest data point.
+ */
+
+static int
+repaint_window(gw, left, width)
+Widget gw;
+int left, width;
+{
+ StripChartWidget w = (StripChartWidget) gw;
+ Dimension s = w->threeD.shadow_width;
+ StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w);
+ int i, j;
+ int next = w->strip_chart.interval;
+ int scale = w->strip_chart.scale;
+ int scalewidth = 0;
+
+ /* Compute the minimum scale required to graph the data, but don't go
+ lower than min_scale. */
+ if (w->strip_chart.interval != 0 || scale <= (int)w->strip_chart.max_value)
+ scale = ((int) (w->strip_chart.max_value)) + 1;
+ if (scale < w->strip_chart.min_scale)
+ scale = w->strip_chart.min_scale;
+
+ if (scale != w->strip_chart.scale) {
+ w->strip_chart.scale = scale;
+ left = 0;
+ width = next; /* check this */
+ scalewidth = w->core.width - 2 * s;
+
+ SetPoints(gw);
+
+ if (XtIsRealized (gw)) {
+ XClearWindow (XtDisplay (gw), XtWindow (gw));
+ (*swclass->threeD_class.shadowdraw) (gw, (XEvent *)0, (Region)0, w->threeD.relief, FALSE);
+ }
+
+ }
+
+ if (XtIsRealized(gw)) {
+ Display *dpy = XtDisplay(gw);
+ Window win = XtWindow(gw);
+
+ width += left - 1;
+ if (!scalewidth) scalewidth = width;
+
+ if (next < (++width - s)) width = next + s;
+
+ /* Draw data point lines. */
+ for (i = left; i < width; i++) {
+ int y = (int) (( w->core.height - 2 * s) -
+ (int)(( w->core.height - 2 * s) * w->strip_chart.valuedata[i]) /
+ w->strip_chart.scale);
+
+ XFillRectangle(dpy, win, w->strip_chart.fgGC,
+ i + s, y + s, (unsigned int) 1,
+ (unsigned int) (w->core.height - 2 * s - y ));
+ }
+
+ /* Draw graph reference lines */
+ for (i = 1; i < w->strip_chart.scale; i++) {
+ j = i * ((w->core.height - 2 * s) / w->strip_chart.scale);
+ XDrawLine(dpy, win, w->strip_chart.hiGC,
+ left + s, j + s, scalewidth + s, j + s);
+ }
+ }
+ return(next);
+}
+
+/* Function Name: MoveChart
+ * Description: moves the chart over when it would run off the end.
+ * Arguments: w - the load widget.
+ * blit - blit the bits? (TRUE/FALSE).
+ * Returns: none.
+ */
+
+static void
+MoveChart(w, blit)
+StripChartWidget w;
+Boolean blit;
+{
+ Dimension s = w->threeD.shadow_width;
+ double old_max;
+ int left, i, j;
+ int next = w->strip_chart.interval;
+
+ if (!XtIsRealized((Widget) w)) return;
+
+ if (w->strip_chart.jump_val < 0) w->strip_chart.jump_val = DEFAULT_JUMP;
+ if (w->strip_chart.jump_val == DEFAULT_JUMP)
+ j = ( w->core.width - 2 * s) / 2; /* Half the window width. */
+ else {
+ j = ( w->core.width - 2 * s) - w->strip_chart.jump_val;
+ if (j < 0) j = 0;
+ }
+
+ (void) memmove((char *)(w->strip_chart.valuedata),
+ (char *)(w->strip_chart.valuedata + next - j),
+ j * sizeof(double));
+ next = w->strip_chart.interval = j;
+
+ /*
+ * Since we just lost some data, recompute the
+ * w->strip_chart.max_value.
+ */
+
+ old_max = w->strip_chart.max_value;
+ w->strip_chart.max_value = 0.0;
+ for (i = 0; i < next; i++) {
+ if (w->strip_chart.valuedata[i] > w->strip_chart.max_value)
+ w->strip_chart.max_value = w->strip_chart.valuedata[i];
+ }
+
+ if (!blit) return; /* we are done... */
+
+ if ( ((int) old_max) != ( (int) w->strip_chart.max_value) ) {
+ XClearWindow(XtDisplay(w), XtWindow(w));
+ repaint_window((Widget)w, 0, w->core.width - 2 * s);
+ return;
+ }
+
+ XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w),
+ w->strip_chart.hiGC,
+ (int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ?
+ (j + s) : (w->strip_chart.jump_val + s)), s,
+ (unsigned int) j, (unsigned int) ( w->core.height - 2 * s),
+ s, s);
+
+ XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w),
+ (int) j + s, s,
+ (unsigned int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ?
+ j : w->strip_chart.jump_val),
+ (unsigned int) ( w->core.height - 2 * s),
+ FALSE);
+
+ /* Draw graph reference lines */
+ left = j;
+ for (i = 1; i < w->strip_chart.scale; i++) {
+ j = i * ((w->core.height - 2 * s) / w->strip_chart.scale);
+ XDrawLine(XtDisplay((Widget) w), XtWindow( (Widget) w),
+ w->strip_chart.hiGC,
+ left, j + s, ((int)w->core.width - s - 1), j + s);
+ }
+ return;
+}
+
+/* ARGSUSED */
+static Boolean SetValues (current, request, new, args, num_args)
+ Widget current, request, new;
+ ArgList args;
+ Cardinal *num_args;
+{
+ StripChartWidget old = (StripChartWidget)current;
+ StripChartWidget w = (StripChartWidget)new;
+ Boolean ret_val = FALSE;
+ unsigned int new_gc = NO_GCS;
+
+ if (w->strip_chart.update != old->strip_chart.update) {
+ if (old->strip_chart.update > 0)
+ XtRemoveTimeOut (old->strip_chart.interval_id);
+ if (w->strip_chart.update > 0)
+ w->strip_chart.interval_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext(new),
+ (unsigned long) w->strip_chart.update * MS_PER_SEC,
+ draw_it, (XtPointer)w);
+ }
+
+ if ( w->strip_chart.min_scale > (int) ((w->strip_chart.max_value) + 1) )
+ ret_val = TRUE;
+
+ if ( w->strip_chart.fgpixel != old->strip_chart.fgpixel ) {
+ new_gc |= FOREGROUND;
+ ret_val = True;
+ }
+
+ if ( w->strip_chart.hipixel != old->strip_chart.hipixel ) {
+ new_gc |= HIGHLIGHT;
+ ret_val = True;
+ }
+
+ DestroyGC(old, new_gc);
+ CreateGC(w, new_gc);
+
+ return( ret_val );
+}
+
+/* Function Name: SetPoints
+ * Description: Sets up the polypoint that will be used to draw in
+ * the graph lines.
+ * Arguments: w - the StripChart widget.
+ * Returns: none.
+ */
+
+#define HEIGHT ( (unsigned int) w->core.height)
+
+static void
+SetPoints(widget)
+Widget widget;
+{
+ StripChartWidget w = (StripChartWidget) widget;
+ Dimension s = w->threeD.shadow_width;
+ XPoint * points;
+ Cardinal size;
+ int i;
+
+ if (w->strip_chart.scale <= 1) { /* no scale lines. */
+ XtFree ((char *) w->strip_chart.points);
+ w->strip_chart.points = NULL;
+ return;
+ }
+
+ size = sizeof(XPoint) * (w->strip_chart.scale - 1);
+
+ points = (XPoint *) XtRealloc( (XtPointer) w->strip_chart.points, size);
+ w->strip_chart.points = points;
+
+ /* Draw graph reference lines into clip mask */
+
+ for (i = 1; i < w->strip_chart.scale; i++) {
+ points[i - 1].x = 0;
+ points[i - 1].y = ( short)(((double)w->core.height - 2.0 * (double) s) / (double) w->strip_chart.scale );
+ }
+ points[0].y += (short)s;
+}