home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-03-18 | 37.8 KB | 1,914 lines |
-
- static char RCSId[] = "$Id: Status.m,v 1.1.1.1 1993/03/18 03:35:28 davis Exp $";
-
-
- #import <appkit/Font.h>
- #import <appkit/nextstd.h> /* NX_FREE */
-
- #import <objc/hashtable.h> /* NXCopyStringBufferFromZone() */
- #import <objc/zone.h>
-
- #import <setjmp.h> /* setjmp() */
- #import <stdio.h>
- #import <stdlib.h>
- #import <strings.h> /* strcat(), strcpy(), index() */
-
- #import "FunctionObject.h"
- #import "GnuplotPlot.h"
- #import "Status.h"
- #import "TicObject.h"
-
-
- @interface Status (Private)
-
- - (const char *) _copyString:(const char *)source to:(char **)dest;
- - _doText:(const char *)theText;
- - _setText:(const char *) aString;
-
- @end
-
-
- /*
- * We can't import all of plot.h because of various complications
- * (redefinitions, conflicting identifiers, etc.), but we need the
- * following structures which are defined there.
- */
- struct ticdef {
- int type; /* one of three constants */
- union {
- struct { /* for TIC_SERIES */
- double start, incr;
- double end;
- } series;
- struct ticmark *user; /* for TIC_USER */
- } def;
- };
-
- struct ticmark {
- double position; /* where on axis is this */
- char *label; /* optional string label */
- struct ticmark *next; /* linked list */
- };
-
-
-
- /*
- * The class records which Status object was the last to issue a plot
- * command to Gnuplot. We need to know this when we set our instance
- * variables to the corresponding Gnuplot values -- see -grabCurrent.
- */
- static id lastplot = nil;
-
- #define MAX_LINE_LEN 1024 /* Same as in plot.h */
- #define DEFAULT_FONT "Helvetica"
-
- #define CONTOUR_NONE 0 /* Where to place contour maps if at all. */
- #define CONTOUR_BASE 1
- #define CONTOUR_SRF 2
- #define CONTOUR_BOTH 3
-
-
- /*
- * All instance variables begin with s_ to avoid confusion with the
- * variables defined in gnuplot .c files.
- *
- * gnuplot Variable (setshow.c) Status Instance Variable
- * ---------------------------- ------------------------
- */
- extern char nextfe_font[]; /* s_font */
- extern int nextfe_fontsize; /* s_fontsize */
- extern char title[]; /* s_title */
- extern char xlabel[]; /* s_labelCoord[] */
- extern char ylabel[];
- extern char zlabel[];
- extern char dummy_var[][51]; /* s_dummy_var[] */
- extern int parametric; /* s_parametric */
- extern int polar; /* s_polar */
- extern int draw_border; /* s_border */
- extern int draw_surface; /* s_draw_surface */
- extern int draw_contour;
- extern int contour_kind; /* s_contour_kind */
- extern int contour_pts; /* s_contour_pts */
- extern int contour_order; /* s_contour_order */
- extern int label_contours; /* s_label_contours */
- extern int grid; /* s_grid */
- extern int xzeroaxis; /* s_xzeroaxis */
- extern int yzeroaxis; /* s_yzeroaxis */
- extern int tic_in; /* s_tics_in */
- extern int xtics, ytics, ztics; /* s_ticsCoord[] */
- extern struct ticdef xticdef; /* s_ticdefCoord[] */
- extern struct ticdef yticdef;
- extern struct ticdef zticdef;
- extern int is_log_x, is_log_y, is_log_z;/* s_isLogCoord[] */
-
- extern double base_log_x, base_log_y, /* Currently unused by Status */
- base_log_z; //
- extern double log_base_log_x,
- log_base_log_y,
- log_base_log_z;
-
-
- extern int key; /* s_key */
- extern double key_x, key_y, key_z; /* s_keyCoord[] */
- extern int timedate; /* s_time */
- extern int time_xoffset, time_yoffset; /* s_timeCoord[] */
- extern float xsize, ysize; /* s_xsize, s_ysize */
- extern float surface_rot_x; /* s_rot_x */
- extern float surface_rot_z; /* s_rot_z */
- extern int hidden3d; /* s_hidden3d */
- extern int autoscale_x; /* s_autoscaleCoord[] */
- extern int autoscale_y;
- extern int autoscale_z;
- extern int autoscale_r;
- extern double xmin, xmax; /* s_minCoord[], s_maxCoord[] */
- extern double ymin, ymax;
- extern double zmin, zmax;
- extern double rmin, rmax;
- extern int angles_format; /* degrees */
- extern int samples; /* s_samples */
- extern int samples_1; /* s_samplesCoord */
- extern int samples_2;
- extern int iso_samples_1; /* s_iso_samplesCoord */
- extern int iso_samples_2;
- extern char replot_line[]; /* s_plotargs */
- extern NXStream *EPSStream; /* s_epsStream (terminal) */
- extern int nextfe_halve; /* (GnuplotPlot preference) */
- extern NEXTFE_reset(); /* Appends PS Trailer to stream */
-
-
- /*
- * Removes leading blanks and tabs.
- */
- static char *_removeLeadingBlanks (char *aString)
- {
- char *cur;
-
- cur = aString;
- if (cur && ((*cur == ' ') || (*cur == '\t')))
- cur++;
-
- strcpy (aString, cur);
- return aString;
- }
-
-
- /*
- * Stores the first line, up to max characters, from the multi-line
- * string source in dest and returns a pointer to it. It replaces
- * the newline with a null character. If the line was the last in
- * the string, it returns NULL.
- */
- static char *_get_line (char *dest, int max, const char *source)
- {
- char *returnVal = dest;
-
- if (source && dest) {
- while ((*source != '\n') && (*source != '\0') && (max > 0)) {
- *dest = *source;
- dest++;
- source++;
- max--;
- }
-
- *dest = '\0';
-
- if (*source == '\n')
- return returnVal;
- } /* NULL is returned if line is */
- /* too long or end of source */
- return NULL; /* or dest string is reached. */
- }
-
-
- /*
- * Frees the list of ticmarks whose head is pointed to by t and sets
- * t to NULL.
- */
- static void _freeLinkedList(struct ticmark **t)
- {
- struct ticmark *cur;
-
- while (*t) {
- cur = *t;
- *t = (*t)->next;
- free (cur);
- }
-
- *t = NULL;
- return;
- }
-
-
- @implementation Status
-
- + lastplot
- {
- return lastplot;
- }
-
-
- + setHalvePlot:(BOOL)condition
- {
- nextfe_halve = condition;
- return self;
- }
-
-
- - init
- {
- int counter;
-
- [super init];
- zone = [self zone];
-
- functions = nil;
-
- delegate = nil;
- report = YES;
-
- s_epsStream = NULL;
-
- /*
- * Set all pointers to NULL or nil so -resetCurrent
- * doesn't try to free them.
- */
- text = s_title = s_plotargs = s_font = appendix =
- s_dummy_var[0] = s_dummy_var[1] = NULL;
-
- for (counter = 0 ; counter < 3 ; counter++) {
- s_labelCoord[counter] = NULL;
- ticDefs[counter] = nil;
- }
-
- [self resetCurrent];
-
- return self;
- }
-
-
- - free
- {
- int counter;
-
- if (s_epsStream)
- NXCloseMemory (s_epsStream, NX_FREEBUFFER);
-
- /*
- * NXZoneFree() doesn't bomb if you give it a NULL pointer, so we
- * don't bother to check the pointer.
- */
-
- NXZoneFree (zone, text);
- NXZoneFree (zone, appendix);
-
- NXZoneFree (zone, s_title);
- NXZoneFree (zone, s_font);
-
- NXZoneFree (zone, s_dummy_var[0]);
- NXZoneFree (zone, s_dummy_var[1]);
-
- for (counter = 0 ; counter < 3 ; counter++) {
- if (ticDefs[counter])
- [[ticDefs[counter] freeObjects] free];
- NXZoneFree (zone, s_labelCoord[counter]);
- }
-
- NXZoneFree (zone, s_plotargs);
-
- if (functions)
- [[functions freeObjects] free];
-
- lastplot = nil;
-
- return [super free];
- }
-
-
- - setReport:(BOOL)cond
- {
- report = cond;
- return self;
- }
-
-
- - (BOOL)report
- {
- return report;
- }
-
-
- - setDelegate: anObject
- {
- delegate = anObject;
- return self;
- }
-
-
- - delegate
- {
- return delegate;
- }
-
-
- - (NXStream *)stream
- {
- return s_epsStream;
- }
-
-
-
- - (BOOL)canPlot
- {
- int count = 0, index;
- int total = [functions count];
-
- /* Count the number of functions */
- index = total;
- while (index--)
- count += ([[functions objectAt:index] isDataFile]) ? 0 : 1;
-
- /*
- * We can plot iff
- *
- * 1) there is an appendix
- *
- * or
- *
- * 2) there is at least one FunctionObject and
- * 3) if the plot is parametric then
- * a) we have pairs of functions (two-dimensional),
- * b) or we have triplets of functions (3-dimens.)
- *
- */
-
- return ((appendix && *appendix) ||
- (total &&
- (s_parametric? (isThreeD? !(count % 3)
- : (!(count % 2) && (total == count)))
- :YES)));
-
- }
-
-
- - plot
- {
- [self applyCurrent];
- lastplot = self;
-
- if (areSettingsEdited && !appendix) {
- [self buildPlotargs];
- [self _setText:s_plotargs];
-
- areSettingsEdited = NO;
- }
-
- if (appendix && *appendix)
- [self _setText:appendix]; /* Appendix overrides current plot */
-
- return [self _doText:text];
- }
-
-
-
- - saveToFile:(const char *)filename
- {
- char *copy, *line, *cur;
- id returnVal;
-
- /*
- * Gnuplot sometimes drops characters off the end of long
- * pathnames given to the "save" command, a bug that seems to
- * have been introduced between 3.1 and 3.2. We work around it
- * by cd'ing to the directory first and then saving the file.
- */
- copy = NXCopyStringBufferFromZone (filename, zone);
-
- if (cur = rindex (copy, '/')) {
- *(cur++) = '\0';
- line = NXZoneMalloc (zone, 15 + strlen (filename));
- sprintf (line, "cd '%s'\nsave '%s'\n", copy, cur);
- } else {
- line = NXZoneMalloc (zone, 9 + strlen (filename));
- sprintf (line, "save '%s'\n", filename);
- }
-
- returnVal = [self _doText:line]? self : nil;
- NXZoneFree (zone, copy);
- NXZoneFree (zone, line);
-
- return returnVal;
- }
-
-
-
- - reportSettingsChange:sender
- {
- areSettingsEdited = YES;
- lastplot = nil; /* Last valid plot is no longer valid */
-
- if (delegate && report)
- [delegate settingsDidChange:self];
-
- return self;
- }
-
-
-
- /*
- * Resets all the instance variables to their default values.
- */
- - resetCurrent
- {
- int counter;
-
- if (functions)
- [functions freeObjects];
- else
- functions = [[List allocFromZone:zone] init];
-
- NXZoneFree (zone, text);
- text = NULL;
-
- NXZoneFree (zone, s_title);
- s_title = NULL;
-
- NXZoneFree (zone, s_dummy_var[0]);
- s_dummy_var[0] = NULL;
-
- NXZoneFree (zone, s_dummy_var[1]);
- s_dummy_var[1] = NULL;
-
- for (counter = 0 ; counter < 3 ; counter++) {
- NXZoneFree (zone, s_labelCoord[counter]);
- s_labelCoord[counter] = NULL;
- s_minCoord[counter] = -10.0;
- s_maxCoord[counter] = 10.0;
- s_isLogCoord[counter] = 0;
- s_ticsCoord[counter] = 1;
- s_ticTypeCoord[counter] = TIC_COMPUTED;
- s_ticSeriesCoord[counter].start = -10.0;
- s_ticSeriesCoord[counter].incr = 5.0;
- s_ticSeriesCoord[counter].end = 10.0;
- if (ticDefs[counter])
- [ticDefs[counter] freeObjects];
- else
- ticDefs[counter] = [[DoubleValueSortedList allocFromZone:zone]
- init];
- }
-
- s_minCoord[R_TAG] = -0.0; /* Gnuplot uses -0.0, not sure why */
- s_maxCoord[R_TAG] = 10.0;
-
- degrees = NO;
-
- NXZoneFree (zone, s_plotargs);
- s_plotargs = NULL;
-
- NXZoneFree (zone, s_font);
- s_font = NULL;
-
- NXZoneFree (zone, appendix);
- appendix = NULL;
-
- s_fontsize = 16;
-
- isThreeD = NO;
- s_parametric = NO;
- s_polar = NO;
- s_border = YES;
- s_draw_surface = YES;
- contourBase = NO;
- contourSurface = NO;
- s_contour_kind = CONTOUR_KIND_LINEAR;
- s_contour_pts = 5;
- s_contour_order = 4;
- s_label_contours = YES;
- s_hidden3d = NO;
- s_grid = NO;
- s_xzeroaxis = YES;
- s_yzeroaxis = YES;
-
- s_tics_in = YES;
-
- s_key = YES; /* Plot has a key, in default location */
- s_key_default = YES;
-
- s_time = NO; /* Don't show time/date */
- s_time_default = YES;
-
- for (counter = 0 ; counter < 4 ; counter++)
- s_autoscaleCoord[counter] = 1;
-
- sizeProp = YES; /* Keep x, y, z proportional */
- s_xsize = s_ysize = 1.0;
- s_samples = s_samplesCoord[X_TAG] = s_samplesCoord[Y_TAG] = 100;
- s_iso_samplesCoord[X_TAG] = s_iso_samplesCoord[Y_TAG] = 10;
-
- s_rotCoord[X_TAG] = 60.0;
- s_rotCoord[Z_TAG] = 30.0;
-
- areSettingsEdited = NO;
-
- return self;
- }
-
-
-
-
-
- /* Sets the current gnuplot settings to the Status instance variables. */
- - applyCurrent
- {
- if (s_font)
- strcpy (nextfe_font, s_font);
- else
- strcpy (nextfe_font, DEFAULT_FONT);
-
- nextfe_fontsize = s_fontsize;
-
- if (s_title)
- strcpy (title, s_title);
- else
- strcpy (title, "");
-
- if (s_dummy_var[0])
- strcpy (dummy_var[0], s_dummy_var[0]);
- else
- strcpy (dummy_var[0], "x");
-
- if (s_dummy_var[1])
- strcpy (dummy_var[1], s_dummy_var[1]);
- else
- strcpy (dummy_var[1], "y");
-
- if (s_labelCoord[X_TAG])
- strcpy (xlabel, s_labelCoord[X_TAG]);
- else
- strcpy (xlabel, "");
-
- if (s_labelCoord[Y_TAG])
- strcpy (ylabel, s_labelCoord[Y_TAG]);
- else
- strcpy (ylabel, "");
-
- if (s_labelCoord[Z_TAG])
- strcpy (zlabel, s_labelCoord[Z_TAG]);
- else
- strcpy (zlabel, "");
-
- parametric = s_parametric;
- polar = s_polar;
- draw_border = s_border;
- draw_surface = s_draw_surface;
-
- if (!contourBase && !contourSurface)
- draw_contour = CONTOUR_NONE;
- else if (contourBase && contourSurface)
- draw_contour = CONTOUR_BOTH;
- else if (contourBase)
- draw_contour = CONTOUR_BASE;
- else if (contourSurface)
- draw_contour = CONTOUR_SRF;
-
- contour_kind = s_contour_kind;
- contour_pts = s_contour_pts;
- contour_order = s_contour_order;
- label_contours = s_label_contours;
-
- hidden3d = s_hidden3d;
- grid = s_grid;
- xzeroaxis = s_xzeroaxis;
- yzeroaxis = s_yzeroaxis;
-
- tic_in = s_tics_in;
- xtics = s_ticsCoord[X_TAG];
- ytics = s_ticsCoord[Y_TAG];
- ztics = s_ticsCoord[Z_TAG];
- [self applyCurrentTicDefs];
-
- is_log_x = s_isLogCoord[X_TAG];
- is_log_y = s_isLogCoord[Y_TAG];
- is_log_z = s_isLogCoord[Z_TAG];
-
- base_log_x = base_log_y = base_log_z = 10.0;
- log_base_log_x = log_base_log_y = log_base_log_z = log(10.0);
-
- autoscale_x = s_autoscaleCoord[X_TAG];
- autoscale_y = s_autoscaleCoord[Y_TAG];
- autoscale_z = s_autoscaleCoord[Z_TAG];
- autoscale_r = s_autoscaleCoord[R_TAG];
-
- xmin = s_minCoord[X_TAG];
- xmax = s_maxCoord[X_TAG];
- ymin = s_minCoord[Y_TAG];
- ymax = s_maxCoord[Y_TAG];
- zmin = s_minCoord[Z_TAG];
- zmax = s_maxCoord[Z_TAG];
- rmin = s_minCoord[R_TAG];
- rmax = s_maxCoord[R_TAG];
-
- angles_format = degrees? ANGLES_DEGREES :ANGLES_RADIANS;
-
- key = s_key? (s_key_default? -1 :1) :0;
- key_x = s_keyCoord[X_TAG];
- key_y = s_keyCoord[Y_TAG];
- key_z = s_keyCoord[Z_TAG];
-
- timedate = s_time? 1 :0;
- if (s_time && !(s_title && *s_title))
- strcpy (title, " "); // Kludge to make time visible if no title
- time_xoffset = (s_time_default? 0 :s_timeCoord[X_TAG]);
- time_yoffset = (s_time_default? 0 :s_timeCoord[Y_TAG]);
-
- xsize = s_xsize;
- ysize = s_ysize;
-
- surface_rot_x = s_rotCoord[X_TAG];
- surface_rot_z = s_rotCoord[Z_TAG];
-
- samples = s_samples;
- samples_1 = s_samplesCoord[X_TAG];
- samples_2 = s_samplesCoord[Y_TAG];
- iso_samples_1 = s_iso_samplesCoord[X_TAG];
- iso_samples_2 = s_iso_samplesCoord[Y_TAG];
-
- return self;
- }
-
-
-
- - applyCurrentTicDefs
- {
- int count;
- struct ticmark *new;
- id tic;
-
- switch (s_ticTypeCoord[X_TAG]) {
- case TIC_SERIES:
- xticdef.def.series.start = s_ticSeriesCoord[X_TAG].start;
- xticdef.def.series.incr = s_ticSeriesCoord[X_TAG].incr;
- xticdef.def.series.end = s_ticSeriesCoord[X_TAG].end;
- break;
- case TIC_USER:
- if (xticdef.type == TIC_USER)
- _freeLinkedList (&(xticdef.def.user));
- else
- xticdef.def.user = NULL;
- if ((count = [ticDefs[X_TAG] count] - 1) >= 0) {
- new = xticdef.def.user = malloc (sizeof (struct ticmark));
- while (count >= 0) {
- new->position = [tic = [ticDefs[X_TAG] objectAt:count]
- doubleValue];
- new->label = (char *) [tic stringValue];
- if (count--) {
- new->next = malloc (sizeof (struct ticmark));
- new = new->next;
- } else
- new->next = NULL;
- }
- break;
- }
- }
- xticdef.type = s_ticTypeCoord[X_TAG];
-
- switch (s_ticTypeCoord[Y_TAG]) {
- case TIC_SERIES:
- yticdef.def.series.start = s_ticSeriesCoord[Y_TAG].start;
- yticdef.def.series.incr = s_ticSeriesCoord[Y_TAG].incr;
- yticdef.def.series.end = s_ticSeriesCoord[Y_TAG].end;
- break;
- case TIC_USER:
- if (yticdef.type == TIC_USER)
- _freeLinkedList (&(yticdef.def.user));
- else
- yticdef.def.user = NULL;
- if ((count = [ticDefs[Y_TAG] count] - 1) >= 0) {
- new = yticdef.def.user = malloc (sizeof (struct ticmark));
- while (count >= 0) {
- new->position = [tic = [ticDefs[Y_TAG] objectAt:count]
- doubleValue];
- new->label = (char *) [tic stringValue];
- if (count--) {
- new->next = malloc (sizeof (struct ticmark));
- new = new->next;
- } else
- new->next = NULL;
- }
- break;
- }
- }
- yticdef.type = s_ticTypeCoord[Y_TAG];
-
- switch (s_ticTypeCoord[Z_TAG]) {
- case TIC_SERIES:
- zticdef.def.series.start = s_ticSeriesCoord[Z_TAG].start;
- zticdef.def.series.incr = s_ticSeriesCoord[Z_TAG].incr;
- zticdef.def.series.end = s_ticSeriesCoord[Z_TAG].end;
- break;
- case TIC_USER:
- if (zticdef.type == TIC_USER)
- _freeLinkedList (&(zticdef.def.user));
- else
- zticdef.def.user = NULL;
- if ((count = [ticDefs[Z_TAG] count] - 1) >= 0) {
- new = zticdef.def.user = malloc (sizeof (struct ticmark));
- while (count >= 0) {
- new->position = [tic = [ticDefs[Z_TAG] objectAt:count]
- doubleValue];
- new->label = (char *) [tic stringValue];
- if (count--) {
- new->next = malloc (sizeof (struct ticmark));
- new = new->next;
- } else
- new->next = NULL;
- }
- break;
- }
-
- }
- zticdef.type = s_ticTypeCoord[Z_TAG];
-
- return self;
- }
-
-
- /*
- * Resets all the instance variables to the current gnuplot settings,
- * all of which pertain to the most recent plot:
- */
- - grabCurrent
- {
- char *cur;
-
- NXZoneFree (zone, s_font);
- s_font = NXCopyStringBufferFromZone (nextfe_font, zone);
-
- s_fontsize = nextfe_fontsize;
-
- NXZoneFree (zone, s_title);
- s_title = NXCopyStringBufferFromZone (title, zone);
-
- NXZoneFree (zone, s_dummy_var[0]);
- s_dummy_var[0] = NXCopyStringBufferFromZone (dummy_var[0], zone);
-
- NXZoneFree (zone, s_dummy_var[1]);
- s_dummy_var[1] = NXCopyStringBufferFromZone (dummy_var[1], zone);
-
- NXZoneFree (zone, s_labelCoord[X_TAG]);
- s_labelCoord[X_TAG] = NXCopyStringBufferFromZone (xlabel, zone);
-
- NXZoneFree (zone, s_labelCoord[Y_TAG]);
- s_labelCoord[Y_TAG] = NXCopyStringBufferFromZone (ylabel, zone);
-
- NXZoneFree (zone, s_labelCoord[Z_TAG]);
- s_labelCoord[Z_TAG] = NXCopyStringBufferFromZone (zlabel, zone);
-
- [self grabCurrentTicDefs];
-
- /*
- * If the last plot command was "splot," as opposed to "plot,"
- * it is three dimensional.
- */
- isThreeD = (*(_removeLeadingBlanks(replot_line)) == 's');
-
- s_parametric = parametric;
- s_polar = polar;
- s_border = draw_border;
- s_draw_surface = draw_surface;
-
- switch (draw_surface) {
- case CONTOUR_NONE:
- contourBase = contourSurface = NO;
- break;
- case CONTOUR_BASE:
- contourBase = YES;
- contourSurface = NO;
- break;
- case CONTOUR_SRF:
- contourBase = NO;
- contourSurface = YES;
- break;
- default:
- contourBase = YES;
- contourSurface = YES;
- break;
- }
-
- s_contour_kind = contour_kind;
- s_contour_pts = contour_pts;
- s_contour_order = contour_order;
- s_label_contours = label_contours;
-
- s_hidden3d = hidden3d;
- s_grid = grid;
- s_xzeroaxis = xzeroaxis;
- s_yzeroaxis = yzeroaxis;
-
- s_tics_in = tic_in;
- s_ticsCoord[X_TAG] = xtics;
- s_ticsCoord[Y_TAG] = ytics;
- s_ticsCoord[Z_TAG] = ztics;
-
- s_isLogCoord[X_TAG] = is_log_x;
- s_isLogCoord[Y_TAG] = is_log_y;
- s_isLogCoord[Z_TAG] = is_log_z;
-
- s_autoscaleCoord[X_TAG] = autoscale_x;
- s_autoscaleCoord[Y_TAG] = autoscale_y;
- s_autoscaleCoord[Z_TAG] = autoscale_z;
- s_autoscaleCoord[R_TAG] = autoscale_r;
-
- s_minCoord[X_TAG] = xmin;
- s_maxCoord[X_TAG] = xmax;
- s_minCoord[Y_TAG] = ymin;
- s_maxCoord[Y_TAG] = ymax;
- s_minCoord[Z_TAG] = zmin;
- s_maxCoord[Z_TAG] = zmax;
- s_minCoord[R_TAG] = rmin;
- s_maxCoord[R_TAG] = rmax;
-
- degrees = (angles_format == ANGLES_DEGREES);
-
- s_key = ((key == -1) || (key == 1));
- s_key_default = (key == -1);
- s_keyCoord[X_TAG] = key_x;
- s_keyCoord[Y_TAG] = key_y;
- s_keyCoord[Z_TAG] = key_z;
-
- s_time = timedate;
- s_time_default = (time_xoffset == 0.0) && (time_yoffset == 0.0);
- s_timeCoord[X_TAG] = time_xoffset;
- s_timeCoord[Y_TAG] = time_yoffset;
-
- s_xsize = xsize;
- s_ysize = ysize;
-
- s_samples = samples;
- s_samplesCoord[X_TAG] = samples_1;
- s_samplesCoord[Y_TAG] = samples_2;
- s_iso_samplesCoord[X_TAG] = iso_samples_1;
- s_iso_samplesCoord[Y_TAG] = iso_samples_2;
-
- s_rotCoord[X_TAG] = surface_rot_x;
- s_rotCoord[Z_TAG] = surface_rot_z;
-
- NXZoneFree (zone, s_plotargs);
- if (cur = index (replot_line, ' ')) { /* todo What about tabs? */
- s_plotargs = NXZoneMalloc (zone, strlen (replot_line) + 1);
- strcpy (s_plotargs, cur + 1);
- } else
- s_plotargs = NULL;
-
- /* Break plotargs into separate functions */
- [self grabFunctionsFrom:s_plotargs];
- [self buildPlotargs];
-
- [self _setText: s_plotargs];
- areSettingsEdited = YES;
-
- return self;
- }
-
-
- - grabCurrentTicDefs
- {
- int count, i;
- struct ticmark *cur;
- id tic;
-
- switch (s_ticTypeCoord[X_TAG] = xticdef.type) {
- case TIC_SERIES:
- s_ticSeriesCoord[X_TAG].start = xticdef.def.series.start;
- s_ticSeriesCoord[X_TAG].incr = xticdef.def.series.incr;
- s_ticSeriesCoord[X_TAG].end = xticdef.def.series.end;
- break;
- case TIC_USER:
- count = [ticDefs[X_TAG] count] - 1;
- i = 0;
- for (cur = xticdef.def.user ; cur != NULL ; cur = cur->next) {
- if (i <= count) {
- [tic = [ticDefs[X_TAG] objectAt:i]
- setDoubleValue:cur->position];
- [tic setStringValue:cur->label];
- } else {
- [ticDefs[X_TAG] addObject:[[TicObject allocFromZone:zone]
- initFromString:cur->label
- doubleValue:cur->position]];
- }
- i++;
- }
- break;
- }
-
- switch (s_ticTypeCoord[Y_TAG] = yticdef.type) {
- case TIC_SERIES:
- s_ticSeriesCoord[Y_TAG].start = yticdef.def.series.start;
- s_ticSeriesCoord[Y_TAG].incr = yticdef.def.series.incr;
- s_ticSeriesCoord[Y_TAG].end = yticdef.def.series.end;
- break;
- case TIC_USER:
- count = [ticDefs[Y_TAG] count] - 1;
- i = 0;
- for (cur = yticdef.def.user ; cur != NULL ; cur = cur->next) {
- if (i <= count) {
- [tic = [ticDefs[Y_TAG] objectAt:i]
- setDoubleValue:cur->position];
- [tic setStringValue:cur->label];
- } else {
- [ticDefs[Y_TAG] addObject:[[TicObject allocFromZone:zone]
- initFromString:cur->label
- doubleValue:cur->position]];
- }
- i++;
- }
- break;
- }
-
- switch (s_ticTypeCoord[Z_TAG] = zticdef.type) {
- case TIC_SERIES:
- s_ticSeriesCoord[Z_TAG].start = zticdef.def.series.start;
- s_ticSeriesCoord[Z_TAG].incr = zticdef.def.series.incr;
- s_ticSeriesCoord[Z_TAG].end = zticdef.def.series.end;
- break;
- case TIC_USER:
- count = [ticDefs[Z_TAG] count] - 1;
- i = 0;
- for (cur = zticdef.def.user ; cur != NULL ; cur = cur->next) {
- if (i <= count) {
- [tic = [ticDefs[Z_TAG] objectAt:i]
- setDoubleValue:cur->position];
- [tic setStringValue:cur->label];
- } else {
- [ticDefs[Z_TAG] addObject:[[TicObject allocFromZone:zone]
- initFromString:cur->label
- doubleValue:cur->position]];
- }
- i++;
- }
- break;
- }
-
-
-
- return self;
- }
-
-
- /*
- * We use a list of FunctionObjects to store each function (a
- * "function" is a mathematical expression that gnuplot will evaluate
- * at certain points or a data file containing pairs/triples of
- * numbers on each line). We create these objects by parsing the
- * plot arguments.
- */
- - grabFunctionsFrom: (char *) aString
- {
- int count;
- FunctionObject *aFunction;
- char *src, *end;
- BOOL done;
-
- if ([functions count])
- [functions freeObjects];
-
- if (!aString)
- return nil;
-
- /* Skip any range specifications */
- if (src = rindex (aString, ']'))
- aString = src + 1;
-
- /* Count the functions */
- count = 1;
- src = aString;
- while (src = index(src, ',')) {
- count ++;
- src++;
- }
-
- /* Copy them to the strings list */
-
- src = aString;
- done = NO;
- while (!done) {
- if (end = index (src, ','))
- *end = '\0';
- else
- done = YES;
-
- aFunction = [[FunctionObject allocFromZone:zone]
- initFromString: _removeLeadingBlanks (src)];
- [functions addObject:aFunction];
-
- if (!done) {
- *end = ',';
- src = ++end;
- }
- }
-
- return self;
- }
-
-
-
-
- - setThreeD:(BOOL) aCondition
- {
-
- if (isThreeD != aCondition) {
-
- isThreeD = aCondition;
-
- if (s_parametric) {
- if (isThreeD) {
- [self _copyString:"u" to:&(s_dummy_var[X_TAG])];
- [self _copyString:"v" to:&(s_dummy_var[Y_TAG])];
- } else
- [self _copyString:"t" to:&(s_dummy_var[X_TAG])];
- }
-
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
- - (BOOL) isThreeD
- {
- return isThreeD;
- }
-
-
-
- - setParametric:(BOOL) cond
- {
- if (s_parametric != cond) {
-
- s_parametric = cond;
-
- if (cond) {
- if (isThreeD) {
- [self _copyString:"u" to:&(s_dummy_var[X_TAG])];
- [self _copyString:"v" to:&(s_dummy_var[Y_TAG])];
- } else
- [self _copyString:"t" to:&(s_dummy_var[X_TAG])];
- } else {
- [self _copyString:"x" to:&(s_dummy_var[X_TAG])];
- [self _copyString:"y" to:&(s_dummy_var[Y_TAG])];
- }
-
- [self reportSettingsChange:self];
-
- }
- return self;
- }
-
-
- - (BOOL) parametric
- {
- return s_parametric;
- }
-
-
-
- - setPolar:(BOOL) cond
- {
- if (s_polar != cond) {
- s_polar = cond;
-
- if (cond) {
- s_minCoord[X_TAG] = 0;
- s_maxCoord[X_TAG] = degrees? 360 :6.283186;
- s_isLogCoord[X_TAG] = 0;
- } else {
- s_minCoord[X_TAG] = -10.0;
- s_maxCoord[X_TAG] = 10.0;
- }
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (BOOL) isPolar
- {
- return s_polar;
- }
-
-
-
- - setBorder:(BOOL) cond
- {
- if (s_border != cond) {
- s_border = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (BOOL) border
- {
- return s_border;
- }
-
-
-
- - setSurface:(BOOL) cond
- {
- if (s_draw_surface != cond) {
- s_draw_surface = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (BOOL) surface
- {
- return s_draw_surface;
- }
-
-
-
- - setHiddenThreeD:(BOOL) cond
- {
- if (s_hidden3d != cond) {
- s_hidden3d = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (BOOL) hiddenThreeD
- {
- return s_hidden3d;
- }
-
-
-
- - setGrid:(BOOL) cond
- {
- if (s_grid != cond) {
- s_grid = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (BOOL) grid
- {
- return s_grid;
- }
-
-
-
- - setAxisX:(int) anInt
- {
- if (s_xzeroaxis != anInt) {
- s_xzeroaxis = anInt;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (int) axisX
- {
- return s_xzeroaxis;
- }
-
-
-
- - setAxisY:(int) anInt
- {
- if (s_yzeroaxis != anInt) {
- s_yzeroaxis = anInt;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (int) axisY
- {
- return s_yzeroaxis;
- }
-
-
-
- - setIsLogCoord:(int)coord isOn:(BOOL)isOn
- {
- if (s_isLogCoord[coord] != isOn) {
- s_isLogCoord[coord] = isOn;
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
-
- - (BOOL) isLogCoord:(int)coord
- {
- return s_isLogCoord[coord];
- }
-
-
-
- - setTitle:(const char *) aString
- {
- [self _copyString:aString to:&s_title];
- [self reportSettingsChange:self];
-
- return self;
- }
-
-
- - (const char *) title
- {
- return s_title;
- }
-
-
- - setLabelCoord:(int)coord to:(const char *) aString
- {
- [self _copyString:aString to:&(s_labelCoord[coord])];
- [self reportSettingsChange:self];
-
- return self;
- }
-
-
-
- - (const char *) labelCoord:(int) coord
- {
- return s_labelCoord[coord];
- }
-
-
- - setDummyVar:(int)coord to:(const char *)aString
- {
- [self _copyString:aString to:&(s_dummy_var[coord])];
- [self reportSettingsChange:self];
- return self;
- }
-
-
- - (const char *)dummyVar:(int)coord
- {
- if (!s_dummy_var[coord])
- switch (coord) {
- case X_TAG:
- return "x";
- break;
- case Y_TAG:
- return "y";
- break;
- }
-
- return s_dummy_var[coord];
- }
-
-
- - setAppendix: (const char *) aString
- {
- NXZoneFree (zone, appendix);
-
- if (aString)
- appendix = NXCopyStringBufferFromZone (aString, zone);
- else
- appendix = NULL;
-
- return self;
- }
-
-
- - setFontsize: (int) anInt;
- {
- if ((s_fontsize != anInt) && (anInt > 0)) {
- s_fontsize = anInt;
- [self reportSettingsChange:self];
- return self;
- } else
- return nil;
- }
-
-
- - (int) fontsize
- {
- return s_fontsize;
- }
-
-
-
- - setFontname: (const char *) aString
- {
- [self _copyString:aString to:&s_font];
- [self reportSettingsChange:self];
-
- return self;
- }
-
-
- - (const char *) fontname
- {
- return s_font;
- }
-
-
-
- - setFont:aFont
- {
- if (aFont) {
- [self _copyString:[aFont name] to:&s_font];
- s_fontsize = [aFont pointSize];
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
-
- - font
- {
- if (!s_font)
- return [Font newFont:DEFAULT_FONT size:s_fontsize];
- return [Font newFont:s_font size:s_fontsize];
- }
-
-
-
- - setKey:(BOOL) cond
- {
- if (s_key != cond) {
- s_key = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
-
- - (BOOL) key
- {
- return s_key;
- }
-
-
- - setKeyDefault:(BOOL) cond
- {
- if (s_key_default != cond) {
- s_key_default = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
-
- - (BOOL) keyDefault
- {
- return s_key_default;
- }
-
-
- - setKeyCoord:(int)coord to:(double)aDouble
- {
- if (s_keyCoord[coord] != aDouble) {
- s_keyCoord[coord] = aDouble;
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
- - (double) keyCoord:(int)coord
- {
- return s_keyCoord[coord];
- }
-
-
-
- - setTime:(BOOL) cond
- {
- if (s_time != cond) {
- s_time = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
-
- - (BOOL) time
- {
- return s_time;
- }
-
-
- - setTimeDefault:(BOOL) cond
- {
- if (s_time_default != cond) {
- s_time_default = cond;
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
-
- - (BOOL) timeDefault
- {
- return s_time_default;
- }
-
-
- - setTimeCoord:(int)coord to:(int)aDouble
- {
- if (s_timeCoord[coord] != aDouble) {
- s_timeCoord[coord] = aDouble;
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
- - (int) timeCoord:(int)coord
- {
- return s_timeCoord[coord];
- }
-
-
-
- - setSizeProp:(BOOL) cond
- {
- sizeProp = cond; /* Don't do anything, just record status */
- return self;
- }
-
-
- - (BOOL)sizeProp
- {
- return sizeProp;
- }
-
-
- /*
- * Size of zero means don't change... (e.g. if x=2 and y=0, we change
- * x but not y).
- */
- - setSizeX:(float) xFloat Y:(float) yFloat
- {
- if ((xFloat != s_xsize) || (yFloat != s_ysize)) {
-
- if (xFloat)
- s_xsize = xFloat;
-
- if (yFloat)
- s_ysize = yFloat;
-
- [self reportSettingsChange:self];
- }
-
- return self;
- }
-
-
- - (float) sizeX
- {
- return s_xsize;
- }
-
-
- - (float) sizeY
- {
- return s_ysize;
- }
-
-
-
- - setRotCoord:(int)coord to:(float)aFloat
- {
- if (s_rotCoord[coord] != aFloat) {
- s_rotCoord[coord] = aFloat;
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
-
- - resetRotation
- {
- s_rotCoord[X_TAG] = 60.0;
- s_rotCoord[Z_TAG] = 30.0;
- [self reportSettingsChange:self];
- return self;
- }
-
-
-
- - (float)rotCoord:(int)coord
- {
- return s_rotCoord[coord];
- }
-
-
-
- - setSamplesCoord:(int)coord to:(int)anInt
- {
- if ((anInt > 0) && (anInt != s_samplesCoord[coord])) {
- s_samplesCoord[coord] = anInt;
- if (coord == X_TAG)
- s_samples = anInt;
- } else
- return nil;
-
- [self reportSettingsChange:self];
- return self;
- }
-
-
- - (int) samples:(int)coord
- {
- return s_samplesCoord[coord];
- }
-
-
-
- - setIsoSamplesCoord:(int)coord to:(int)anInt
- {
- if ((anInt > 0) && (anInt != s_iso_samplesCoord[coord]))
- s_iso_samplesCoord[coord] = anInt;
- else
- return nil;
-
- [self reportSettingsChange:self];
- return self;
- }
-
-
- - (int) isoSamples:(int)coord
- {
- return s_iso_samplesCoord[coord];
- }
-
-
-
- - setAutoscaleCoord:(int)coord isOn:(BOOL)cond
- {
- if (s_autoscaleCoord[coord] != cond) {
- s_autoscaleCoord[coord] = cond;
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
- - (BOOL)autoscaleCoord:(int)coord
- {
- return s_autoscaleCoord[coord];
- }
-
-
- - setRangeCoord:(int)coord min:(double)min max:(double)max
- {
- if ((s_maxCoord[coord] != max) || (s_minCoord[coord] != min)) {
-
- s_maxCoord[coord] = max;
- s_minCoord[coord] = min;
-
- [self reportSettingsChange:self];
-
- }
- return self;
- }
-
- - (double)minCoord:(int)coord
- {
- return s_minCoord[coord];
- }
-
- - (double)maxCoord:(int)coord
- {
- return s_maxCoord[coord];
- }
-
-
-
- - setDegrees:(BOOL)cond;
- {
- if (degrees != cond) {
- degrees = cond;
- if (s_polar)
- if (degrees) { /* Convert radians to degrees */
- s_maxCoord[X_TAG] *= 57.2957795131;
- s_minCoord[X_TAG] *= 57.2957795131;
- } else { /* Convert degrees to radians */
- s_maxCoord[X_TAG] /= 57.2957795131;
- s_minCoord[X_TAG] /= 57.2957795131;
- }
-
- [self reportSettingsChange:self];
- }
- return self;
- }
-
-
- - (BOOL)degrees
- {
- return degrees;
- }
-
-
-
- /*
- * We plot by assembling a Gnuplot "plot" command from the list of
- * FunctionObjects.
- */
-
- - buildPlotargs
- {
- int index = [functions count];
- const char *aString;
- FunctionObject *function;
- int size = 0, counter, anInt, anInt2;
-
- /*
- * First, we calculate the total size that will be required for
- * the entire plot command, including commas, etc.
- */
- if (counter = index) {
-
- size = isThreeD? 6 : 5; /* "splot" or "plot" */
-
- while (counter--) {
- function = [functions objectAt:counter];
-
- if (aString = [function stringValue])
- size += strlen (aString);
-
- if ([function isDataFile])
- size += 2; /* 2 quotation marks */
-
- if (aString = [function title])
- size += (strlen (aString) + 9); /* " title 'xxx'" */
-
- if (aString = [function styleString])
- size += (strlen (aString) + 12); /* " with ??? xx xx" */
-
- size += 2; /* comma and space */
- }
-
- /*
- * No comma or space after the last functions = -2
- * Terminating ASCII NULL = +1
- * ----
- * Total = -1
- */
-
- size--;
- }
-
- /* Then we malloc enough space. */
-
- NXZoneFree (zone, s_plotargs);
- s_plotargs = NXZoneMalloc (zone, size);
-
-
- /* And finally, assemble the pieces. */
- if (index) {
- if (isThreeD)
- strcpy (s_plotargs, "splot ");
- else
- strcpy (s_plotargs, "plot ");
-
- counter = 0;
- while (counter != index) {
- function = [functions objectAt:counter++];
-
- if ([function isDataFile])
- sprintf (index (s_plotargs, '\0'), "'%s'",
- [function stringValue]);
- else
- s_plotargs = strcat (s_plotargs, [function stringValue]);
-
- /*
- * We determine which kind of quotation marks to use for
- * the title by checking to see if the title itself
- * contains any quotation marks and using the opposite
- * kind. Assumption: that the title does not use both
- * kinds of quotation marks, single and double.
- */
- if (aString = [function title]) {
- if (index (aString, '"'))
- sprintf (index (s_plotargs, '\0'), " title '%s'", aString);
- else
- sprintf(index(s_plotargs, '\0'), " title \"%s\"", aString);
- }
-
- if (aString = [function styleString]) {
-
- sprintf (index (s_plotargs, '\0'), " with %s", aString);
-
- /*
- * The following logical gymnastics are required
- * because the specific line and point styles may or
- * may not have been specified by the user and may or
- * may not be relevant. Plus, Gnuplot requires that
- * the line style be specified whenever the point
- * style is specified, even if the function has no
- * lines. Basically, we specify what we must (based
- * on the user's choices) and let the rest go to the
- * default.
- */
-
- switch ([function style]) {
- case FUNCTION_LINES:
- if ((anInt = [function lineStyle]) != LINE_NOSTYLE)
- sprintf (index (s_plotargs, '\0'), " %d", anInt);
- break;
- case FUNCTION_POINTS:
- if ((anInt = [function pointsStyle]) != POINTS_NOSTYLE)
- sprintf (index (s_plotargs, '\0'), " 1 %d", anInt);
- break;
- case FUNCTION_LINESPOINTS:
- anInt2 = [function pointsStyle];
- anInt = [function lineStyle];
- if ((anInt != LINE_NOSTYLE) ||
- (anInt2 != POINTS_NOSTYLE)) {
- sprintf (index (s_plotargs, '\0'), " %d", anInt);
- if (anInt2 != POINTS_NOSTYLE)
- sprintf (index (s_plotargs, '\0'), " %d", anInt2);
- }
- break;
- }
-
- }
-
- /* If there are more functions, we need a comma */
- if (counter != index)
- s_plotargs = strcat (s_plotargs, ", ");
- }
- }
-
- return self;
- }
-
-
- - (const char *) plotargs
- {
- return s_plotargs;
- }
-
-
-
- - (List *)functions
- {
- return functions;
- }
-
-
- // Shuts up the compiler about unused RCSId
- - (const char *) rcsid
- {
- return RCSId;
- }
-
-
- @end
-
-
- @implementation Status (Private)
-
-
- - (const char *) _copyString:(const char *)source to:(char **)dest
- {
- if (dest) {
- NXZoneFree (zone, *dest);
-
- if (source)
- *dest = NXCopyStringBufferFromZone (source, zone);
- else
- *dest = NULL;
- }
-
- return *dest;
- }
-
-
- /*
- * This method is nearly identical to load_file in misc.c, except
- * that instead of reading commands from a file, it reads from a
- * string, passing one line at a time to gnuplot.
- */
- - _doText:(const char *)theText
- {
- extern char input_line[]; /* Line to be read by do_line() */
- extern jmp_buf env;
- extern int do_line();
- extern int interactive;
-
- int len; /* The length of a command */
- int start, max; /* Indexes in input_line string */
- BOOL more; /* Is there more of this line? */
- BOOL stop; /* Are we done reading text? */
- int inline_num; /* Text line number... */
- int inline_index; /* ... which begins here */
-
-
- if (setjmp(env)) { /* Gnuplot bails out to here */
- /* in case of parse error, etc.*/
- if (s_epsStream) {
-
- NXCloseMemory (s_epsStream, NX_FREEBUFFER);
- s_epsStream = NULL;
-
- }
-
- return nil;
-
- } else {
-
- interactive = 0;
- max = MAX_LINE_LEN;
- stop = NO;
- inline_num = inline_index = start = 0;
-
- if (s_epsStream)
- NXCloseMemory (s_epsStream, NX_FREEBUFFER);
- s_epsStream = NXOpenMemory(NULL, 0, NX_READWRITE);
-
- EPSStream = s_epsStream;
-
- while (!stop) { /* Read every line in theText */
-
- more = YES; /* Read one command */
- while (more) {
- if (!_get_line (&(input_line[start]), max,
- &theText[inline_index])) {
- stop = YES; /* End of string */
- more = NO;
- }
-
- inline_num++;
- len = strlen (input_line);
- inline_index += (len + 1);
- if (len+1 >= max) {
- fprintf (stderr, "Input line too long\n");
- /* todo Bring up a modal panel here or something */
- }
-
- /* Continuation line */
- if (input_line[len - 1] == '\\') {
- start = len - 1;
- max -= start;
- } else
- more = NO;
- }
-
- if (strlen (input_line) > 0) {
- do_line(); /* Parse input_line */
- }
-
- }
-
- NEXTFE_reset();
-
- return self;
- }
- }
-
-
-
- - _setText: (const char *) aString
- {
- NXZoneFree (zone, text);
-
- /* Magic number 100 -- todo be more accurate */
- text = NXZoneMalloc (zone, strlen (aString) + 130);
- sprintf (text, "set term nextfe '%s' %d\nset output '/dev/null'\npi = 3.14159265359\n%s",
- s_font ? s_font : DEFAULT_FONT, s_fontsize, aString);
-
- return self;
- }
-
-
-
-
- @end
-