2000-04-27 22:03:57 +02:00
|
|
|
/**********
|
|
|
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
|
|
|
Author: 1988 Jeffrey M. Hsu
|
2005-05-29 03:05:33 +02:00
|
|
|
$Id$
|
2000-04-27 22:03:57 +02:00
|
|
|
**********/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Most of the gr_ module resides here, in particular, gr_init
|
|
|
|
|
* and gr_point, expect for the gr_ grid routines.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2000-05-13 19:28:16 +02:00
|
|
|
#include <ngspice.h>
|
2010-07-17 22:56:12 +02:00
|
|
|
#include "cpdefs.h" /* for CP_ */
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "cpextern.h"
|
2000-05-13 12:31:55 +02:00
|
|
|
#include <plot.h>
|
|
|
|
|
#include "ftedebug.h" /* for iplot */
|
|
|
|
|
#include <dvec.h> /* for struct dvec */
|
|
|
|
|
#include "ftedefs.h" /* for FTEextern.h and IPOINT{MIN,MAX} */
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "fteinput.h"
|
2000-05-13 19:28:16 +02:00
|
|
|
#include <graph.h>
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "ftedbgra.h"
|
|
|
|
|
#include "ftedev.h"
|
2008-08-27 15:39:05 +02:00
|
|
|
#include <terminal.h>
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "graf.h"
|
2005-05-29 03:05:33 +02:00
|
|
|
#include "graphdb.h"
|
|
|
|
|
#include "grid.h"
|
|
|
|
|
#include "../terminal.h"
|
|
|
|
|
#include "../breakp2.h"
|
|
|
|
|
#include "../error.h"
|
|
|
|
|
#include "../display.h"
|
|
|
|
|
#include "../runcoms.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* static declarations */
|
|
|
|
|
static void gr_start_internal(struct dvec *dv, bool copyvec);
|
|
|
|
|
static int iplot(struct plot *pl, int id);
|
|
|
|
|
static void set(struct plot *plot, struct dbcomm *db, bool unset, int mode);
|
|
|
|
|
static char * getitright(char *buf, double num);
|
|
|
|
|
|
|
|
|
|
/* for legends, set in gr_start, reset in gr_iplot and gr_init */
|
|
|
|
|
static int plotno;
|
|
|
|
|
static int curcolor = 1; /* for assigning unique colors */
|
|
|
|
|
static int curlst = 0; /* for assigning line styles */
|
|
|
|
|
|
|
|
|
|
/* invariant: currentgraph contains the current graph */
|
|
|
|
|
|
|
|
|
|
/* These are what gets plotted as points when you specify point plots */
|
|
|
|
|
static char pointchars[128];
|
2009-12-31 16:42:28 +01:00
|
|
|
#define DEFPOINTCHARS "ox+#*abcdefhgijklmnpqrstuvwyz"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Buffer for ticmarks if given a list */
|
|
|
|
|
static char ticbuf[1024];
|
|
|
|
|
static char *ticlist = ticbuf;
|
|
|
|
|
#define MAXTICS 100
|
|
|
|
|
|
2009-05-09 15:23:08 +02:00
|
|
|
#define XFACTOR 1 /* How much to expand the X scale during iplot. */
|
|
|
|
|
#define YFACTOR 0.2 /* How much to expand the Y scale during iplot. */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Start of a new graph.
|
|
|
|
|
* Fill in the data that gets displayed.
|
|
|
|
|
* Difference from old gr_init
|
|
|
|
|
* we don't try to determine the look of the screen from here
|
|
|
|
|
* leave to lower level routines
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2000-05-13 12:31:55 +02:00
|
|
|
gr_init(double *xlims, double *ylims, /* The size of the screen. */
|
|
|
|
|
char *xname, char *plotname, /* What to label things. */
|
|
|
|
|
char *hcopy, /* The raster file. */
|
|
|
|
|
int nplots, /* How many plots there will be. */
|
|
|
|
|
double xdelta, double ydelta, /* Line increments for the scale. */
|
|
|
|
|
GRIDTYPE gridtype, /* The grid type */
|
|
|
|
|
PLOTTYPE plottype, /* and the plot type. */
|
|
|
|
|
char *xlabel, char *ylabel, /* Labels for axes. */
|
|
|
|
|
int xtype, int ytype, /* The types of the data graphed. */
|
|
|
|
|
char *pname,
|
|
|
|
|
char *commandline) /* For xi_zoomdata() */
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GRAPH *graph;
|
|
|
|
|
wordlist *wl;
|
|
|
|
|
char *comb_title;
|
|
|
|
|
|
2010-11-16 20:11:32 +01:00
|
|
|
IGNORE(nplots);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (!(graph = NewGraph())) {
|
|
|
|
|
return(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The global currentgraph will always be the current graph.
|
|
|
|
|
*/
|
|
|
|
|
SetGraphContext(graph->graphid);
|
|
|
|
|
|
|
|
|
|
graph->onevalue = (xname ? FALSE : TRUE);
|
|
|
|
|
|
|
|
|
|
/* communicate filename to plot 5 driver */
|
|
|
|
|
if (hcopy) {
|
|
|
|
|
graph->devdep = hcopy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
plotno = 0;
|
|
|
|
|
|
|
|
|
|
/* note: should do only once, maybe in gr_init_once */
|
2010-07-17 22:48:20 +02:00
|
|
|
if (!cp_getvar("pointchars", CP_STRING, pointchars))
|
2000-04-27 22:03:57 +02:00
|
|
|
(void) strcpy(pointchars, DEFPOINTCHARS);
|
|
|
|
|
|
2010-07-17 22:48:20 +02:00
|
|
|
if (!cp_getvar("ticmarks", CP_NUM, (char *) &graph->ticmarks)) {
|
2010-07-20 20:41:25 +02:00
|
|
|
if (cp_getvar("ticmarks", CP_BOOL, NULL))
|
2000-04-27 22:03:57 +02:00
|
|
|
graph->ticmarks = 10;
|
|
|
|
|
else
|
|
|
|
|
graph->ticmarks = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-17 22:48:20 +02:00
|
|
|
if (cp_getvar("ticlist", CP_LIST, ticlist)) {
|
2000-04-27 22:03:57 +02:00
|
|
|
wl = (wordlist *)vareval("ticlist");
|
|
|
|
|
ticlist = (char *)wl_flatten(wl);
|
|
|
|
|
graph->ticdata = (double *) readtics(ticlist);
|
|
|
|
|
} else
|
|
|
|
|
graph->ticdata = NULL;
|
|
|
|
|
|
|
|
|
|
if (!xlims || !ylims) {
|
|
|
|
|
internalerror("gr_init: no range specified");
|
|
|
|
|
return(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* save upper and lower limits */
|
|
|
|
|
graph->data.xmin = xlims[0];
|
|
|
|
|
graph->data.xmax = xlims[1];
|
|
|
|
|
graph->data.ymin = ylims[0];
|
|
|
|
|
graph->data.ymax = ylims[1];
|
2002-01-03 23:44:21 +01:00
|
|
|
/* get title into plot window */
|
|
|
|
|
#ifdef HAS_WINDOWS
|
|
|
|
|
if (!pname)
|
|
|
|
|
pname = "(unknown)";
|
|
|
|
|
if (!plotname)
|
|
|
|
|
plotname = "(unknown)";
|
2010-10-28 21:32:34 +02:00
|
|
|
comb_title = TMALLOC(char, strlen(plotname) + strlen(pname) + 3);
|
2002-01-03 23:44:21 +01:00
|
|
|
sprintf(comb_title, "%s: %s", pname, plotname);
|
|
|
|
|
graph->plotname = comb_title;
|
|
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* note: have enum here or some better convention */
|
|
|
|
|
if (NewViewport(graph) == 1) {
|
|
|
|
|
/* note: where is the error message generated? */
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
/* note: undo tmallocs */
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Can't open viewport for graphics.\n");
|
|
|
|
|
return(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* layout decisions */
|
|
|
|
|
/* note: have to do before gr_fixgrid and after NewViewport */
|
|
|
|
|
graph->viewportxoff = graph->fontwidth * 8; /* 8 lines on left */
|
|
|
|
|
graph->viewportyoff = graph->fontheight * 4; /* 4 on bottom */
|
|
|
|
|
|
|
|
|
|
DevClear();
|
|
|
|
|
|
|
|
|
|
graph->grid.gridtype = gridtype;
|
|
|
|
|
graph->plottype = plottype;
|
|
|
|
|
graph->grid.xdatatype = xtype;
|
|
|
|
|
graph->grid.ydatatype = ytype;
|
|
|
|
|
graph->grid.xdelta = xdelta;
|
|
|
|
|
graph->grid.ydelta = ydelta;
|
|
|
|
|
graph->grid.ysized = 0;
|
|
|
|
|
graph->grid.xsized = 0;
|
|
|
|
|
|
|
|
|
|
if (!graph->onevalue) {
|
|
|
|
|
if (xlabel) {
|
|
|
|
|
graph->grid.xlabel = xlabel;
|
|
|
|
|
} else {
|
|
|
|
|
graph->grid.xlabel = xname;
|
|
|
|
|
}
|
|
|
|
|
if (ylabel) {
|
|
|
|
|
graph->grid.ylabel = ylabel;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (xlabel) {
|
|
|
|
|
graph->grid.xlabel = xlabel;
|
|
|
|
|
} else {
|
|
|
|
|
graph->grid.xlabel = "real";
|
|
|
|
|
}
|
|
|
|
|
if (ylabel) {
|
|
|
|
|
graph->grid.ylabel = ylabel;
|
|
|
|
|
} else {
|
|
|
|
|
graph->grid.ylabel = "imag";
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-01-03 23:44:21 +01:00
|
|
|
#ifndef HAS_WINDOWS
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!pname)
|
|
|
|
|
pname = "(unknown)";
|
|
|
|
|
if (!plotname)
|
|
|
|
|
plotname = "(unknown)";
|
2010-10-28 21:32:34 +02:00
|
|
|
comb_title = TMALLOC(char, strlen(plotname) + strlen(pname) + 3);
|
2000-04-27 22:03:57 +02:00
|
|
|
sprintf(comb_title, "%s: %s", pname, plotname);
|
|
|
|
|
graph->plotname = comb_title;
|
2002-01-03 23:44:21 +01:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
gr_resize_internal(graph);
|
|
|
|
|
gr_redrawgrid(graph);
|
|
|
|
|
|
|
|
|
|
/* Set up colors and line styles. */
|
|
|
|
|
if (dispdev->numlinestyles == 1)
|
|
|
|
|
curlst = 0; /* Use the same one all the time. */
|
|
|
|
|
else
|
|
|
|
|
curlst = 1;
|
|
|
|
|
/* XXX Special exception for SMITH */
|
|
|
|
|
if (dispdev->numcolors > 2 && (graph->grid.gridtype == GRID_SMITH
|
|
|
|
|
|| graph->grid.gridtype == GRID_SMITHGRID))
|
|
|
|
|
{
|
|
|
|
|
curcolor = 3;
|
|
|
|
|
} else
|
|
|
|
|
curcolor = 1;
|
|
|
|
|
|
|
|
|
|
graph->commandline = copy(commandline);
|
|
|
|
|
|
|
|
|
|
return(TRUE);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Add a point to the curve we're currently drawing.
|
|
|
|
|
* Should be in between a gr_init() and a gr_end()
|
|
|
|
|
* expect when iplotting, very bad hack
|
|
|
|
|
* Differences from old gr_point:
|
|
|
|
|
* We save points here, instead of in lower levels.
|
|
|
|
|
* Assume we are in right context
|
|
|
|
|
* Save points in data space (not screen space).
|
|
|
|
|
* We pass two points in so we can multiplex plots.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2000-05-13 12:31:55 +02:00
|
|
|
gr_point(struct dvec *dv,
|
|
|
|
|
double newx, double newy,
|
|
|
|
|
double oldx, double oldy,
|
|
|
|
|
int np)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
|
|
|
|
int oldtox, oldtoy; /* value before clipping */
|
|
|
|
|
|
|
|
|
|
char pointc[2];
|
|
|
|
|
|
|
|
|
|
int fromx, fromy, tox, toy;
|
|
|
|
|
int ymin, dummy;
|
|
|
|
|
|
|
|
|
|
DatatoScreen(currentgraph, oldx, oldy, &fromx, &fromy);
|
|
|
|
|
DatatoScreen(currentgraph, newx, newy, &tox, &toy);
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* note: we do not particularly want to clip here */
|
2000-04-27 22:03:57 +02:00
|
|
|
oldtox = tox; oldtoy = toy;
|
|
|
|
|
if (!currentgraph->grid.circular) {
|
|
|
|
|
if (clip_line(&fromx, &fromy, &tox, &toy,
|
|
|
|
|
currentgraph->viewportxoff, currentgraph->viewportyoff,
|
|
|
|
|
currentgraph->viewport.width + currentgraph->viewportxoff,
|
|
|
|
|
currentgraph->viewport.height + currentgraph->viewportyoff))
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if (clip_to_circle(&fromx, &fromy, &tox, &toy,
|
|
|
|
|
currentgraph->grid.xaxis.circular.center,
|
|
|
|
|
currentgraph->grid.yaxis.circular.center,
|
|
|
|
|
currentgraph->grid.xaxis.circular.radius))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentgraph->plottype != PLOT_POINT) {
|
|
|
|
|
SetLinestyle(dv->v_linestyle);
|
|
|
|
|
} else {
|
|
|
|
|
/* if PLOT_POINT,
|
|
|
|
|
don't want to plot an endpoint which have been clipped */
|
|
|
|
|
if (tox != oldtox || toy != oldtoy)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SetColor(dv->v_color);
|
|
|
|
|
|
|
|
|
|
switch (currentgraph->plottype) {
|
|
|
|
|
double *tics;
|
|
|
|
|
case PLOT_LIN:
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* If it's a linear plot, ignore first point since we don't
|
|
|
|
|
want to connect with oldx and oldy. */
|
2000-04-27 22:03:57 +02:00
|
|
|
if (np)
|
2010-09-08 20:03:40 +02:00
|
|
|
DevDrawLine(fromx, fromy, tox, toy);
|
2000-04-27 22:03:57 +02:00
|
|
|
if ((tics = (double *) currentgraph->ticdata)) {
|
|
|
|
|
for (; *tics < HUGE; tics++) {
|
|
|
|
|
if (*tics == (double) np) {
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText("x", (int) (tox - currentgraph->fontwidth / 2),
|
2000-04-27 22:03:57 +02:00
|
|
|
(int) (toy - currentgraph->fontheight / 2));
|
2001-04-15 21:32:25 +02:00
|
|
|
/* gr_redraw will redraw this w/o our having to save it
|
|
|
|
|
Guenther Roehrich 22-Jan-99 */
|
|
|
|
|
/* SaveText(currentgraph, "x",
|
2000-04-27 22:03:57 +02:00
|
|
|
(int) (tox - currentgraph->fontwidth / 2),
|
2001-04-15 21:32:25 +02:00
|
|
|
(int) (toy - currentgraph->fontheight / 2)); */
|
2000-04-27 22:03:57 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if ((currentgraph->ticmarks >0) && (np > 0)
|
|
|
|
|
&& (np % currentgraph->ticmarks == 0))
|
|
|
|
|
{
|
|
|
|
|
/* Draw an 'x' */
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText("x", (int) (tox - currentgraph->fontwidth / 2),
|
2000-04-27 22:03:57 +02:00
|
|
|
(int) (toy - currentgraph->fontheight / 2));
|
2001-04-15 21:32:25 +02:00
|
|
|
/* gr_redraw will redraw this w/o our having to save it
|
|
|
|
|
Guenther Roehrich 22-Jan-99 */
|
|
|
|
|
/* SaveText(currentgraph, "x",
|
2000-04-27 22:03:57 +02:00
|
|
|
(int) (tox - currentgraph->fontwidth / 2),
|
2001-04-15 21:32:25 +02:00
|
|
|
(int) (toy - currentgraph->fontheight / 2)); */
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PLOT_COMB:
|
|
|
|
|
DatatoScreen(currentgraph,
|
|
|
|
|
(double) 0, currentgraph->datawindow.ymin,
|
|
|
|
|
&dummy, &ymin);
|
2010-09-08 20:03:40 +02:00
|
|
|
DevDrawLine(tox, ymin, tox, toy);
|
2000-04-27 22:03:57 +02:00
|
|
|
break;
|
|
|
|
|
case PLOT_POINT:
|
|
|
|
|
/* Here, gi_linestyle is the character used for the point. */
|
|
|
|
|
pointc[0] = dv->v_linestyle;
|
|
|
|
|
pointc[1] = '\0';
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText(pointc, (int) (tox - currentgraph->fontwidth / 2),
|
2000-04-27 22:03:57 +02:00
|
|
|
(int) (toy - currentgraph->fontheight / 2));
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gr_start_internal(struct dvec *dv, bool copyvec)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dveclist *link;
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
/* Do something special with poles and zeros. Poles are 'x's, and
|
2000-05-13 12:31:55 +02:00
|
|
|
* zeros are 'o's. */
|
2000-04-27 22:03:57 +02:00
|
|
|
s = ft_typenames(dv->v_type);
|
|
|
|
|
if (eq(s, "pole")) {
|
|
|
|
|
dv->v_linestyle = 'x';
|
|
|
|
|
return;
|
|
|
|
|
} else if (eq(s, "zero")) {
|
|
|
|
|
dv->v_linestyle = 'o';
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find a (hopefully) new line style and color. */
|
|
|
|
|
if (currentgraph->plottype == PLOT_POINT) {
|
|
|
|
|
if (pointchars[curlst - 1])
|
|
|
|
|
curlst++;
|
|
|
|
|
else
|
|
|
|
|
curlst = 2;
|
|
|
|
|
} else if ((curlst > 0) && (++curlst == dispdev->numlinestyles))
|
|
|
|
|
curlst = 2;
|
|
|
|
|
if ((curcolor > 0) && (++curcolor == dispdev->numcolors))
|
|
|
|
|
curcolor = (((currentgraph->grid.gridtype == GRID_SMITH
|
|
|
|
|
|| currentgraph->grid.gridtype == GRID_SMITHGRID) &&
|
|
|
|
|
(dispdev->numcolors > 3)) ? 4 : 2);
|
|
|
|
|
if (currentgraph->plottype == PLOT_POINT)
|
|
|
|
|
dv->v_linestyle = pointchars[curlst - 2];
|
|
|
|
|
else
|
|
|
|
|
dv->v_linestyle = curlst;
|
|
|
|
|
dv->v_color = curcolor;
|
|
|
|
|
|
|
|
|
|
/* save the data so we can refresh */
|
2010-10-28 21:32:34 +02:00
|
|
|
link = TMALLOC(struct dveclist, 1);
|
2000-04-27 22:03:57 +02:00
|
|
|
link->next = currentgraph->plotdata;
|
|
|
|
|
|
|
|
|
|
if (copyvec) {
|
|
|
|
|
link->vector = vec_copy(dv);
|
|
|
|
|
/* vec_copy doesn't set v_color or v_linestyle */
|
|
|
|
|
link->vector->v_color = dv->v_color;
|
|
|
|
|
link->vector->v_linestyle = dv->v_linestyle;
|
|
|
|
|
link->vector->v_flags |= VF_PERMANENT;
|
|
|
|
|
} else {
|
|
|
|
|
link->vector = dv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentgraph->plotdata = link;
|
|
|
|
|
|
|
|
|
|
/* Put the legend entry on the screen. */
|
|
|
|
|
drawlegend(currentgraph, plotno, dv);
|
|
|
|
|
|
|
|
|
|
plotno++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* start one plot of a graph */
|
|
|
|
|
void
|
|
|
|
|
gr_start(struct dvec *dv)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
gr_start_internal(dv, TRUE);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* make sure the linestyles in this graph don't exceed the number of
|
2000-05-13 12:31:55 +02:00
|
|
|
linestyles available in the current display device */
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
|
|
|
|
gr_relinestyle(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dveclist *link;
|
|
|
|
|
|
|
|
|
|
for (link = graph->plotdata; link; link = link->next) {
|
|
|
|
|
if (graph->plottype == PLOT_POINT) continue;
|
|
|
|
|
if (!(link->vector->v_linestyle < dispdev->numlinestyles)) {
|
|
|
|
|
link->vector->v_linestyle %= dispdev->numlinestyles;
|
|
|
|
|
}
|
|
|
|
|
if (!(link->vector->v_color < dispdev->numcolors)) {
|
|
|
|
|
link->vector->v_color %= dispdev->numcolors;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* PN static */
|
|
|
|
|
void
|
|
|
|
|
drawlegend(GRAPH *graph, int plotno, struct dvec *dv)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int x, y, i;
|
|
|
|
|
char buf[16];
|
|
|
|
|
|
|
|
|
|
x = ((plotno % 2) ? graph->viewportxoff :
|
|
|
|
|
((graph->viewport.width) / 2));
|
|
|
|
|
y = graph->absolute.height - graph->fontheight
|
|
|
|
|
- ((plotno + 2) / 2) * (graph->fontheight);
|
|
|
|
|
i = y + graph->fontheight / 2 + 1;
|
|
|
|
|
SetColor(dv->v_color);
|
|
|
|
|
if (graph->plottype == PLOT_POINT) {
|
|
|
|
|
(void) sprintf(buf, "%c : ", dv->v_linestyle);
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText(buf, x + graph->viewport.width / 20
|
2000-04-27 22:03:57 +02:00
|
|
|
- 3 * graph->fontwidth, y);
|
|
|
|
|
} else {
|
|
|
|
|
SetLinestyle(dv->v_linestyle);
|
2010-09-08 20:03:40 +02:00
|
|
|
DevDrawLine(x, i, x + graph->viewport.width / 20, i);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
SetColor(1);
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText(dv->v_name, x + graph->viewport.width / 20
|
2000-04-27 22:03:57 +02:00
|
|
|
+ graph->fontwidth, y);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* end one plot of a graph */
|
|
|
|
|
void
|
|
|
|
|
gr_end(struct dvec *dv)
|
|
|
|
|
{
|
2010-11-16 20:11:32 +01:00
|
|
|
IGNORE(dv);
|
2010-09-08 20:06:51 +02:00
|
|
|
DevUpdate();
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print text in the bottom line. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gr_pmsg(char *text)
|
|
|
|
|
{
|
|
|
|
|
char buf[BSIZE_SP];
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
|
2010-09-08 20:06:51 +02:00
|
|
|
DevUpdate();
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2010-07-17 22:48:20 +02:00
|
|
|
if (cp_getvar("device", CP_STRING, buf)
|
2000-04-27 22:03:57 +02:00
|
|
|
&& !(strcmp("/dev/tty", buf) == 0))
|
|
|
|
|
fprintf(cp_err, "%s", text);
|
|
|
|
|
else
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* MW. grid.xlabel may be NULL */
|
|
|
|
|
if (currentgraph->grid.xlabel)
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText(text, currentgraph->viewport.width
|
2010-11-06 21:17:19 +01:00
|
|
|
- (int) (strlen(currentgraph->grid.xlabel) + 3)
|
2000-05-13 12:31:55 +02:00
|
|
|
* currentgraph->fontwidth,
|
|
|
|
|
currentgraph->absolute.height - currentgraph->fontheight);
|
|
|
|
|
else
|
|
|
|
|
fprintf(cp_err, " %s \n", text);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2010-09-08 20:06:51 +02:00
|
|
|
DevUpdate();
|
2000-04-27 22:03:57 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gr_clean(void)
|
|
|
|
|
{
|
2010-09-08 20:06:51 +02:00
|
|
|
DevUpdate();
|
2000-04-27 22:03:57 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* call this routine after viewport size changes */
|
|
|
|
|
void
|
|
|
|
|
gr_resize(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
double oldxratio, oldyratio;
|
|
|
|
|
double scalex, scaley;
|
|
|
|
|
struct _keyed *k;
|
|
|
|
|
|
|
|
|
|
oldxratio = graph->aspectratiox;
|
|
|
|
|
oldyratio = graph->aspectratioy;
|
|
|
|
|
|
|
|
|
|
graph->grid.xsized = 0;
|
|
|
|
|
graph->grid.ysized = 0;
|
|
|
|
|
|
|
|
|
|
gr_resize_internal(graph);
|
|
|
|
|
|
|
|
|
|
/* scale keyed text */
|
|
|
|
|
scalex = oldxratio / graph->aspectratiox;
|
|
|
|
|
scaley = oldyratio / graph->aspectratioy;
|
|
|
|
|
for (k = graph->keyed; k; k = k->next) {
|
|
|
|
|
k->x = (k->x - graph->viewportxoff) * scalex + graph->viewportxoff;
|
|
|
|
|
k->y = (k->y - graph->viewportyoff) * scaley + graph->viewportyoff;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* X also generates an expose after a resize.
|
|
|
|
|
|
|
|
|
|
This is handled in X10 by not redrawing on resizes and waiting
|
|
|
|
|
for the expose event to redraw. In X11, the expose routine
|
|
|
|
|
tries to be clever and only redraws the region specified in an
|
|
|
|
|
expose event, which does not cover the entire region of the
|
|
|
|
|
plot if the resize was from a small window to a larger window.
|
|
|
|
|
So in order to keep the clever X11 expose event handling, we
|
|
|
|
|
have the X11 resize routine pull out expose events for that
|
|
|
|
|
window, and we redraw on resize also. */
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef X_DISPLAY_MISSING
|
|
|
|
|
gr_redraw(graph);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* PN static */
|
|
|
|
|
void
|
|
|
|
|
gr_resize_internal(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (!graph->grid.xsized)
|
|
|
|
|
graph->viewport.width = graph->absolute.width -
|
|
|
|
|
1.4 * graph->viewportxoff;
|
|
|
|
|
if (!graph->grid.ysized)
|
|
|
|
|
graph->viewport.height = graph->absolute.height -
|
|
|
|
|
2 * graph->viewportyoff;
|
|
|
|
|
|
|
|
|
|
gr_fixgrid(graph, graph->grid.xdelta, graph->grid.ydelta,
|
|
|
|
|
graph->grid.xdatatype, graph->grid.ydatatype);
|
|
|
|
|
|
|
|
|
|
/* cache width and height info to make DatatoScreen go fast */
|
|
|
|
|
/* note: XXX see if this is actually used anywhere */
|
|
|
|
|
graph->datawindow.width = graph->datawindow.xmax -
|
|
|
|
|
graph->datawindow.xmin;
|
|
|
|
|
graph->datawindow.height = graph->datawindow.ymax -
|
|
|
|
|
graph->datawindow.ymin;
|
|
|
|
|
|
|
|
|
|
/* cache (datawindow size) / (viewport size) */
|
|
|
|
|
graph->aspectratiox = graph->datawindow.width / graph->viewport.width;
|
|
|
|
|
graph->aspectratioy = graph->datawindow.height / graph->viewport.height;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* redraw everything in struct graph */
|
|
|
|
|
void
|
|
|
|
|
gr_redraw(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dveclist *link;
|
|
|
|
|
|
|
|
|
|
/* establish current graph so default graphic calls will work right */
|
|
|
|
|
PushGraphContext(graph);
|
|
|
|
|
|
|
|
|
|
DevClear();
|
|
|
|
|
|
|
|
|
|
/* redraw grid */
|
|
|
|
|
gr_redrawgrid(graph);
|
|
|
|
|
|
|
|
|
|
for (link=graph->plotdata, plotno = 0; link;
|
|
|
|
|
link = link->next, plotno++) {
|
|
|
|
|
/* redraw legend */
|
|
|
|
|
drawlegend(graph, plotno, link->vector);
|
|
|
|
|
|
|
|
|
|
/* replot data
|
|
|
|
|
if onevalue, pass it a NULL scale
|
|
|
|
|
otherwise, if vec has its own scale, pass that
|
|
|
|
|
else pass vec's plot's scale
|
|
|
|
|
*/
|
|
|
|
|
ft_graf(link->vector,
|
|
|
|
|
graph->onevalue ? (struct dvec *) NULL :
|
|
|
|
|
(link->vector->v_scale ?
|
|
|
|
|
link->vector->v_scale :
|
|
|
|
|
link->vector->v_plot->pl_scale),
|
|
|
|
|
TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gr_restoretext(graph);
|
|
|
|
|
|
|
|
|
|
PopGraphContext();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gr_restoretext(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct _keyed *k;
|
|
|
|
|
|
|
|
|
|
/* restore text */
|
|
|
|
|
for (k=graph->keyed; k; k = k->next) {
|
|
|
|
|
SetColor(k->colorindex);
|
2010-09-08 20:01:42 +02:00
|
|
|
DevDrawText(k->text, k->x, k->y);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* Do some incremental plotting. There are 3 cases:
|
|
|
|
|
*
|
|
|
|
|
* First, if length < IPOINTMIN, don't do anything.
|
|
|
|
|
*
|
|
|
|
|
* Second, if length = IPOINTMIN, plot what we have so far.
|
|
|
|
|
*
|
|
|
|
|
* Third, if length > IPOINTMIN, plot the last points and resize if
|
|
|
|
|
* needed.
|
|
|
|
|
*
|
2000-04-27 22:03:57 +02:00
|
|
|
* Note we don't check for pole / zero because they are of length 1.
|
2000-05-13 12:31:55 +02:00
|
|
|
*
|
|
|
|
|
* FIXME: there is a problem with multiple iplots that use the same
|
|
|
|
|
* vector, namely, that vector has the same color throughout. This is
|
|
|
|
|
* another reason why we need to pull color and linestyle out of dvec
|
|
|
|
|
* XXX Or maybe even something more drastic ?? */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
iplot(struct plot *pl, int id)
|
|
|
|
|
{
|
|
|
|
|
int len = pl->pl_scale->v_length;
|
|
|
|
|
struct dvec *v, *xs = pl->pl_scale;
|
|
|
|
|
double *lims, dy;
|
|
|
|
|
double start, stop, step;
|
|
|
|
|
register int j;
|
|
|
|
|
bool changed = FALSE;
|
|
|
|
|
int yt;
|
|
|
|
|
char *yl = NULL;
|
|
|
|
|
double xlims[2], ylims[2];
|
|
|
|
|
static REQUEST reqst = { checkup_option, 0 };
|
|
|
|
|
int inited = 0;
|
|
|
|
|
char commandline[513];
|
|
|
|
|
|
|
|
|
|
for (j = 0, v = pl->pl_dvecs; v; v = v->v_next)
|
|
|
|
|
if (v->v_flags & VF_PLOT)
|
|
|
|
|
j++;
|
|
|
|
|
if (!j)
|
|
|
|
|
return(0);
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "Entering iplot, len = %d\n", len);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (len < IPOINTMIN) {
|
|
|
|
|
/* Nothing yet */
|
|
|
|
|
return(0);
|
2000-05-13 12:31:55 +02:00
|
|
|
} else if (len == IPOINTMIN || !id) {
|
2009-05-09 15:23:08 +02:00
|
|
|
resumption = FALSE;
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Draw the grid for the first time, and plot everything. */
|
|
|
|
|
lims = ft_minmax(xs, TRUE);
|
|
|
|
|
xlims[0] = lims[0];
|
|
|
|
|
xlims[1] = lims[1];
|
|
|
|
|
ylims[0] = HUGE;
|
|
|
|
|
ylims[1] = - ylims[0];
|
|
|
|
|
for (v = pl->pl_dvecs; v; v = v->v_next)
|
|
|
|
|
if (v->v_flags & VF_PLOT) {
|
|
|
|
|
lims = ft_minmax(v, TRUE);
|
|
|
|
|
if (lims[0] < ylims[0])
|
|
|
|
|
ylims[0] = lims[0];
|
|
|
|
|
if (lims[1] > ylims[1])
|
|
|
|
|
ylims[1] = lims[1];
|
|
|
|
|
if (!yl)
|
|
|
|
|
yl = v->v_name;
|
|
|
|
|
}
|
|
|
|
|
if (ft_grdb)
|
|
|
|
|
fprintf(cp_err,
|
2010-09-19 18:30:39 +02:00
|
|
|
"iplot: after 5, xlims = %G, %G, ylims = %G, %G\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[0],
|
|
|
|
|
xlims[1],
|
|
|
|
|
ylims[0],
|
|
|
|
|
ylims[1]);
|
|
|
|
|
for (yt = pl->pl_dvecs->v_type, v = pl->pl_dvecs->v_next; v;
|
|
|
|
|
v = v->v_next)
|
|
|
|
|
if ((v->v_flags & VF_PLOT) && (v->v_type != yt)) {
|
|
|
|
|
yt = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2000-05-13 12:31:55 +02:00
|
|
|
|
|
|
|
|
/* note: have command options for iplot to specify xdelta,
|
|
|
|
|
etc. So don't need static variables hack. Assume default
|
|
|
|
|
values for now. */
|
2009-05-09 15:23:08 +02:00
|
|
|
sprintf(commandline, "plot %s", yl);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
(void) gr_init(xlims, ylims, xs->v_name,
|
|
|
|
|
pl->pl_title, (char *) NULL, j, 0.0, 0.0,
|
|
|
|
|
GRID_LIN, PLOT_LIN, xs->v_name, yl, xs->v_type, yt,
|
|
|
|
|
plot_cur->pl_typename, commandline);
|
|
|
|
|
for (v = pl->pl_dvecs; v; v = v->v_next)
|
|
|
|
|
if (v->v_flags & VF_PLOT) {
|
|
|
|
|
gr_start_internal(v, FALSE);
|
|
|
|
|
ft_graf(v, xs, TRUE);
|
|
|
|
|
}
|
|
|
|
|
inited = 1;
|
|
|
|
|
} else {
|
2009-05-09 15:23:08 +02:00
|
|
|
/* plot the last points and resize if needed */
|
|
|
|
|
Input(&reqst, 0);
|
2000-04-27 22:03:57 +02:00
|
|
|
/* First see if we have to make the screen bigger */
|
|
|
|
|
dy = (isreal(xs) ? xs->v_realdata[len - 1] :
|
|
|
|
|
realpart(&xs->v_compdata[len - 1]));
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "x = %G\n", dy);
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!if_tranparams(ft_curckt, &start, &stop, &step) ||
|
|
|
|
|
!ciprefix("tran", pl->pl_typename)) {
|
|
|
|
|
stop = HUGE;
|
|
|
|
|
start = - stop;
|
|
|
|
|
}
|
2009-05-09 15:23:08 +02:00
|
|
|
/* checking for x lo */
|
2000-04-27 22:03:57 +02:00
|
|
|
while (dy < currentgraph->data.xmin) {
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "resize: xlo %G -> %G\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.xmin,
|
|
|
|
|
currentgraph->data.xmin -
|
|
|
|
|
(currentgraph->data.xmax -
|
|
|
|
|
currentgraph->data.xmin)
|
|
|
|
|
* XFACTOR);
|
2009-05-09 15:23:08 +02:00
|
|
|
/* set the new x lo value */
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.xmin -=
|
|
|
|
|
(currentgraph->data.xmax -
|
|
|
|
|
currentgraph->data.xmin)
|
|
|
|
|
* XFACTOR;
|
|
|
|
|
if (currentgraph->data.xmin < start) {
|
|
|
|
|
currentgraph->data.xmin = start;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (currentgraph->data.xmax <
|
|
|
|
|
currentgraph->data.xmin)
|
|
|
|
|
currentgraph->data.xmax =
|
|
|
|
|
currentgraph->data.xmin;
|
2009-05-09 15:23:08 +02:00
|
|
|
/* checking for x hi */
|
2000-04-27 22:03:57 +02:00
|
|
|
while (dy > currentgraph->data.xmax) {
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "resize: xhi %G -> %G\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.xmax,
|
|
|
|
|
currentgraph->data.xmax +
|
|
|
|
|
(currentgraph->data.xmax -
|
|
|
|
|
currentgraph->data.xmin) * XFACTOR);
|
2009-05-09 15:23:08 +02:00
|
|
|
/* set the new x hi value */
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.xmax +=
|
|
|
|
|
(currentgraph->data.xmax -
|
|
|
|
|
currentgraph->data.xmin) *
|
|
|
|
|
XFACTOR;
|
|
|
|
|
if (currentgraph->data.xmax > stop) {
|
|
|
|
|
currentgraph->data.xmax = stop;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-05-09 15:23:08 +02:00
|
|
|
/* checking for all y values */
|
2000-04-27 22:03:57 +02:00
|
|
|
for (v = pl->pl_dvecs; v; v = v->v_next) {
|
|
|
|
|
if (!(v->v_flags & VF_PLOT))
|
|
|
|
|
continue;
|
|
|
|
|
dy = (isreal(v) ? v->v_realdata[len - 1] :
|
|
|
|
|
realpart(&v->v_compdata[len - 1]));
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "y = %G\n", dy);
|
2009-05-09 15:23:08 +02:00
|
|
|
/* checking for y lo */
|
2000-04-27 22:03:57 +02:00
|
|
|
while (dy < currentgraph->data.ymin) {
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "resize: ylo %G -> %G\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.ymin,
|
|
|
|
|
currentgraph->data.ymin -
|
|
|
|
|
(currentgraph->data.ymax -
|
|
|
|
|
currentgraph->data.ymin) * YFACTOR);
|
2009-05-09 15:23:08 +02:00
|
|
|
/* set the new y lo value */
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.ymin -=
|
|
|
|
|
(currentgraph->data.ymax -
|
2009-05-09 15:23:08 +02:00
|
|
|
currentgraph->data.ymin) * YFACTOR;
|
|
|
|
|
/* currentgraph->data.ymin +=
|
|
|
|
|
(dy - currentgraph->data.ymin) * YFACTOR;*/
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
if (currentgraph->data.ymax <
|
|
|
|
|
currentgraph->data.ymin)
|
|
|
|
|
currentgraph->data.ymax =
|
|
|
|
|
currentgraph->data.ymin;
|
2009-05-09 15:23:08 +02:00
|
|
|
/* checking for y hi */
|
2000-04-27 22:03:57 +02:00
|
|
|
while (dy > currentgraph->data.ymax) {
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
if (ft_grdb)
|
2010-09-19 18:30:39 +02:00
|
|
|
fprintf(cp_err, "resize: yhi %G -> %G\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.ymax,
|
|
|
|
|
currentgraph->data.ymax +
|
|
|
|
|
(currentgraph->data.ymax -
|
|
|
|
|
currentgraph->data.ymin) * YFACTOR);
|
2009-05-09 15:23:08 +02:00
|
|
|
/* set the new y hi value */
|
2000-04-27 22:03:57 +02:00
|
|
|
currentgraph->data.ymax +=
|
|
|
|
|
(currentgraph->data.ymax -
|
2009-05-09 15:23:08 +02:00
|
|
|
currentgraph->data.ymin) * YFACTOR;
|
|
|
|
|
/* currentgraph->data.ymax +=
|
|
|
|
|
(dy - currentgraph->data.ymax) * YFACTOR;*/
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (changed) {
|
|
|
|
|
/* Redraw everything. */
|
|
|
|
|
gr_pmsg("Resizing screen");
|
|
|
|
|
gr_resize(currentgraph);
|
2009-05-09 15:23:08 +02:00
|
|
|
#ifndef X_DISPLAY_MISSING
|
2000-04-27 22:03:57 +02:00
|
|
|
gr_redraw(currentgraph);
|
2009-05-09 15:23:08 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
} else {
|
2000-05-13 12:31:55 +02:00
|
|
|
/* Just connect the last two points. This won't be done
|
|
|
|
|
* with curve interpolation, so it might look funny. */
|
2000-04-27 22:03:57 +02:00
|
|
|
for (v = pl->pl_dvecs; v; v = v->v_next)
|
|
|
|
|
if (v->v_flags & VF_PLOT) {
|
|
|
|
|
gr_point(v,
|
|
|
|
|
(isreal(xs) ? xs->v_realdata[len - 1] :
|
|
|
|
|
realpart(&xs->v_compdata[len - 1])),
|
|
|
|
|
(isreal(v) ? v->v_realdata[len - 1] :
|
|
|
|
|
realpart(&v->v_compdata[len - 1])),
|
|
|
|
|
(isreal(xs) ? xs->v_realdata[len - 2] :
|
|
|
|
|
realpart(&xs->v_compdata[len - 2])),
|
|
|
|
|
(isreal(v) ? v->v_realdata[len - 2] :
|
|
|
|
|
realpart(&v->v_compdata[len - 2])),
|
|
|
|
|
len - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-08 20:06:51 +02:00
|
|
|
DevUpdate();
|
2000-04-27 22:03:57 +02:00
|
|
|
return(inited);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set(struct plot *plot, struct dbcomm *db, bool unset, int mode)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dvec *v;
|
|
|
|
|
struct dbcomm *dc;
|
|
|
|
|
|
|
|
|
|
if (db->db_type == DB_IPLOTALL || db->db_type == DB_TRACEALL) {
|
|
|
|
|
for (v = plot->pl_dvecs; v; v = v->v_next) {
|
|
|
|
|
if (unset)
|
|
|
|
|
v->v_flags &= ~mode;
|
|
|
|
|
else
|
|
|
|
|
v->v_flags |= mode;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (dc = db; dc; dc = dc->db_also) {
|
|
|
|
|
v = vec_fromplot(dc->db_nodename1, plot);
|
|
|
|
|
if (!v || v->v_plot != plot) {
|
|
|
|
|
if (!eq(dc->db_nodename1, "0") && !unset) {
|
|
|
|
|
fprintf(cp_err, "Warning: node %s non-existent in %s.\n",
|
|
|
|
|
dc->db_nodename1, plot->pl_name);
|
|
|
|
|
/* note: XXX remove it from dbs, so won't get further errors */
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (unset)
|
|
|
|
|
v->v_flags &= ~mode;
|
|
|
|
|
else
|
|
|
|
|
v->v_flags |= mode;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
getitright(char *buf, double num)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
int k;
|
|
|
|
|
|
|
|
|
|
sprintf(buf, " % .5g", num);
|
|
|
|
|
p =strchr(buf, '.');
|
|
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
|
return p - 4;
|
|
|
|
|
} else {
|
2010-11-06 17:54:11 +01:00
|
|
|
k = (int) strlen(buf);
|
2000-04-27 22:03:57 +02:00
|
|
|
if (k > 8)
|
|
|
|
|
return buf + 4;
|
|
|
|
|
else /* k >= 4 */
|
|
|
|
|
return buf + k - 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int hit, hit2;
|
|
|
|
|
|
|
|
|
|
void reset_trace(void)
|
|
|
|
|
{
|
|
|
|
|
hit = -1;
|
|
|
|
|
hit2 = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gr_iplot(struct plot *plot)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dbcomm *db;
|
|
|
|
|
int dontpop; /* So we don't pop w/o push. */
|
|
|
|
|
char buf[30];
|
|
|
|
|
|
|
|
|
|
hit = 0;
|
|
|
|
|
for (db = dbs; db; db = db->db_next) {
|
|
|
|
|
if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) {
|
|
|
|
|
|
|
|
|
|
if (db->db_graphid) PushGraphContext(FindGraph(db->db_graphid));
|
|
|
|
|
|
|
|
|
|
set(plot, db, FALSE, VF_PLOT);
|
|
|
|
|
|
|
|
|
|
dontpop = 0;
|
|
|
|
|
if (iplot(plot, db->db_graphid)) {
|
|
|
|
|
/* graph just assigned */
|
|
|
|
|
db->db_graphid = currentgraph->graphid;
|
|
|
|
|
dontpop = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set(plot, db, TRUE, VF_PLOT);
|
|
|
|
|
|
|
|
|
|
if (!dontpop && db->db_graphid) PopGraphContext();
|
|
|
|
|
|
|
|
|
|
} else if (db->db_type == DB_TRACENODE || db->db_type == DB_TRACEALL) {
|
|
|
|
|
|
|
|
|
|
struct dvec *v, *u;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
set(plot, db, FALSE, VF_PRINT);
|
|
|
|
|
|
|
|
|
|
len = plot->pl_scale->v_length;
|
|
|
|
|
|
|
|
|
|
dontpop = 0;
|
|
|
|
|
for (v = plot->pl_dvecs; v; v = v->v_next) {
|
|
|
|
|
if (v->v_flags & VF_PRINT) {
|
|
|
|
|
u = plot->pl_scale;
|
|
|
|
|
if (len <= 1 || hit <= 0 || hit2 < 0) {
|
|
|
|
|
if (len <= 1 || hit2 < 0)
|
|
|
|
|
term_clear( );
|
|
|
|
|
else
|
|
|
|
|
term_home( );
|
|
|
|
|
hit = 1;
|
|
|
|
|
hit2 = 1;
|
|
|
|
|
printf(
|
|
|
|
|
"\tExecution trace (remove with the \"delete\" command)");
|
|
|
|
|
term_cleol( );
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
if (u) {
|
|
|
|
|
printf("%12s:", u->v_name);
|
|
|
|
|
if (isreal(u)) {
|
|
|
|
|
printf("%s",
|
|
|
|
|
getitright(buf, u->v_realdata[len - 1]));
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* MW. Complex data here, realdata is NULL
|
|
|
|
|
(why someone use realdata here again) */
|
|
|
|
|
printf("%s",
|
|
|
|
|
getitright(buf, u->v_compdata[len - 1].cx_real));
|
|
|
|
|
printf(", %s",
|
|
|
|
|
getitright(buf, u->v_compdata[len - 1].cx_imag));
|
|
|
|
|
}
|
|
|
|
|
term_cleol( );
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (v == u)
|
|
|
|
|
continue;
|
|
|
|
|
printf("%12s:", v->v_name);
|
|
|
|
|
if (isreal(v)) {
|
|
|
|
|
printf("%s", getitright(buf, v->v_realdata[len - 1]));
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* MW. Complex data again */
|
|
|
|
|
printf("%s", getitright(buf, v->v_compdata[len - 1].cx_real));
|
|
|
|
|
printf(", %s", getitright(buf, v->v_compdata[len - 1].cx_imag));
|
|
|
|
|
}
|
|
|
|
|
term_cleol( );
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set(plot, db, TRUE, VF_PRINT);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-13 12:31:55 +02:00
|
|
|
/* This gets called after iplotting is done. We clear out the
|
|
|
|
|
* db_graphid fields. Copy the dvecs, which we referenced by
|
|
|
|
|
* reference, so DestroyGraph gets to free its own copy.
|
|
|
|
|
*
|
|
|
|
|
* Note: This is a clear case for separating the linestyle and color
|
|
|
|
|
* fields from dvec. */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gr_end_iplot(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct dbcomm *db, *prev, *next;
|
|
|
|
|
GRAPH *graph;
|
|
|
|
|
struct dveclist *link;
|
|
|
|
|
struct dvec *dv;
|
|
|
|
|
|
|
|
|
|
prev = NULL;
|
|
|
|
|
for (db = dbs; db; prev = db, db = next) {
|
|
|
|
|
next = db->db_next;
|
|
|
|
|
if (db->db_type == DB_DEADIPLOT) {
|
|
|
|
|
if (db->db_graphid) {
|
|
|
|
|
DestroyGraph(db->db_graphid);
|
|
|
|
|
if (prev)
|
|
|
|
|
prev->db_next = next;
|
|
|
|
|
else
|
|
|
|
|
dbs = next;
|
|
|
|
|
dbfree(db);
|
|
|
|
|
}
|
|
|
|
|
} else if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) {
|
|
|
|
|
if (db->db_graphid) {
|
|
|
|
|
|
|
|
|
|
/* get private copy of dvecs */
|
|
|
|
|
graph = FindGraph(db->db_graphid);
|
|
|
|
|
|
|
|
|
|
link = graph->plotdata;
|
|
|
|
|
|
|
|
|
|
while (link) {
|
|
|
|
|
dv = link->vector;
|
|
|
|
|
link->vector = vec_copy(dv);
|
|
|
|
|
/* vec_copy doesn't set v_color or v_linestyle */
|
|
|
|
|
link->vector->v_color = dv->v_color;
|
|
|
|
|
link->vector->v_linestyle = dv->v_linestyle;
|
|
|
|
|
link->vector->v_flags |= VF_PERMANENT;
|
|
|
|
|
link = link->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db->db_graphid = 0;
|
|
|
|
|
} else {
|
|
|
|
|
/* warn that this wasn't plotted */
|
|
|
|
|
fprintf(cp_err, "Warning: iplot %d was not executed.\n",
|
|
|
|
|
db->db_number);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double *
|
|
|
|
|
readtics(char *string)
|
|
|
|
|
{
|
|
|
|
|
int i, k;
|
|
|
|
|
char *words, *worde;
|
|
|
|
|
double *tics, *ticsk;
|
|
|
|
|
|
2010-10-28 21:32:34 +02:00
|
|
|
tics = TMALLOC(double, MAXTICS);
|
2000-04-27 22:03:57 +02:00
|
|
|
ticsk = tics;
|
|
|
|
|
words = string;
|
|
|
|
|
|
|
|
|
|
for (i = k = 0; *words && k < MAXTICS; words = worde) {
|
|
|
|
|
|
|
|
|
|
while (isspace(*words))
|
|
|
|
|
words++;
|
|
|
|
|
|
|
|
|
|
worde = words;
|
|
|
|
|
while (isalpha(*worde) || isdigit(*worde))
|
|
|
|
|
worde++;
|
|
|
|
|
|
|
|
|
|
if (*worde)
|
|
|
|
|
*worde++ = '\0';
|
|
|
|
|
|
|
|
|
|
sscanf(words, "%lf", ticsk++);
|
|
|
|
|
|
|
|
|
|
k++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
*ticsk = HUGE;
|
|
|
|
|
return(tics);
|
|
|
|
|
}
|