[comp.sources.sun] v01i082: Trackertool - Graph data coming from a pipe

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (11/29/89)

Submitted-by: rphroy!rrichter@edsews.eds.com (Roy Richter)
Posting-number: Volume 1, Issue 82
Archive-name: trackertool/part01


#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--  1 roy          1809 Nov 29 10:06 README
# -rwxr-xr-x  1 roy          6544 Nov 29 10:05 trackertool.1
# -rw-r--r--  1 roy            11 Oct 12 11:55 patchlevel.h
# -rw-r--r--  1 roy          2496 Oct 12 10:54 trackertool.h
# -rw-r--r--  1 roy          1933 Oct 12 10:52 trackertool.icon
# -rw-r--r--  1 roy          2341 Jan 16 11:41 Makefile
# -rw-r--r--  1 roy          1742 Sep 14 16:28 change_axis_proc.c
# -rw-r--r--  1 roy           619 Sep 14 16:28 change_connect_proc.c
# -rw-r--r--  1 roy           735 Sep 14 16:28 change_variables_proc.c
# -rw-r--r--  1 roy           966 Sep 14 16:28 close_them_proc.c
# -rw-r--r--  1 roy          5779 Oct 14 15:39 display_mode_proc.c
# -rw-r--r--  1 roy           904 Sep 14 16:28 do_minmax.c
# -rw-r--r--  1 roy           655 Sep 14 16:28 fakeit.c
# -rw-r--r--  1 roy          1220 Sep 14 16:28 get_axis_bounds.c
# -rw-r--r--  1 roy          1133 Sep 14 16:28 get_axis_log_bounds.c
# -rw-r--r--  1 roy          1050 Sep 14 16:28 get_grid_bounds.c
# -rw-r--r--  1 roy          1145 Oct 12 10:49 get_grid_log_bounds.c
# -rw-r--r--  1 roy          1280 Sep 15 16:53 get_next_string.c
# -rw-r--r--  1 roy           605 Sep 14 16:28 init_arrays.c
# -rw-r--r--  1 roy           531 Sep 14 16:28 init_choices.c
# -rw-r--r--  1 roy          1837 Sep 14 16:28 kill_view_proc.c
#
echo 'x - README'
if test -f README
then echo 'shar: not overwriting README'; else
sed 's/^X//' << '________This_Is_The_END________' > README
XTrackertool, Version 1.0, November 1988
X
X  Copyright (c) 1988 Roy Richter, GM Corp.  Anyone can use this
X  software in any manner they choose, including copying, modification
X  and redistribution, provided they make no charge for it, the source
X  code is included in the distribution, and these conditions remain
X  unchanged.
X
X  This program is distributed as is, with all faults (if any), and
X  without any warranty. No author or distributor accepts responsibility
X  to anyone for the consequences of using it, or for whether it serves
X  any particular purpose at all, or any other reason.
X
XTrackertool was originally developed to monitor long-running
Xcalculations.  It allows you to accept data from another process
Xthrough a pipe and graph that data, updating the display as needed.
XTrackertool runs on a Sun Workstation under Sunview.
X
XThe makefile will compile and make the tool.  You are responsible
Xfor placing it where you want it.
X
XI also provide a sample input program called fakeit.  If you
Xtype `make example', both fakeit and trackertool will be made and
Xstarted.  It is interesting to look at the Lissajous figures
Xavailable.
X
XYou should note that a problem arises when you decide to quit.  If you
Xjust exited, then the process producing the data also gets killed by an
Xopen pipe.  Since this is supposed to be used for processes running a
Xfew days (yes, a few days) this is bad.  So, the default behaviour
Xshould be "Hide", which will replace the tool with a simple cat(1).  To
Xget a true exit, do a "Quit", or use the pull-down Quit from the menu.
X
XProblems, updates, and questions should be sent to me,
X
XRoy Richter
XPhysics Department
XGeneral Motors Research Laboratories
XWarren, Michigan 48090-9055
X
XUUCP:     {cfctech, sharkey, uunet!edsews}!rphroy!roy
XInternet: roy%rphroy.uucp@mailgw.cc.umich.edu
________This_Is_The_END________
if test `wc -l < README` -ne 42; then
	echo -n 'shar: README was damaged during transit'
	echo ' (should have been 42 bytes)'
fi
fi		; : end of overwriting check
echo 'x - trackertool.1'
if test -f trackertool.1
then echo 'shar: not overwriting trackertool.1'; else
sed 's/^X//' << '________This_Is_The_END________' > trackertool.1
X.TH TRACKERTOOL 1 Local
X.UC 4
X.SH NAME
Xtrackertool \- filter to display and update information in graphical form
Xon a Sun
X.SH SYNOPSIS
X.B trackertool
X[
X.BI \-v count
X] [
X.B \-n
X] [
X.I window args
X]
X.SH DESCRIPTION
X.I Trackertool
Xdisplays data piped to its standard input in various forms.
XIt runs under Sunview on a Sun Workstation.
XThe user chooses graphical or text output, or both.
XThe display is updated each time a new line of data arrives.
X.PP
X.I Trackertool
Xtakes data in columnar format.  A possible use is as a replacement for
X.IR perfmeter (1)
Xfor viewing output from vmstat, with the appropriate
X.IR sed (1)
Xscript to make the input data format conform.  See EXAMPLES.
XIt was originally designed to monitor the convergence of long-running
Xnumerical programs.
X.PP
X.I Trackertool
Xoutputs the data without change to its standard output.
X.SH OPTIONS
X.TP
X.BI \-v count
XRetain
X.I count
Xvalues before resetting the internal buffers.  Since 
X.I trackertool
Xcan only keep so much data in memory, it periodically flushes its
Xbuffers.
X.I count
Xdetermines when the buffers are flushed.  The default is 1000.  When
Xflushed, only half the values are kept.  The next repaint will reflect
Xthis;  if no repaint is forced, the display will continue to display old
Xvalues.  The text window will reset after
X.RI 4* count
Xvalues have been added to it.
X.TP
X.B \-n
XDon't copy the input to standard out.
X.SH "INPUT FORMAT"
XThe first line contains labels to be used to distinguish the columns.
XSubsequent lines are assumed to contain a value for each label.
XMissing values are waited for, and extra values are ignored.
XA label is a string that contains no white space.
XOnly the first 20 characters of the label are used.
XThe data values must be separated by white space.
X.PP
X.I Trackertool
Xreads the input as it appears, up to a new-line.
XIf no new-line is given, it will hang waiting for input.
XThe safest input is a full line at a time.
XThe easiest way to ensure this is to set line buffering
Xin the previous application (see
X.IR setlinebuf (3S)).
X.SH "THE DISPLAY"
X.I Trackertool
Xfirst comes up with a small window containing the master control
Xpanel.  The first button, "Create View", will make another window
Xappear.  You can create many views until the file descriptors run out;
Xthen the button disappears.  The "Hide" button will throw away
X.I trackertool
Xand replace it with a null process, allowing the process producing the
Xdata to continue.  The "Quit" button will really quit, killing the
Xdata-producing process.  The master control panel also give the status
Xof the input and the number of data values currently stored.  When the
Xinternal tables are flushed (see
X.BR \-v ),
Xthis number drops.
X.PP
XEach view contains up to 4 sub-windows, controlled by the view control
Xpanel.  The "Display mode:" toggle allows you to choose which one you
Xdesire.  There are pop-up menus that allow you to choose the variables
Xfor the abscissa and the ordinate.  The default configuration will show
Xa graph of the first variable against the
X.RI n+1 st
Xvariable.  You can also kill the view completely, using the "Kill View"
Xbutton.
X.PP
XThe
X.B Text
Xsub-window contains two columns of data.  The
X.B Graph
Xsub-window graphs these two columns against each other.  The
X.B Props
Xpanel lets you modify the graph.  You can choose to: connect the data
Xvalues (Lines/Points); automatically scale the axis limits; have an
Xaxis grid; or use a log axis.  The "Reset" button returns to the
Xinitial configuration (auto-scale, grid off, log off).  The "Redraw"
Xbutton will draw the graph again.  This is useful if you change axis
Xbounds. You may also change the axis values with the mouse by clicking
Xthe left-mouse key down at one new axis value, dragging the other end
Xof the box to the other desired point, and lifting the mouse button.
XThis has the side-effect of shutting off automatic axis scaling.
XYou may "Reset" to return to the original graph.
X.SH AUTHOR
XRoy Richter, Staff Research Scientist, Physics Department,
XGeneral Motors Research Labs.  Mail address is {umix,
Xuunet!edsews}!rphroy!roy.
X.SH BUGS
XBe aware that if you really quit, then the process feeding the pipe
Xbeing read will also die.  Also, if
X.I trackertool
Xis being run in the background, and you hide, it will stay until the
Xfeeding process terminates.  In the case of
X.IR tail (1),
Xthis will take forever.
X.PP
XThe perfmeter mode (small, graph-only window) should scroll as data
Xarrives, not rescaled; possibly a switch to turn on scrolling should be
Xadded.
X.PP
XMissing values mess up the display for a little while.
X.PP
XThere should be a way of saving and loading a configuration of views.
XAlso, a way of recovering after a hide, or reattachment when restarting
X.IR suntools (1).
XI'll do it when I get around to it.
X.PP
XA repaint of only a section of the canvas (due to exposing that section
Xby removing another overalapping window, for example) will result in a
Xmixed display if a rescaling occured.  Hit the Redraw button to fix it
Xup.
X.PP
XUsing the "Open" Sunview Accelerator button (L7) will close the master
Xcontrol panel without closing the views.  This can be construed as a
Xfeature.
X.SH EXAMPLES
Xvmstat 1 | sed -e '/cpu/d' -e 3d -e '2s/r/R/' -e '/^ r/d' -e '2s/R/r/'
X| trackertool -n
X.PP
XThe first sed command deletes one of the header lines, the next deletes
Xthe cumulative summary, and the last three delete header lines after the
Xfirst one.  A problem occures if any of the fields fill up, e.g. cpu
Xusage is 100, since then fields bang together.  It is left as an
Xexercise to split the output further into columns that don't run
Xtogether.
X.PP
XYou might think a similar trick would work with
X.IR iostat (8),
Xbut it doesn't, since
X.IR iostat (8)
Xbuffers its output.
X.I Trackertool
Xthen gives rather bursty output and hangs on incomplete lines.
X.PP
XYou can produce a graph that looks like
X.IR perfmeter (1)
Xby toggling off all displays except for the graph and resizing the
Xwindow to be tiny.
X.SH COPYRIGHT NOTICE
XTrackertool, Version 1.0, November 1988 
X.PP
XCopyright (c) 1988 Roy Richter, GM Corp.  Anyone can use this software
Xin any manner they choose, including copying, modification and
Xredistribution, provided they make no charge for it, source code is
Xincluded in the distribution, and these conditions remain unchanged.
X.PP
XThis program is distributed as is, with all faults (if any), and 
Xwithout any warranty. No author or distributor accepts responsibility 
Xto anyone for the consequences of using it, or for whether it serves 
Xany particular purpose at all, or any other reason. 
________This_Is_The_END________
if test `wc -l < trackertool.1` -ne 173; then
	echo -n 'shar: trackertool.1 was damaged during transit'
	echo ' (should have been 173 bytes)'
fi
fi		; : end of overwriting check
echo 'x - patchlevel.h'
if test -f patchlevel.h
then echo 'shar: not overwriting patchlevel.h'; else
sed 's/^X//' << '________This_Is_The_END________' > patchlevel.h
XPatch #: 0
________This_Is_The_END________
if test `wc -l < patchlevel.h` -ne 1; then
	echo -n 'shar: patchlevel.h was damaged during transit'
	echo ' (should have been 1 bytes)'
fi
fi		; : end of overwriting check
echo 'x - trackertool.h'
if test -f trackertool.h
then echo 'shar: not overwriting trackertool.h'; else
sed 's/^X//' << '________This_Is_The_END________' > trackertool.h
X#define ALLOC(type)     (type *)malloc((unsigned)sizeof(type))
X
X#define MAX_FD        30	/* 64 in SunOS 4.0 */
X#define MAX_STR_LEN   11	/* Label length+1; used for many things */
X#define MAX_ARRAYS    50	/* Change if you want */
X#define DEFAULT_MAX_VALUES  1001/* Default number of values to keep */
X#define MAX_SUBFRAMES MAX_FD	/* A little generous */
X
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X#include <suntool/canvas.h>
X#include <suntool/textsw.h>
X
Xtypedef struct {
X    char            label_r[MAX_STR_LEN];	/* Right-justified */
X    char            label_l[MAX_STR_LEN];	/* Left-justified */
X    float           max_value, min_value, min_value_log; /* Actual bounds */
X    float           max_graph, min_graph;	/* Suggested bounds */
X    float           max_graph_log, min_graph_log;	/* Suggested bounds */
X    float          *values;	/* Pointer to values */
X    float          *log_values;	/* Pointer to log values */
X}               Array;		/* One of these for each variable */
X
Xtypedef struct {
X    Array          *x, *y;	/* Which variables to plot */
X    Frame           handle;	/* Base frame for sub-frame */
X    Panel           panel;	/* Control panel */
X    Panel_item      choice;	/* Display Mode choice */
X    Menu_item       menu_item;	/* Controls the control panel display */
X    Canvas          canvas;	/* Graph representation */
X    Textsw          textsw;	/* Text representation */
X    Panel           props;	/* Knobs to turn follow */
X    int             connect_points;
X    Panel_item      props_x_min, props_x_max, props_y_min, props_y_max;
X    int             x_min_auto, x_max_auto, y_min_auto, y_max_auto;
X    int             x_log, y_log, x_grid, y_grid;
X    float           x_min, x_max, y_min, y_max;
X    int             x_axis_min, x_axis_max, y_axis_min, y_axis_max;
X}               Subframe;	/* One of these for each view */
X
Xint             num_of_subframes;
Xint             num_arrays;
Xint             num_values;
Xint             num_fd;		/* File descriptor count */
Xint             MAX_VALUES;	/* # of array values to keep before reset */
Xint		echo_on;	/* TRUE means copy stdin to stdout */
X
XPanel           main_panel;	/* Overall control panel */
XPanel_item      view_button;	/* Creates new view */
XPanel_item      hide_button;	/* Creates new view */
XPanel_item      quit_button;	/* Creates new view */
XPanel_item      num_message;	/* number of variables read in */
X
XSubframe       *subframe[MAX_SUBFRAMES];
XArray          *array_ptr[MAX_ARRAYS];
________This_Is_The_END________
if test `wc -l < trackertool.h` -ne 55; then
	echo -n 'shar: trackertool.h was damaged during transit'
	echo ' (should have been 55 bytes)'
fi
fi		; : end of overwriting check
echo 'x - trackertool.icon'
if test -f trackertool.icon
then echo 'shar: not overwriting trackertool.icon'; else
sed 's/^X//' << '________This_Is_The_END________' > trackertool.icon
X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
X */
X	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
X	0x0020,0x0000,0x0800,0x0000,0x0020,0x0000,0x0800,0x0000,
X	0x00F9,0x61C3,0x890E,0x2C00,0x0021,0x9224,0x4A11,0x3200,
X	0x0021,0x0024,0x0C11,0x2000,0x0021,0x01E4,0x0C1F,0x2000,
X	0x0021,0x0224,0x0A10,0x2000,0x0021,0x0224,0x4911,0x2000,
X	0x0019,0x01E3,0x888E,0x2000,0x0000,0x0000,0x0000,0x0000,
X	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
X	0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x4000,0x0000,0x0000,0x0002,
X	0x4000,0x0000,0x0000,0x0002,0x42AA,0xA222,0x221D,0xDDD2,
X	0x4555,0x5044,0x441B,0xBBB2,0x42AA,0xA111,0x110E,0xEEE2,
X	0x4555,0x5088,0x8817,0x7772,0x4000,0x0000,0x0000,0x0002,
X	0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x0000,0x0000,0x0000,0x0000,
X	0x0FFF,0xFFFE,0x7FFF,0xFFF0,0x0800,0x0002,0x4000,0x0010,
X	0x0800,0x0002,0x4000,0x0010,0x0D30,0x0002,0x58FA,0x7F90,
X	0x0B10,0x0002,0x4000,0x0010,0x0D18,0x0002,0x58FA,0x3F90,
X	0x090C,0x0002,0x4000,0x0010,0x0907,0x0002,0x587A,0x0390,
X	0x0901,0xF002,0x4000,0x0010,0x0900,0x0FC2,0x5CFA,0x1F90,
X	0x0900,0x0002,0x4000,0x0010,0x0900,0x0002,0x59FA,0x0790,
X	0x09FF,0xFFF2,0x4000,0x0010,0x0800,0x002A,0x50FA,0x7F90,
X	0x0800,0x0052,0x4000,0x0010,0x0800,0x0002,0x4000,0x0010,
X	0x0FFF,0xFFFE,0x7FFF,0xFFF0,0x0000,0x0000,0x0000,0x0000,
X	0x0000,0x0000,0x0000,0x0000,0x0FFF,0xFFFE,0x7FFF,0xFFF0,
X	0x0800,0x0002,0x4000,0x0010,0x0800,0x0002,0x4000,0x0010,
X	0x0C00,0x0002,0x4000,0x0010,0x0B20,0x0202,0x4800,0x0010,
X	0x0D20,0x0782,0x4BF0,0x0610,0x0910,0x0442,0x4A10,0x0810,
X	0x0910,0x0462,0x4810,0x1010,0x0910,0x0822,0x4818,0x2010,
X	0x0918,0x0832,0x480C,0x6010,0x0907,0xF802,0x4803,0xC010,
X	0x0900,0x0002,0x4800,0x0010,0x0900,0x0002,0x4800,0x0010,
X	0x09FF,0xFFF2,0x4FFF,0xFF10,0x0800,0x002A,0x4000,0x0A10,
X	0x0800,0x0052,0x4000,0x0510,0x0FFF,0xFFFE,0x7FFF,0xFFF0,
X	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
X	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
________This_Is_The_END________
if test `wc -l < trackertool.icon` -ne 34; then
	echo -n 'shar: trackertool.icon was damaged during transit'
	echo ' (should have been 34 bytes)'
fi
fi		; : end of overwriting check
echo 'x - Makefile'
if test -f Makefile
then echo 'shar: not overwriting Makefile'; else
sed 's/^X//' << '________This_Is_The_END________' > Makefile
XOBJ =	change_axis_proc.o \
X	change_connect_proc.o \
X	change_variables_proc.o \
X	close_them_proc.o \
X	display_mode_proc.o \
X	do_minmax.o \
X	get_axis_bounds.o \
X	get_axis_log_bounds.o \
X	get_grid_bounds.o \
X	get_grid_log_bounds.o \
X	get_next_string.o \
X	init_arrays.o \
X	init_choices.o \
X	trackertool.o \
X	kill_view_proc.o \
X	make_base.o \
X	make_labels.o \
X	make_panel.o \
X	make_props.o \
X	make_sub.o \
X	pipe_reader.o \
X	quit_proc.o \
X	repaint_canvas.o \
X	reset_axis_proc.o \
X	rewrite_text.o \
X	update_arrays.o \
X	update_canvas.o \
X	update_displays.o \
X	update_textsw.o \
X	zoom_event.o
X
XCFLAGS = -g
X
Xtrackertool: $(OBJ)
X	cc -o trackertool $(OBJ) -lsuntool -lsunwindow -lpixrect -lm
X
Xexample: fakeit trackertool
X	fakeit | trackertool -n
X
Xfakeit: fakeit.c
X	cc -o fakeit fakeit.c -lm
X
Xtrackertool.shar:
X	shar -h trackertool.shar.1of2 README *.1 *.h *.icon Makefile [a-l]*.c
X	shar -h trackertool.shar.2of2 [m-z]*.c
X
Xchange_axis_proc.o : change_axis_proc.c trackertool.h 
Xchange_connect_proc.o : change_connect_proc.c trackertool.h 
Xchange_variables_proc.o : change_variables_proc.c trackertool.h 
Xclose_them_proc.o : close_them_proc.c trackertool.h 
Xdisplay_mode_proc.o : display_mode_proc.c trackertool.h 
Xdo_minmax.o : do_minmax.c trackertool.h 
Xget_axis_bounds.o : get_axis_bounds.c 
Xget_axis_log_bounds.o : get_axis_log_bounds.c 
Xget_grid_bounds.o : get_grid_bounds.c 
Xget_grid_log_bounds.o : get_grid_log_bounds.c 
Xget_next_string.o : get_next_string.c 
Xinit_arrays.o : init_arrays.c trackertool.h 
Xinit_choices.o : init_choices.c trackertool.h 
Xtrackertool.o : trackertool.c trackertool.h 
Xkill_view_proc.o : kill_view_proc.c trackertool.h 
Xmake_base.o : make_base.c trackertool.h trackertool.icon 
Xmake_labels.o : make_labels.c trackertool.h 
Xmake_panel.o : make_panel.c trackertool.h 
Xmake_props.o : make_props.c trackertool.h 
Xmake_sub.o : make_sub.c trackertool.h 
Xpipe_reader.o : pipe_reader.c trackertool.h 
Xquit_proc.o : quit_proc.c trackertool.h 
Xrepaint_canvas.o : repaint_canvas.c trackertool.h 
Xreset_axis_proc.o : reset_axis_proc.c trackertool.h 
Xrewrite_text.o : rewrite_text.c trackertool.h 
Xupdate_arrays.o : update_arrays.c trackertool.h 
Xupdate_canvas.o : update_canvas.c trackertool.h 
Xupdate_displays.o : update_displays.c trackertool.h 
Xupdate_textsw.o : update_textsw.c trackertool.h 
Xzoom_event.o : zoom_event.c trackertool.h 
________This_Is_The_END________
if test `wc -l < Makefile` -ne 76; then
	echo -n 'shar: Makefile was damaged during transit'
	echo ' (should have been 76 bytes)'
fi
fi		; : end of overwriting check
echo 'x - change_axis_proc.c'
if test -f change_axis_proc.c
then echo 'shar: not overwriting change_axis_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > change_axis_proc.c
X#include "trackertool.h"
X
X#define AUTO_MIN 0		/* the toggle values as set in
X				 * make_props */
X#define AUTO_MAX 1
X#define GRID_ON  2
X#define LOG_ON   3
X#define toggle_bit_on(value,bit) ((value) & (1 << (bit)))
X
Xvoid
Xchange_axis_proc(choice, value, event)
X    Panel_item      choice;
X    unsigned int    value;
X    Event          *event;
X/*
X * Changes the display mode of the canvas.
X * When this proc is called, recreate the canvas.
X */
X{
X    Panel           panel;
X    Subframe       *subframe_ptr;
X
X    void            repaint_canvas();
X    void            do_minmax();
X
X    panel = (Panel) panel_get(choice, PANEL_PARENT_PANEL);
X    subframe_ptr = (Subframe *) window_get(panel, WIN_CLIENT_DATA, 0);
X
X    if ((char) panel_get(choice, PANEL_CLIENT_DATA, 0) == 'x') {
X	do_minmax(value, AUTO_MIN, &(subframe_ptr->x_min_auto),
X	    subframe_ptr->props_x_min, &(subframe_ptr->x_min));
X	do_minmax(value, AUTO_MAX, &(subframe_ptr->x_max_auto),
X	    subframe_ptr->props_x_max, &(subframe_ptr->x_max));
X	if (toggle_bit_on(value, GRID_ON))
X	    subframe_ptr->x_grid = TRUE;
X	else
X	    subframe_ptr->x_grid = FALSE;
X	if (toggle_bit_on(value, LOG_ON))
X	    subframe_ptr->x_log = TRUE;
X	else
X	    subframe_ptr->x_log = FALSE;
X    } else {
X	do_minmax(value, AUTO_MIN, &(subframe_ptr->y_min_auto),
X	    subframe_ptr->props_y_min, &(subframe_ptr->y_min));
X	do_minmax(value, AUTO_MAX, &(subframe_ptr->y_max_auto),
X	    subframe_ptr->props_y_max, &(subframe_ptr->y_max));
X	if (toggle_bit_on(value, GRID_ON))
X	    subframe_ptr->y_grid = TRUE;
X	else
X	    subframe_ptr->y_grid = FALSE;
X	if (toggle_bit_on(value, LOG_ON))
X	    subframe_ptr->y_log = TRUE;
X	else
X	    subframe_ptr->y_log = FALSE;
X    }
X
X    repaint_canvas(subframe_ptr->canvas);
X    return;
X}
________This_Is_The_END________
if test `wc -l < change_axis_proc.c` -ne 59; then
	echo -n 'shar: change_axis_proc.c was damaged during transit'
	echo ' (should have been 59 bytes)'
fi
fi		; : end of overwriting check
echo 'x - change_connect_proc.c'
if test -f change_connect_proc.c
then echo 'shar: not overwriting change_connect_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > change_connect_proc.c
X#include "trackertool.h"
X
Xvoid
Xchange_connect_proc(choice, value, event)
X    Panel_item      choice;
X    unsigned int    value;
X    Event          *event;
X/*
X * Changes the connect type of the points in the canvas,
X * and redraws it.
X */
X{
X    Panel           panel;
X    Subframe       *subframe_ptr;
X
X    void            repaint_canvas();
X
X    panel = (Panel) panel_get(choice, PANEL_PARENT_PANEL);
X    subframe_ptr = (Subframe *) window_get(panel, WIN_CLIENT_DATA, 0);
X
X    if (value != subframe_ptr->connect_points) {
X	subframe_ptr->connect_points = value;
X	repaint_canvas(subframe_ptr->canvas);
X    }
X    return;
X}
________This_Is_The_END________
if test `wc -l < change_connect_proc.c` -ne 26; then
	echo -n 'shar: change_connect_proc.c was damaged during transit'
	echo ' (should have been 26 bytes)'
fi
fi		; : end of overwriting check
echo 'x - change_variables_proc.c'
if test -f change_variables_proc.c
then echo 'shar: not overwriting change_variables_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > change_variables_proc.c
X#include "trackertool.h"
X#include <stdio.h>
X
Xvoid
Xchange_variables_proc(choice, value, event)
X    Panel_item      choice;
X    int             value;
X    Event          *event;
X/*
X * Changes the variables use in subframe, and redraws it.
X */
X{
X    Panel           panel;
X    Subframe       *subframe_ptr;
X
X    void            rewrite_text(), repaint_canvas();
X
X    panel = (Panel) panel_get(choice, PANEL_PARENT_PANEL);
X    subframe_ptr = (Subframe *) window_get(panel, WIN_CLIENT_DATA, 0);
X
X    if ((char) panel_get(choice, PANEL_CLIENT_DATA, 0) == 'x')
X	subframe_ptr->x = array_ptr[value];
X    else
X	subframe_ptr->y = array_ptr[value];
X
X    rewrite_text(subframe_ptr->textsw);
X    repaint_canvas(subframe_ptr->canvas);
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < change_variables_proc.c` -ne 30; then
	echo -n 'shar: change_variables_proc.c was damaged during transit'
	echo ' (should have been 30 bytes)'
fi
fi		; : end of overwriting check
echo 'x - close_them_proc.c'
if test -f close_them_proc.c
then echo 'shar: not overwriting close_them_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > close_them_proc.c
X#include "trackertool.h"
X
XNotify_value
Xclose_them_proc(frame, event, arg, type)
X    Frame           frame;
X    Event           event;
X    Notify_arg      arg;
X    Notify_event_type type;
X /*
X  * Closes each subframe if we close the main frame through the window
X  * menu. Opens them all when the main one opens.
X  */
X{
X    int             closed_initial, closed_current;
X    Notify_value    value;
X    int             i;
X
X    /* Determine initial state of frame */
X    closed_initial = (int) window_get(frame, FRAME_CLOSED);
X
X    /* Let frame operate on event */
X    value = notify_next_event_func(frame, event, arg, type);
X
X    /* Determine current state of frame */
X    closed_current = (int) window_get(frame, FRAME_CLOSED);
X
X    /* Close/open the other frames if we just changed this one */
X    if (closed_initial != closed_current)
X	for (i = 0; i <= num_of_subframes; i++)
X	    window_set(subframe[i]->handle, WIN_SHOW, closed_initial, 0);
X
X    return value;
X}
________This_Is_The_END________
if test `wc -l < close_them_proc.c` -ne 33; then
	echo -n 'shar: close_them_proc.c was damaged during transit'
	echo ' (should have been 33 bytes)'
fi
fi		; : end of overwriting check
echo 'x - display_mode_proc.c'
if test -f display_mode_proc.c
then echo 'shar: not overwriting display_mode_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > display_mode_proc.c
X#include <stdio.h>
X#include "trackertool.h"
X
X#define TEXT 0			/* the toggle values as set in make_sub */
X#define GRAPH 1
X#define PROPS 2
X#define PAN_L 3
X#define toggle_bit_on(value,bit) ((value) & (1 << (bit)))
X
Xvoid
Xdisplay_mode_proc(choice, value, event)
X    Panel_item      choice;
X    unsigned int    value;
X    Event          *event;
X/*
X * Changes the display mode of the subframe.
X * When this proc is called, recreate the entire subframe
X */
X{
X    Panel           panel;
X    Frame           frame;
X
X    Panel           make_props();
X    void            repaint_canvas();
X    void            rewrite_text();
X    Notify_value    zoom_event();
X
X    int             frame_no, frame_height, frame_width, text_height;
X    Panel           above_panel;
X    Subframe       *subframe_ptr;
X
X    int             old_fd, new_fd;
X
X    /* find everybody before we start */
X    panel = (Panel) panel_get(choice, PANEL_PARENT_PANEL);
X    frame = (Frame) window_get(panel, WIN_OWNER);
X    frame_no = (int) window_get(frame, WIN_CLIENT_DATA, 0);
X    frame_height = (int) window_get(frame, WIN_HEIGHT, 0);
X    frame_width = (int) window_get(frame, WIN_WIDTH, 0);
X    subframe_ptr = subframe[frame_no];
X    above_panel = panel;	/* set the next subwindow under top */
X
X    /* Current and new file descriptor usage */
X    old_fd = 0;
X    if (subframe_ptr->textsw)
X	old_fd = old_fd + 3;
X    if (subframe_ptr->canvas)
X	old_fd = old_fd + 1;
X    if (subframe_ptr->props)
X	old_fd = old_fd + 1;
X    if (subframe_ptr->panel)
X	old_fd = old_fd + 1;
X    new_fd = 0;
X    if (toggle_bit_on(value, TEXT))
X	new_fd = new_fd + 3;
X    if (toggle_bit_on(value, GRAPH))
X	new_fd = new_fd + 1;
X    if (toggle_bit_on(value, PROPS))
X	new_fd = new_fd + 1;
X    if (toggle_bit_on(value, PAN_L))
X	new_fd = new_fd + 1;
X    if (num_fd - old_fd + new_fd > MAX_FD) {
X	fprintf(stderr, "Too many windows open.  Request ignored.\n");
X	if (subframe_ptr->textsw)
X	    panel_set(choice, PANEL_TOGGLE_VALUE, TEXT, TRUE, 0);
X	else
X	    panel_set(choice, PANEL_TOGGLE_VALUE, TEXT, FALSE, 0);
X	if (subframe_ptr->canvas)
X	    panel_set(choice, PANEL_TOGGLE_VALUE, GRAPH, TRUE, 0);
X	else
X	    panel_set(choice, PANEL_TOGGLE_VALUE, GRAPH, FALSE, 0);
X	if (subframe_ptr->props)
X	    panel_set(choice, PANEL_TOGGLE_VALUE, PROPS, TRUE, 0);
X	else
X	    panel_set(choice, PANEL_TOGGLE_VALUE, PROPS, FALSE, 0);
X	if (subframe_ptr->panel)
X	    panel_set(choice, PANEL_TOGGLE_VALUE, PAN_L, TRUE, 0);
X	else
X	    panel_set(choice, PANEL_TOGGLE_VALUE, PAN_L, FALSE, 0);
X	return;
X    }
X    /*
X     * destroy textsw only if unneeded, it takes time to remake;
X     * destroy canvas and props, they're easy to remake; destroy panel
X     * if requested, also change menu item, namestripe
X     */
X    if (subframe_ptr->textsw && !toggle_bit_on(value, TEXT))
X	window_destroy(subframe_ptr->textsw);
X    if (subframe_ptr->canvas)
X	window_destroy(subframe_ptr->canvas);
X    if (subframe_ptr->props)
X	window_destroy(subframe_ptr->props);
X    if (subframe_ptr->panel && !toggle_bit_on(value, PAN_L)) {
X	window_destroy(subframe_ptr->panel);
X	menu_set(subframe_ptr->menu_item, MENU_INACTIVE, FALSE, 0);
X	window_set(subframe_ptr->handle, FRAME_SHOW_LABEL, FALSE, 0);
X	subframe_ptr->panel = 0;
X	above_panel = 0;	/* panel no longer there */
X    }
X    num_fd -= old_fd;
X
X    /* Create or adjust the textsw as needed */
X    if (toggle_bit_on(value, TEXT)) {
X	if (toggle_bit_on(value, PROPS) || toggle_bit_on(value, GRAPH))
X	    if (above_panel != NULL)
X		text_height = (frame_height -
X			(int) window_get(panel, WIN_HEIGHT, 0)) / 2 - 40;
X	    else
X		text_height = frame_height / 2;
X	else
X	    text_height = WIN_EXTEND_TO_EDGE;
X	if (subframe_ptr->textsw) {	/* already there */
X	    if (above_panel == NULL)	/* move up */
X		window_set(subframe_ptr->textsw, WIN_Y, 0, 0);
X	    else			/* move down */
X		window_set(subframe_ptr->textsw, WIN_BELOW, above_panel, 0);
X	    window_set(subframe_ptr->textsw, WIN_HEIGHT, text_height, 0);
X	} else {		/* create a new one */
X	    subframe_ptr->textsw = window_create(frame, TEXTSW,
X		TEXTSW_BROWSING, TRUE,
X		TEXTSW_AGAIN_RECORDING, FALSE,
X		TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
X		TEXTSW_MEMORY_MAXIMUM, 21 * MAX_VALUES * 5,
X		WIN_X, 0,
X		WIN_BELOW, above_panel,
X		WIN_WIDTH, (int) window_get(above_panel, WIN_WIDTH, 0),
X		WIN_HEIGHT, text_height,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X	    rewrite_text(subframe_ptr->textsw);
X	}
X	above_panel = subframe_ptr->textsw;	/* next subwindow under */
X    } else {
X	subframe_ptr->textsw = 0;
X    }
X
X    /* Create the props as needed */
X    if (toggle_bit_on(value, PROPS)) {
X	subframe_ptr->props = make_props(subframe_ptr, frame, above_panel);
X    } else {
X	subframe_ptr->props = 0;
X    }
X
X    /* Create the canvas as needed */
X    if (toggle_bit_on(value, GRAPH)) {
X	if (above_panel != NULL)
X	    subframe_ptr->canvas = window_create(frame, CANVAS,
X		CANVAS_REPAINT_PROC, repaint_canvas,
X		CANVAS_FIXED_IMAGE, FALSE,
X		CANVAS_RETAINED, FALSE,
X		CANVAS_WIDTH, frame_width,
X		CANVAS_HEIGHT, frame_height,
X		WIN_BELOW, above_panel,
X		WIN_EVENT_PROC, zoom_event,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X	else
X	    subframe_ptr->canvas = window_create(frame, CANVAS,
X		CANVAS_REPAINT_PROC, repaint_canvas,
X		CANVAS_FIXED_IMAGE, FALSE,
X		CANVAS_RETAINED, FALSE,
X		CANVAS_WIDTH, frame_width,
X		CANVAS_HEIGHT, frame_height,
X		WIN_Y, 0,
X		WIN_EVENT_PROC, zoom_event,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X	if (!subframe_ptr->props)
X	    window_set(subframe_ptr->canvas, WIN_X, 0, 0);
X	repaint_canvas(subframe_ptr->canvas);
X    } else {
X	subframe_ptr->canvas = 0;
X    }
X
X    num_fd += new_fd;
X    if (num_fd + 3 > MAX_FD)	/* need three fd's to make another
X				 * window */
X	panel_set(view_button, PANEL_SHOW_ITEM, FALSE, 0);
X    else
X	panel_set(view_button, PANEL_SHOW_ITEM, TRUE, 0);
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < display_mode_proc.c` -ne 183; then
	echo -n 'shar: display_mode_proc.c was damaged during transit'
	echo ' (should have been 183 bytes)'
fi
fi		; : end of overwriting check
echo 'x - do_minmax.c'
if test -f do_minmax.c
then echo 'shar: not overwriting do_minmax.c'; else
sed 's/^X//' << '________This_Is_The_END________' > do_minmax.c
X#include "trackertool.h"
X#include <string.h>
X
X#define toggle_bit_on(value,bit) ((value) & (1 << (bit)))
X
Xvoid
Xdo_minmax(value, auto_m, xy_m_auto_ptr, props_xy_m, xy_m_ptr)
X    unsigned int    value;
X    int             auto_m;
X    int            *xy_m_auto_ptr;
X    Panel_item      props_xy_m;
X    float          *xy_m_ptr;
X /*
X  * Checks the panel values to make sure that they have been set. If
X  * not, it sets them.
X  */
X{
X    char           *value_ptr, buf[18];
X    char           *gcvt();
X    double          atof();
X
X    if (toggle_bit_on(value, auto_m)) {
X	*xy_m_auto_ptr = TRUE;
X    } else {
X	*xy_m_auto_ptr = FALSE;
X	value_ptr = (char *) panel_get_value(props_xy_m);
X	/* set int/ext-ernal values, depending on which was given */
X	if (strcmp(value_ptr, "Not set")) {
X	    *xy_m_ptr = atof(value_ptr);
X	} else {
X	    panel_set_value(props_xy_m,
X		gcvt(*xy_m_ptr, 8, buf));
X	}
X    }
X    return;
X}
________This_Is_The_END________
if test `wc -l < do_minmax.c` -ne 36; then
	echo -n 'shar: do_minmax.c was damaged during transit'
	echo ' (should have been 36 bytes)'
fi
fi		; : end of overwriting check
echo 'x - fakeit.c'
if test -f fakeit.c
then echo 'shar: not overwriting fakeit.c'; else
sed 's/^X//' << '________This_Is_The_END________' > fakeit.c
X#include <math.h>
X#include <stdio.h>
X#include <signal.h>
X
X/* This program just puts out some fake data every second. */
X
Xmain()
X{
X    double          x, dx;
X    double          fac, facfac;
X    int             num_funcs, i;
X
X    setlinebuf(stdout);
X
X    num_funcs = 21;
X
X    printf("x x**2");
X    for (i = 1; i <= num_funcs; i++)
X	printf(" sin(%dx) cos(%dx)", i, i);
X    printf("\n");
X
X    fac = 1.;
X    facfac = 0.999;
X    dx = 0.1;
X    x = dx;
X    while (1) {
X	printf("%lf %lf", x, x * x);
X	for (i = 1; i <= num_funcs; i++)
X	    printf(" %lf %lf", fac * sin(i * x), fac * cos(i * x));
X	printf("\n");
X	x = x + dx;
X	fac = fac * facfac;
X	sleep(1);
X    }
X}
________This_Is_The_END________
if test `wc -l < fakeit.c` -ne 35; then
	echo -n 'shar: fakeit.c was damaged during transit'
	echo ' (should have been 35 bytes)'
fi
fi		; : end of overwriting check
echo 'x - get_axis_bounds.c'
if test -f get_axis_bounds.c
then echo 'shar: not overwriting get_axis_bounds.c'; else
sed 's/^X//' << '________This_Is_The_END________' > get_axis_bounds.c
X#include <math.h>
X
Xvoid
Xget_axis_bounds(actual_min, actual_max, graph_min, graph_max)
X    float           actual_min, actual_max;
X    float          *graph_min, *graph_max;
X/*
X * get_axis_bounds returns good bounds for graphing the actual range.
X * The min and max bounds are guaranteed to be different.
X */
X{
X    double          range;
X    double          range_log, range_mantissa, range_exponent;
X    double          precision;
X
X    range = actual_max - actual_min;
X
X    if (range < 1e-20) {	/* Too small to be of use */
X	*graph_min = actual_min;
X	*graph_max = *graph_min + 1.;
X	return;
X    }
X    /* Get the order of magnitude of the range */
X    range_log = log10(range);
X    range_exponent = floor(range_log);
X    range_mantissa = range_log - range_exponent;
X
X    /* returned range is either 2, 5, or 10 */
X    if (range_mantissa < 0.3)
X	precision = 2. * pow(10., range_exponent);
X    else if (range_mantissa < 0.7)
X	precision = 5. * pow(10., range_exponent);
X    else
X	precision = 10. * pow(10., range_exponent);
X
X    *graph_min = precision * floor(actual_min / precision);
X    *graph_max = precision * ceil(actual_max / precision);
X
X    if (*graph_min == *graph_max)
X	*graph_max = *graph_max + 1.;
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < get_axis_bounds.c` -ne 43; then
	echo -n 'shar: get_axis_bounds.c was damaged during transit'
	echo ' (should have been 43 bytes)'
fi
fi		; : end of overwriting check
echo 'x - get_axis_log_bounds.c'
if test -f get_axis_log_bounds.c
then echo 'shar: not overwriting get_axis_log_bounds.c'; else
sed 's/^X//' << '________This_Is_The_END________' > get_axis_log_bounds.c
X#include <math.h>
X
Xvoid
Xget_axis_log_bounds(actual_min, actual_max, graph_min, graph_max)
X    float           actual_min, actual_max;
X    float          *graph_min, *graph_max;
X/*
X * get_axis_log_bounds returns good bounds for graphing the range.
X * The format is suitable for a log graph.
X * The min and max bounds are guaranteed to be different.
X */
X{
X    double          v_log, v_exponent;
X
X    if (actual_min <= 0.) {	/* no positive values in range */
X	*graph_min = 0.;	/* Let repaint bounce the values */
X	*graph_max = 0.;
X	return;
X    }
X    /*
X     * set the minimum graph value to be just `1' under the minimum
X     * actual value, where the `1' is one most significant digit.
X     */
X    v_log = log10(actual_min);
X    v_exponent = floor(v_log);
X    *graph_min = pow(10., v_exponent) * floor(pow(10., v_log - v_exponent));
X
X    /*
X     * set the maximum graph value to be just `1' over the maximum
X     * actual value, where the `1' is one most significant digit.
X     */
X    v_log = log10(actual_max);
X    v_exponent = floor(v_log);
X    *graph_max = pow(10., v_exponent) * ceil(pow(10., v_log - v_exponent));
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < get_axis_log_bounds.c` -ne 37; then
	echo -n 'shar: get_axis_log_bounds.c was damaged during transit'
	echo ' (should have been 37 bytes)'
fi
fi		; : end of overwriting check
echo 'x - get_grid_bounds.c'
if test -f get_grid_bounds.c
then echo 'shar: not overwriting get_grid_bounds.c'; else
sed 's/^X//' << '________This_Is_The_END________' > get_grid_bounds.c
X#include <math.h>
X
Xvoid
Xget_grid_bounds(v_min, v_max, g_min_ptr, g_max_ptr, g_delta_ptr)
X    float           v_min, v_max;
X    float          *g_min_ptr, *g_max_ptr, *g_delta_ptr;
X{
X    /* Returns good bounds for graphing the grid lines. */
X
X    double          range;
X    double          range_log, range_mantissa, range_exponent;
X
X    range = v_max - v_min;
X
X    if (range < 1e-20) {
X	*g_min_ptr = v_min;
X	*g_max_ptr = v_min - 1.;
X	*g_delta_ptr = 1.;
X	return;
X    }
X    range_log = log10(range);
X    range_exponent = floor(range_log);
X    range_mantissa = range_log - range_exponent;
X
X    if (range_mantissa < 0.3)	/* 1-2, grid 0.2; 5-10 lines */
X	*g_delta_ptr = 0.2 * pow(10., range_exponent);
X    else if (range_mantissa < 0.7)	/* 2-5, grid 0.2; 4-10 lines */
X	*g_delta_ptr = 0.5 * pow(10., range_exponent);
X    else			/* 5-10, grid 0.2; 5-10 lines */
X	*g_delta_ptr = pow(10., range_exponent);
X
X    *g_min_ptr = *g_delta_ptr * ceil(v_min / *g_delta_ptr);
X    *g_max_ptr = *g_delta_ptr * (floor(v_max / *g_delta_ptr + 0.01) + 0.1);
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < get_grid_bounds.c` -ne 36; then
	echo -n 'shar: get_grid_bounds.c was damaged during transit'
	echo ' (should have been 36 bytes)'
fi
fi		; : end of overwriting check
echo 'x - get_grid_log_bounds.c'
if test -f get_grid_log_bounds.c
then echo 'shar: not overwriting get_grid_log_bounds.c'; else
sed 's/^X//' << '________This_Is_The_END________' > get_grid_log_bounds.c
X#include <math.h>
X
Xvoid
Xget_grid_log_bounds(v_min, v_max,
X    g_min_ptr, g_max_ptr, g_delta_ptr, g_switch_ptr)
X    float           v_min, v_max;
X    float          *g_min_ptr, *g_max_ptr, *g_delta_ptr, *g_switch_ptr;
X{
X    /*
X     * Returns good bounds for graphing the grid lines on a log scale.
X     * v_min, v_max are the logs of the bounds.
X     */
X
X    double          v_exponent;
X
X    v_exponent = floor(v_min);	/* scale for min, delta */
X
X    /*
X     * Scale of the minimum value sets the initial grid spacing. The
X     * minimum grid value is the one just up from the minimum axis
X     * value.  The grid spacing switched when the grid line is an order
X     * of magnitude above the grid spacing.
X     */
X    *g_delta_ptr = pow(10., v_exponent);
X    *g_min_ptr = *g_delta_ptr * ceil(pow(10., v_min - v_exponent));
X    *g_switch_ptr = *g_delta_ptr * 10.5;
X
X    /* See if we need to got to the next grid spacing yet. */
X    if (*g_min_ptr + *g_delta_ptr > *g_switch_ptr) {
X	*g_delta_ptr *= 10.;
X	*g_switch_ptr *= 10.;
X    }
X    /* Maximum grid line is simply set by the max value */
X    *g_max_ptr = pow(10., v_max) * 1.01;
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < get_grid_log_bounds.c` -ne 37; then
	echo -n 'shar: get_grid_log_bounds.c was damaged during transit'
	echo ' (should have been 37 bytes)'
fi
fi		; : end of overwriting check
echo 'x - get_next_string.c'
if test -f get_next_string.c
then echo 'shar: not overwriting get_next_string.c'; else
sed 's/^X//' << '________This_Is_The_END________' > get_next_string.c
X#include <stdio.h>
X#include <string.h>
X
Xint
Xget_next_string(s_l, s_r, n, stream)
X    char            s_l[], s_r[];
Xint             n;
XFILE           *stream;
X{
X    /*
X     * reads  strings s_l, s_r from stream up to n-1 characters and
X     * terminates with a null.  Differs from fgets in that new-lines
X     * are discarded and preceeding blanks ignored. s_l is
X     * left-justified and s_r is right-justified. It returns the length
X     * of the non-blank string.
X     */
X    int             i = 0, j;
X    char            c;
X
X    while ((c = getc(stream)) == ' ');	/* skip to non-blank */
X
X    if (c == '\n') {
X	s_l[i] = '\0';
X	s_r[i] = '\0';
X	return i;
X    }
X    s_l[n - 1] = '\0';
X    s_r[n - 1] = '\0';
X
X    s_l[i++] = c;
X
X    while ((c = getc(stream)) != ' ') {
X	if (c == '\n') {
X	    ungetc(c, stream);
X	    break;
X	}
X	s_l[i++] = c;
X
X	/* skip over unused string if we already have n-1 characters */
X	if (i == n - 1) {
X	    while ((c = getc(stream)) != ' ') {
X		if (c == '\n') {
X		    ungetc(c, stream);
X		    break;
X		}
X	    }
X	    strcpy(s_r, s_l);
X	    return i;
X	}
X    }
X    s_l[i] = '\0';
X
X    /* copy string from left to right-justified position */
X    strncpy(&s_r[n - i - 1], s_l, i);
X    for (j = i; j < n - 1; j++) {
X	s_r[n - 2 - j] = ' ';
X    }
X
X    return i;
X}
________This_Is_The_END________
if test `wc -l < get_next_string.c` -ne 60; then
	echo -n 'shar: get_next_string.c was damaged during transit'
	echo ' (should have been 60 bytes)'
fi
fi		; : end of overwriting check
echo 'x - init_arrays.c'
if test -f init_arrays.c
then echo 'shar: not overwriting init_arrays.c'; else
sed 's/^X//' << '________This_Is_The_END________' > init_arrays.c
X#include "trackertool.h"
X
Xvoid
Xinit_arrays(subframe_ptr)
X    Subframe       *subframe_ptr;
X{
X    /* set the default variables */
X
X    subframe_ptr->x = array_ptr[0];
X    subframe_ptr->y = array_ptr[
X	(num_of_subframes + 1 < num_arrays) ? num_of_subframes + 1 : 1];
X
X    subframe_ptr->x_min_auto = TRUE;
X    subframe_ptr->x_max_auto = TRUE;
X    subframe_ptr->y_min_auto = TRUE;
X    subframe_ptr->y_max_auto = TRUE;
X
X    subframe_ptr->x_log = FALSE;
X    subframe_ptr->y_log = FALSE;
X    subframe_ptr->x_grid = FALSE;
X    subframe_ptr->y_grid = FALSE;
X    subframe_ptr->connect_points = TRUE;
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < init_arrays.c` -ne 25; then
	echo -n 'shar: init_arrays.c was damaged during transit'
	echo ' (should have been 25 bytes)'
fi
fi		; : end of overwriting check
echo 'x - init_choices.c'
if test -f init_choices.c
then echo 'shar: not overwriting init_choices.c'; else
sed 's/^X//' << '________This_Is_The_END________' > init_choices.c
X#include "trackertool.h"
X
Xvoid
Xinit_choices(choice_list)
X    Attr_avlist     choice_list[MAX_ARRAYS + 2];
X /*
X  * We set up the pointers to character strings for the pull-down menu
X  * that comes up when the user chooses a variable for the ordinate or
X  * the abscissa.
X  */
X{
X    int             i = 0;
X
X    choice_list[i] = (Attr_avlist) PANEL_CHOICE_STRINGS;
X
X    for (; i <= num_arrays; i++)
X	choice_list[i + 1] = (Attr_avlist) array_ptr[i]->label_l;
X
X    for (i++; i < MAX_ARRAYS + 2; i++)
X	choice_list[i] = 0;
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < init_choices.c` -ne 23; then
	echo -n 'shar: init_choices.c was damaged during transit'
	echo ' (should have been 23 bytes)'
fi
fi		; : end of overwriting check
echo 'x - kill_view_proc.c'
if test -f kill_view_proc.c
then echo 'shar: not overwriting kill_view_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > kill_view_proc.c
X#include "trackertool.h"
X#include <stdio.h>
X
Xvoid
Xkill_view_proc(button)
X    Panel_item      button;
X /*
X  * Kills the view (subframe) and releases the associated memory and
X  * file descriptors.  Renumbers the other views.
X  */
X{
X    Panel           panel;
X    Frame           frame;
X    int             frame_no;
X    Subframe       *subframe_ptr;
X    char            string[22];
X
X    panel = (Panel) panel_get(button, PANEL_PARENT_PANEL);
X    frame = (Frame) window_get(panel, WIN_OWNER);
X    frame_no = (int) window_get(frame, WIN_CLIENT_DATA, 0);
X    subframe_ptr = subframe[frame_no];
X
X    /* recover the file descriptors */
X    num_fd -= 1;		/* main frame */
X    if (subframe_ptr->textsw)
X	num_fd -= 3;
X    if (subframe_ptr->canvas)
X	num_fd -= 1;
X    if (subframe_ptr->props)
X	num_fd -= 1;
X    if (subframe_ptr->panel)
X	num_fd -= 1;
X
X    /* get rid of this subframe completely */
X    window_destroy(frame);
X    free(subframe_ptr);
X
X    /*
X     * renumber the successive subframes, not forgetting the internal
X     * client data.
X     */
X    for (; frame_no < num_of_subframes; frame_no++) {
X	subframe[frame_no] = subframe[frame_no + 1];
X	sprintf(string, "Trackertool view #%2d", frame_no + 1);
X	subframe_ptr = subframe[frame_no];
X	window_set(subframe_ptr->handle,
X	    FRAME_LABEL, string,
X	    WIN_CLIENT_DATA, frame_no,
X	    0);
X	if (subframe_ptr->textsw)
X	    window_set(subframe_ptr->textsw,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X	if (subframe_ptr->canvas)
X	    window_set(subframe_ptr->canvas,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X	if (subframe_ptr->props)
X	    window_set(subframe_ptr->props,
X		WIN_CLIENT_DATA, subframe_ptr,
X		0);
X    }
X    num_of_subframes--;
X
X    /* See if we have enough fd's left to make another view */
X    if (num_fd + 3 <= MAX_FD)
X	panel_set(view_button, PANEL_SHOW_ITEM, TRUE, 0);
X
X    return;
X}
________This_Is_The_END________
if test `wc -l < kill_view_proc.c` -ne 70; then
	echo -n 'shar: kill_view_proc.c was damaged during transit'
	echo ' (should have been 70 bytes)'
fi
fi		; : end of overwriting check
exit 0
-- 
Roy Richter                  UUCP:  {sharkey,edsews,cfctech}!rphroy!rrichter
Physics Dept, GM Research    CSNet: rrichter@gmr.com
                             Internet: rrichter%rphroy.uucp@mailgw.cc.umich.edu