summaryrefslogtreecommitdiff
path: root/Tachometer.c
diff options
context:
space:
mode:
authorRemco Treffkorn <remco@rvt.com>1999-07-17 23:03:47 +0000
committerRemco Treffkorn <remco@rvt.com>1999-07-17 23:03:47 +0000
commitf632377e259aa6656057e238e73051121e2d2478 (patch)
tree564da23d7331d6cb90ecea5c37ab1550080d71a4 /Tachometer.c
parent6ac8d7649f528969ce98a8067bcf6aaa749b8b10 (diff)
downloadgpsd-f632377e259aa6656057e238e73051121e2d2478.tar.gz
*** empty log message ***
Diffstat (limited to 'Tachometer.c')
-rw-r--r--Tachometer.c741
1 files changed, 741 insertions, 0 deletions
diff --git a/Tachometer.c b/Tachometer.c
new file mode 100644
index 00000000..9c952892
--- /dev/null
+++ b/Tachometer.c
@@ -0,0 +1,741 @@
+/*
+ * Tachometer Widget Implementation
+ *
+ * Author: Kazuhiko Shutoh, 1989.
+ * Revised by Shinji Sumimoto, 1989/9 (xtachos)
+ *
+ * Permission to use, copy, modify and distribute without charge this software,
+ * documentation, images, etc. is granted, provided that this comment and the
+ * author's name is retained. The author assumes no responsibility for lost
+ * sleep as a consequence of use of this software.
+ *
+ * Send any comments, bug reports, etc. to shutoh@isl.yamaha.JUNET
+ *
+ *
+ * Modifications : ilham@mit.edu (July 10 '90)
+ */
+
+
+#define XtStrlen(s) ((s) ? strlen(s) : 0)
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <TachometerP.h>
+#include <math.h>
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+/* Private Data */
+
+#define PI 3.1415927
+
+typedef struct {
+ unsigned char digit[7];
+ } DigitRec;
+
+typedef struct {
+ int nofline;
+ XPoint point_list[5];
+ } StringRec;
+
+/* Number's character database - like as "LED" */
+
+DigitRec num_segment[] = {
+ {1,1,1,1,1,1,0},
+ {0,1,1,0,0,0,0},
+ {1,1,0,1,1,0,1},
+ {1,1,1,1,0,0,1},
+ {0,1,1,0,0,1,1},
+ {1,0,1,1,0,1,1},
+ {1,0,1,1,1,1,1},
+ {1,1,1,0,0,0,0},
+ {1,1,1,1,1,1,1},
+ {1,1,1,1,0,1,1}};
+
+XSegment offset[] = {
+ {-10,-10, 10,-10},
+ { 10,-10, 10, 0},
+ { 10, 0, 10, 10},
+ { 10, 10,-10, 10},
+ {-10, 10,-10, 0},
+ {-10, 0,-10,-10},
+ {-10, 0, 10, 0}};
+
+
+/* " X 10 %" character database */
+
+StringRec char_data[] = {
+ { 2, /* "X" */
+ {{-17, -5},
+ {-7, 5}}},
+ { 2,
+ {{-7, -5},
+ {-17, 5}}},
+ { 2, /* "1" */
+ {{-2, -5},
+ {-2, 5}}},
+ { 5, /* "0" */
+ {{2, -5},
+ {12, -5},
+ {12, 5},
+ {2, 5},
+ {2, -5}}}};
+#if 0
+{{{{ {2, -5}}},
+ { 5, /* "%" */
+ {{17, -5},
+ {20, -5},
+ {20, -2},
+ {17, -2},
+ {17, -5}}},
+ { 2,
+ {{27, -5},
+ {17, 5}}},
+ {5,
+ {{24, 2},
+ {27, 2},
+ {27, 5},
+ {24, 5},
+ {24, 2}}}};
+#endif
+
+
+
+#define offst(field) XtOffset(TachometerWidget, field)
+static XtResource resources[] = {
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ offst(tachometer.scale), XtRString, "XtDefaultForeground"},
+ {XtNtachometerCircleColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
+ offst(tachometer.circle), XtRString, "XtDefaultForeground"},
+ {XtNtachometerNeedleColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
+ offst(tachometer.needle), XtRString, "XtDefaultForeground"},
+ {XtNtachometerNeedleSpeed, XtCtachometerNeedleSpeed, XtRInt,
+ sizeof(int), offst(tachometer.speed), XtRImmediate, (caddr_t) 1},
+ {XtNvalue, XtCValue, XtRInt, sizeof(int),
+ offst(tachometer.value), XtRImmediate, (caddr_t) 0},
+ {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
+ offst(core.height), XtRImmediate, (caddr_t) 100},
+ {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
+ offst(core.width), XtRImmediate, (caddr_t) 100},
+ {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
+ offst(core.border_width), XtRImmediate, (caddr_t) 0},
+ {XtNinternalBorderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
+ offst(tachometer.internal_border), XtRImmediate, (caddr_t) 0},
+};
+
+static void Initialize();
+static void Realize();
+static void Resize();
+static void Redisplay();
+static Boolean SetValues();
+static void Destroy();
+
+TachometerClassRec tachometerClassRec = {
+ {
+/* core_class fields */
+#define superclass (&simpleClassRec)
+ /* superclass */ (WidgetClass) superclass,
+ /* class_name */ "Tachometer",
+ /* widget_size */ sizeof(TachometerRec),
+ /* class_initialize */ NULL,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ NULL,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+/* Simple class fields initialization */
+ {
+ /* change_sensitive */ XtInheritChangeSensitive
+ }
+
+};
+WidgetClass tachometerWidgetClass = (WidgetClass)&tachometerClassRec;
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+
+static void DrawTachometer();
+static void FastFillCircle();
+static void GetneedleGC();
+static void GetscaleGC();
+static void GetcSingleircleGC();
+static void GetbackgroundGC();
+static void DrawGauge();
+static void DrawNeedle();
+static void DrawNumbers();
+static void DrawSingleNumber();
+static void DrawLabelString();
+static void MoveNeedle();
+
+
+
+static void DrawTachometer(w)
+TachometerWidget w;
+{
+ Cardinal center_x, center_y;
+ Cardinal radius_x, radius_y;
+
+ center_x = w->core.width / 2;
+ center_y = w->core.height / 2;
+
+ radius_x = center_x - w->tachometer.internal_border;
+ radius_y = center_y - w->tachometer.internal_border;
+
+ if ((center_x == 0) || (center_y == 0) ||
+ (radius_x <= 0) || (radius_y <= 0))
+ /* Can't draw anything -- no room */
+ return;
+
+ /* Draw meter shape */
+
+ /* Big circle */
+
+ FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC,
+ center_x, center_y, radius_x, radius_y);
+
+ /* Inner circle same color as the background */
+
+ FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.background_GC,
+ center_x, center_y, (Cardinal) (radius_x * 0.95),
+ (Cardinal) (radius_y * 0.95));
+
+ /* Small circle */
+
+ FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC,
+ center_x, center_y, (Cardinal) (radius_x * 0.1),
+ (Cardinal) (radius_y * 0.1));
+
+ /* Draw the details */
+
+ DrawGauge(w);
+ DrawNeedle(w, w->tachometer.value);
+}
+
+
+
+static void FastFillCircle(d, w, gc, center_x, center_y, radius_x, radius_y)
+Display *d;
+Drawable w;
+GC gc;
+Cardinal center_x;
+Cardinal center_y;
+Cardinal radius_x;
+Cardinal radius_y;
+{
+ XPoint points[360];
+ Cardinal angle;
+
+ for (angle = 0; angle < 360; angle++) {
+ points[angle].x = (short) (sin((double) angle * PI / 180.0) *
+ (double) radius_x + (double) center_x);
+ points[angle].y = (short) (cos((double) angle * PI / 180.0) *
+ (double) radius_y + (double) center_y);
+ }
+
+ XFillPolygon(d, w, gc, points, 360, Complex,
+ CoordModeOrigin);
+
+}
+
+
+
+
+static void DrawGauge(w)
+TachometerWidget w;
+{
+ XPoint points[4];
+ double step;
+ Cardinal in_gauge_x, in_gauge_y;
+ Cardinal out_gauge_x, out_gauge_y;
+ Cardinal number_x, number_y;
+ Cardinal center_x, center_y;
+ Cardinal radius_x, radius_y;
+ GC gc;
+ double jump = 1.0;
+
+ center_x = w->core.width / 2;
+ center_y = w->core.height / 2;
+
+ radius_x = center_x - w->tachometer.internal_border;
+ radius_y = center_y - w->tachometer.internal_border;
+
+ if ((center_x == 0) || (center_y == 0) || (radius_x <= 0) ||
+ (radius_y <= 0))
+ /* Can't draw anything */
+ return;
+
+ gc = w->tachometer.scale_GC;
+
+ for (step = 330.0; step >= 30.0; step -= jump) {
+ if ((Cardinal) (step) % 30 == 0) {
+ points[0].x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.75
+ + center_x;
+ points[0].y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.75
+ + center_y;
+ points[1].x = sin((step - 1.0) * PI / 180.0) * radius_x * 0.75
+ + center_x;
+ points[1].y = cos((step - 1.0) * PI / 180.0) * radius_y * 0.75
+ + center_y;
+ points[2].x = sin((step - 1.0) * PI / 180.0) * radius_x * 0.85
+ + center_x;
+ points[2].y = cos((step - 1.0) * PI / 180.0) * radius_y * 0.85
+ + center_y;
+ points[3].x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.85
+ + center_x;
+ points[3].y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.85
+ + center_y;
+
+ XFillPolygon(XtDisplay(w), XtWindow(w), gc, points, 4,
+ Complex, CoordModeOrigin);
+
+ number_x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.65
+ + center_x;
+ number_y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.65
+ + center_y;
+
+ if ((int)((330.0 - step) / 30.0) == 1)
+ jump = 3.0;
+
+ DrawNumbers(w, (unsigned char) ((330.0 - step) / 30.0),
+ number_x, number_y);
+
+ } else {
+ in_gauge_x = sin(step * PI / 180.0) * radius_x * 0.8 + center_x;
+ in_gauge_y = cos(step * PI / 180.0) * radius_y * 0.8 + center_y;
+ out_gauge_x = sin(step * PI / 180.0) * radius_x * 0.85
+ + center_x;
+ out_gauge_y = cos(step * PI / 180.0) * radius_y * 0.85
+ + center_y;
+
+ XDrawLine(XtDisplay(w), XtWindow(w), gc, in_gauge_x,
+ in_gauge_y, out_gauge_x, out_gauge_y);
+ }
+ }
+
+ DrawLabelString(w);
+}
+
+static void DrawNeedle(w, load)
+TachometerWidget w;
+int load;
+{
+ XPoint points[6];
+ double cur_theta1, cur_theta2, cur_theta3;
+ double cur_theta4, cur_theta5;
+ Cardinal center_x, center_y;
+ Cardinal radius_x, radius_y;
+ GC gc;
+
+ center_x = w->core.width / 2;
+ center_y = w->core.height / 2;
+
+ radius_x = center_x - w->tachometer.internal_border;
+ radius_y = center_y - w->tachometer.internal_border;
+
+ if ((center_x == 0) || (center_y == 0) || (radius_x <= 0) ||
+ (radius_y <= 0))
+ /* can't draw anything */
+ return;
+
+ gc = w->tachometer.needle_GC;
+
+ cur_theta1 = (double) (330 - (load * 3)) * PI / 180.0;
+ cur_theta2 = (double) (330 - (load * 3) + 1) * PI / 180.0;
+ cur_theta3 = (double) (330 - (load * 3) - 1) * PI / 180.0;
+ cur_theta4 = (330.0 - ((double) load * 3.0) + 7.0) * PI / 180.0;
+ cur_theta5 = (330.0 - ((double) load * 3.0) - 7.0) * PI / 180.0;
+
+ points[0].x = sin(cur_theta1) * radius_x * 0.75 + center_x;
+ points[0].y = cos(cur_theta1) * radius_y * 0.75 + center_y;
+ points[1].x = sin(cur_theta2) * radius_x * 0.7 + center_x;
+ points[1].y = cos(cur_theta2) * radius_y * 0.7 + center_y;
+ points[2].x = sin(cur_theta4) * radius_x * 0.1 + center_x;
+ points[2].y = cos(cur_theta4) * radius_y * 0.1 + center_y;
+ points[3].x = sin(cur_theta5) * radius_x * 0.1 + center_x;
+ points[3].y = cos(cur_theta5) * radius_y * 0.1 + center_y;
+ points[4].x = sin(cur_theta3) * radius_x * 0.7 + center_x;
+ points[4].y = cos(cur_theta3) * radius_y * 0.7 + center_y;
+ points[5].x = points[0].x;
+ points[5].y = points[0].y;
+
+ XDrawLines(XtDisplay(w), XtWindow(w), gc, points, 6, CoordModeOrigin);
+}
+
+
+static void DrawNumbers(w, which, x, y)
+TachometerWidget w;
+unsigned char which;
+Cardinal x, y;
+{
+ /* Draw Numbers */
+
+ if (which == 10) {
+ DrawSingleNumber(w, 1, (Cardinal) ((double) x * 0.9), y);
+ DrawSingleNumber(w, 0, x, y);
+ } else
+ DrawSingleNumber(w, which, x, y);
+}
+
+
+
+static void DrawSingleNumber(w, which, x, y)
+TachometerWidget w;
+Cardinal x, y;
+{
+
+ XSegment segments[7];
+ Cardinal nsegments;
+ unsigned char count;
+ Cardinal width, height;
+ GC gc;
+
+ width = (w->core.width / 2) - w->tachometer.internal_border;
+ height = (w->core.height / 2) - w->tachometer.internal_border;
+
+ if ((width <= 0) || (height <= 0))
+ return;
+
+ gc = w->tachometer.scale_GC;
+
+ for (count = 0, nsegments = 0; count < 7; count++) {
+ if (num_segment[which].digit[count] == 1) {
+ segments[nsegments].x1 = (short)
+ (x + ((double) offset[count].x1 *
+ ((double) width / 200.0)));
+ segments[nsegments].y1 = (short)
+ (y + ((double) offset[count].y1 *
+ ((double) height / 200.0)));
+ segments[nsegments].x2 = (short)
+ (x + ((double) offset[count].x2 *
+ ((double) width / 200.0)));
+ segments[nsegments].y2 = (short)
+ (y + ((double) offset[count].y2 *
+ ((double) height / 200.0)));
+ nsegments++;
+ }
+ }
+
+ XDrawSegments(XtDisplay(w), XtWindow(w), gc, segments, nsegments);
+
+}
+
+
+
+static void DrawLabelString(w)
+TachometerWidget w;
+{
+ XPoint points[5];
+ Cardinal ry;
+ unsigned char char_count;
+ unsigned char data_count;
+ Cardinal center_x, center_y;
+ Cardinal radius_x, radius_y;
+ GC gc;
+
+ gc = w->tachometer.scale_GC;
+
+ center_x = w->core.width / 2;
+ center_y = w->core.height / 2;
+ radius_x = center_x - w->tachometer.internal_border;
+ radius_y = center_y - w->tachometer.internal_border;
+
+ if (! (center_x && center_y && (radius_x > 0) && (radius_y > 0)))
+ return;
+
+ ry = (double) radius_y * 0.35 + center_y;
+
+ for (char_count = 0; char_count < 4; char_count++) {
+ for (data_count = 0; data_count < char_data[char_count].nofline
+ ; data_count++) {
+ points[data_count].x = (double)
+ (char_data[char_count].point_list[data_count].x) *
+ (double) radius_x * 0.01 + center_x;
+ points[data_count].y = (double)
+ (char_data[char_count].point_list[data_count].y) *
+ (double) radius_y * 0.01 + ry;
+ }
+ XDrawLines(XtDisplay(w), XtWindow(w), gc, points,
+ char_data[char_count].nofline, CoordModeOrigin);
+ }
+}
+
+
+
+static void MoveNeedle(w, new)
+TachometerWidget w;
+int new;
+{
+ int step;
+ int old, loop;
+
+ old = w->tachometer.value;
+ if (new > 100)
+ new = 100;
+
+ if (old == new)
+ return;
+ else if (old < new)
+ step = (w->tachometer.speed ? w->tachometer.speed : new - old);
+ else
+ step = (w->tachometer.speed ? - w->tachometer.speed : new - old);
+
+ if (old < new) {
+ for (loop = old; loop < new; loop += step)
+ DrawNeedle(w, loop);
+ for (loop = old + step; loop <= new; loop += step)
+ DrawNeedle(w, loop);
+ }
+ else {
+ for (loop = old; loop > new; loop += step)
+ DrawNeedle(w, loop);
+ for (loop = old + step; loop >= new; loop += step)
+ DrawNeedle(w, loop);
+ }
+
+ if (loop != new + step) /* The final needle wasn't printed */
+ DrawNeedle(w, new);
+
+ w->tachometer.value = new;
+}
+
+static void GetneedleGC(ta)
+TachometerWidget ta;
+{
+ XGCValues values;
+
+ values.background = ta->core.background_pixel;
+ values.foreground = ta->tachometer.needle ^ ta->core.background_pixel;
+ values.function = GXxor;
+
+ ta->tachometer.needle_GC = XtGetGC(
+ (Widget)ta,
+ (unsigned) GCFunction | GCBackground | GCForeground,
+ &values);
+}
+
+static void GetscaleGC(ta)
+TachometerWidget ta;
+{
+ XGCValues values;
+
+ values.foreground = ta->tachometer.scale;
+ values.background = ta->core.background_pixel;
+
+ ta->tachometer.scale_GC = XtGetGC(
+ (Widget)ta,
+ (unsigned) GCForeground | GCBackground,
+ &values);
+}
+
+static void GetcircleGC(ta)
+TachometerWidget ta;
+{
+ XGCValues values;
+
+ values.foreground = ta->tachometer.circle;
+ values.background = ta->core.background_pixel;
+
+ ta->tachometer.circle_GC = XtGetGC(
+ (Widget)ta,
+ (unsigned) GCForeground | GCBackground,
+ &values);
+}
+
+
+static void GetbackgroundGC(ta)
+TachometerWidget ta;
+{
+ XGCValues values;
+
+ values.foreground = ta->core.background_pixel;
+ values.background = ta->core.background_pixel;
+
+ ta->tachometer.background_GC = XtGetGC(
+ (Widget)ta,
+ (unsigned) GCForeground | GCBackground,
+ &values);
+}
+
+/* ARGSUSED */
+static void Initialize(request, new)
+ Widget request, new;
+{
+ TachometerWidget ta = (TachometerWidget) new;
+
+ GetneedleGC(ta);
+ GetcircleGC(ta);
+ GetscaleGC(ta);
+ GetbackgroundGC(ta);
+ ta->tachometer.width = ta->tachometer.height = 0;
+} /* Initialize */
+
+
+static void Realize(w, valueMask, attributes)
+ register Widget w;
+ Mask *valueMask;
+ XSetWindowAttributes *attributes;
+{
+ *valueMask |= CWBitGravity;
+ attributes->bit_gravity = NorthWestGravity;
+ (*superclass->core_class.realize) (w, valueMask, attributes);
+
+} /* Realize */
+
+
+
+/*
+ * Repaint the widget window
+ */
+
+/* ARGSUSED */
+static void Redisplay(w, event, region)
+ Widget w;
+ XEvent *event;
+ Region region;
+{
+ TachometerWidget ta = (TachometerWidget) w;
+
+ if (event->xexpose.count == 0)
+ DrawTachometer(ta);
+}
+
+static void Resize(w)
+ Widget w;
+{
+ TachometerWidget ta = (TachometerWidget) w;
+
+ if ((ta->core.width == ta->tachometer.width) &&
+ (ta->core.height == ta->tachometer.height))
+ /* What resize? We don't see a resize! */
+ return;
+
+ XClearWindow(XtDisplay(w), XtWindow(w));
+
+ if ((ta->core.width <= ta->tachometer.width) &&
+ (ta->core.height <= ta->tachometer.height))
+ /* Only redraw here if no expose events are going to be */
+ /* generated, i.e. if the window has not grown horizontally */
+ /* or vertically. */
+ DrawTachometer(ta);
+
+ ta->tachometer.width = ta->core.width;
+ ta->tachometer.height = ta->core.height;
+}
+
+/*
+ * Set specified arguments into widget
+ */
+
+/* ARGSUSED */
+static Boolean SetValues(current, request, new)
+ Widget current, request, new;
+{
+ Boolean back;
+ Boolean changed = False;
+
+ TachometerWidget curta = (TachometerWidget) current;
+ TachometerWidget newta = (TachometerWidget) new;
+
+ back = (curta->core.background_pixel != newta->core.background_pixel);
+
+ if (back || (curta->tachometer.needle != newta->tachometer.needle)) {
+ XtReleaseGC(new, newta->tachometer.needle_GC);
+ GetneedleGC(newta);
+ changed = True;
+ }
+ if (back || (curta->tachometer.scale != newta->tachometer.scale)) {
+ XtReleaseGC(new, newta->tachometer.scale_GC);
+ GetscaleGC(newta);
+ changed = True;
+ }
+ if (back || (curta->tachometer.circle != newta->tachometer.circle)) {
+ XtReleaseGC(new, newta->tachometer.circle_GC);
+ GetcircleGC(newta);
+ changed = True;
+ }
+ if (back) {
+ XtReleaseGC(new, newta->tachometer.background_GC);
+ GetbackgroundGC(newta);
+ changed = True;
+ }
+
+ if (curta->tachometer.value != newta->tachometer.value) {
+ MoveNeedle(newta, newta->tachometer.value);
+ changed = True;
+ }
+
+ return(changed);
+}
+
+static void Destroy(w)
+ Widget w;
+{
+ TachometerWidget ta = (TachometerWidget) w;
+
+ XtReleaseGC( w, ta->tachometer.needle_GC );
+ XtReleaseGC( w, ta->tachometer.circle_GC );
+ XtReleaseGC( w, ta->tachometer.scale_GC );
+ XtReleaseGC( w, ta->tachometer.background_GC );
+}
+
+
+
+/***************************************************************
+ *
+ * Exported Procedures
+ *
+ ***************************************************************/
+
+int TachometerGetValue(w)
+Widget w;
+{
+ TachometerWidget ta = (TachometerWidget) w;
+
+ return(ta->tachometer.value);
+}
+
+
+int TachometerSetValue(w, i)
+Widget w;
+int i;
+{
+ int old;
+ TachometerWidget ta = (TachometerWidget) w;
+
+ old = ta->tachometer.value;
+
+ MoveNeedle(ta, i);
+
+ return(old);
+}