horizontal cursors in graphs

This commit is contained in:
stefan schippers 2025-01-07 04:20:32 +01:00
parent 9fda7e2f96
commit a3e7610d83
5 changed files with 241 additions and 48 deletions

View File

@ -66,9 +66,6 @@ p{padding: 15px 30px 10px;}
<kbd>Waves-&gt;Op | Ac | Dc | Tran | Tran | Noise | Sp </kbd>. This command loads the user selected
.raw file produced by a ngspice/Xyce simulation.
</p>
<p class="important">
Ensure the <kbd>circuit.raw</kbd> is saved in binary format (no <kbd>set filetype=ascii</kbd> in your testbench)
</p>
<p>
The raw file is usually located in the simulation/netlisting directory
<kbd>Simulation -&gt;set netlist dir</kbd>.<br>
@ -80,6 +77,17 @@ p{padding: 15px 30px 10px;}
Then, select a node or a net label, press 'Alt-G', the net will be added to the graph. Here after a
list of commands you can perform in a graph to modify the viewport. These commands are active when
the mouse is Inside the graph (you will notice the mouse pointer changing from an arrow to a <kbd>+</kbd>).
</p>
<p class="important">
if <kbd>set graph_use_ctrl_key 1</kbd> is set in the <kbd>xschemrc</kbd> file all bind keys shown
below will need the <kbd>Control</kbd> key pressed to operate on the graphs. This setting can be used
to make it more explicit when the user wants to operate on graphs. Without the <kbd>Control</kbd>
key pressed the usual functions on schematic are performed instead of graph functions.<br>
Example: the key <kbd>a</kbd> will create a symbol if used in a schematic while it shows a cursor
if done when the mouse pointer is inside a graph. With the <kbd>set graph_use_ctrl_key 1</kbd> option
you will need to press <kbd>Control-a</kbd> with the mouse pointer inside a graph to show a cursor.
</p>
<p>
if the mouse is outside the graph the usual Xschem functions will be available to operate on schematics:
</p>
<ul>
@ -87,13 +95,14 @@ p{padding: 15px 30px 10px;}
<li>Pressing <kbd>f</kbd> with the mouse on the left of the Y axis will do a full Y-axis zoom.</li>
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is inside a graph will
move the waveforms to the left/right or zoom in/zoom out respectively.</li>
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is on the left of the Y-axis
will move the waveforms or zoom in/zoom out in the Y direction respectively.</li>
<li>Pressing <kbd>Left/Right</kbd> arrow keys while the mouse is on the left of the Y-axis
will zoom in/zoom out in the Y direction.</li>
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is in the center of the graph
will move the waves left or right following the pointer X movement.</li>
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is on the left of the Y-axis
will move the waves high or low following the pointer Y movement.</li>
<li> Doing the above with the <kbd>Shift</kbd> key pressed will zoom in/out instead of moving.</li>
<li> pressing <kbd>A</kbd> and/or <kbd>B</kbd> will show a horizontal cursor.
The difference between the <kbd>A</kbd> and the <kbd>B</kbd> cursor is shown.</li>
<li> pressing <kbd>a</kbd> and/or <kbd>b</kbd> will show a vertical cursor.
The sweep variable difference between the <kbd>a</kbd> and the <kbd>b</kbd> cursor is shown and
the values of all signals at the X position of the <kbd>a</kbd> cursor is shown. </li>

View File

@ -46,7 +46,7 @@ static int waves_selected(int event, KeySym key, int state, int button)
else if(event == ButtonPress && button == Button2) skip = 1;
else if(event == ButtonPress && button == Button1 && (state & ShiftMask) ) skip = 1;
else if(event == ButtonRelease && button == Button2) skip = 1;
else if(event == KeyPress && (state & ShiftMask)) skip = 1;
/* else if(event == KeyPress && (state & ShiftMask)) skip = 1; */
else if(!skip) for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
xRect *r;
r = &xctx->rect[GRIDLAYER][i];
@ -68,6 +68,7 @@ static int waves_selected(int event, KeySym key, int state, int button)
is_inside = 1;
if(draw_xhair) draw_crosshair(1);
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
break;
}
}
if(!is_inside) {
@ -366,7 +367,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
int save_mouse_at_end = 0, clear_graphpan_at_end = 0;
int track_dset = -2; /* used to find dataset of closest wave to mouse if 't' is pressed */
xRect *r = NULL;
int access_cond = !graph_use_ctrl_key || ( (state & ControlMask) && !(state & ShiftMask) );
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
if(event != -3 && !xctx->raw) return 0;
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
@ -392,9 +393,27 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
dbg(1, "mouse inside: %d\n", i);
setup_graph_data(i, 0, gr);
/* move hcursor1 */
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 512 )) {
double c;
c = G_Y(xctx->mousey);
if(gr->logy) c = pow(10, c);
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
}
/* move hcursor2 */
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 1024 )) {
double c;
c = G_Y(xctx->mousey);
if(gr->logy) c = pow(10, c);
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
}
/* move cursor1 */
/* set cursor position from master graph x-axis */
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
double c;
c = G_X(xctx->mousex);
@ -448,7 +467,27 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
zoom_m = (xctx->mousex - gr->x1) / gr->w;
if(event == ButtonPress && button == Button1) {
/* dragging cursors when mouse is very close */
if(xctx->graph_flags & 2) {
if(xctx->graph_flags & 128) { /* hcursor1 */
double cursor;
cursor = gr->hcursor1_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
xctx->graph_flags |= 512; /* Start move hcursor1 */
}
}
if(xctx->graph_flags & 256) { /* hcursor2 */
double cursor;
cursor = gr->hcursor2_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
xctx->graph_flags |= 1024; /* Start move hcursor2 */
}
}
if(xctx->graph_flags & 2) { /* cursor1 */
double cursor1;
if(r->flags & 4) { /* private_cursor */
const char *s = get_tok_value(r->prop_ptr, "cursor1_x", 0);
@ -467,7 +506,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xctx->graph_flags |= 16; /* Start move cursor1 */
}
}
if(xctx->graph_flags & 4) {
if(xctx->graph_flags & 4) { /* cursor2 */
double cursor2;
if(r->flags & 4) { /* private_cursor */
const char *s = get_tok_value(r->prop_ptr, "cursor2_x", 0);
@ -518,7 +557,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
redraw_all_at_end = 1;
}
/* Numerically set cursor position */
if(xctx->graph_flags & 4) {
double cursor2;
if(r->flags & 4) { /* private_cursor */
@ -678,7 +717,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* check if user clicked on a wave label -> draw wave in bold */
if(event == ButtonPress && button == Button3 &&
edit_wave_attributes(2, i, gr)) {
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in graph box */
draw_graph(i, 1 + 8 + (xctx->graph_flags & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
return 0;
}
/* save mouse position when doing pan operations */
@ -800,7 +839,12 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
if( event == KeyPress || event == ButtonPress || event == MotionNotify ) {
/* move cursor1 */
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16)) {
need_redraw = 1;
}
/* move hcursor1 or hcursor2 */
else if(event == MotionNotify && i == xctx->graph_master &&
(state & Button1Mask) && (xctx->graph_flags & (512 | 1024) )) {
need_redraw = 1;
}
/* move cursor2 */
@ -811,7 +855,8 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
else need_redraw = 1;
}
else /* drag waves with mouse */
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom) {
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
!(xctx->graph_flags & (16 | 32 | 512 | 1024))) {
double delta;
if(xctx->graph_left) {
if(i == xctx->graph_master) {
@ -856,6 +901,36 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
else if(event == ButtonPress && button == Button3) {
/* Numerically set hcursor position */
if(xctx->graph_flags & 128) {
double cursor;
cursor = gr->hcursor1_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor), NULL);
cursor = atof_spice(tclresult());
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(cursor)));
}
need_redraw = 1;
}
/* Numerically set hcursor position */
if(xctx->graph_flags & 256) {
double cursor;
cursor = gr->hcursor2_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor), NULL);
cursor = atof_spice(tclresult());
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(cursor)));
}
need_redraw = 1;
}
}
else if((button == Button5 && !(state & ShiftMask))) {
double delta;
if(xctx->graph_left) {
@ -890,6 +965,30 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
/* y hcursor1 toggle */
else if(key == 'A' && access_cond && i == xctx->graph_master) {
xctx->graph_flags ^= 128;
need_redraw = 1;
if(xctx->graph_flags & 128) {
double c = G_Y(xctx->mousey);
if(gr->logy) c = pow(10, c);
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
} else {
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", NULL));
}
}
/* y hcursor2 toggle */
else if(key == 'B' && access_cond && i == xctx->graph_master) {
xctx->graph_flags ^= 256;
need_redraw = 1;
if(xctx->graph_flags & 256) {
double c = G_Y(xctx->mousey);
if(gr->logy) c = pow(10, c);
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
} else {
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", NULL));
}
}
else if(key == 't' && access_cond ) {
if(track_dset != -2) {
/*
@ -1161,7 +1260,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
else if( event == ButtonRelease) {
if(button != Button3) {
xctx->ui_state &= ~GRAPHPAN;
xctx->graph_flags &= ~(16 | 32); /* clear move cursor flags */
xctx->graph_flags &= ~(16 | 32 | 512 | 1024); /* clear move cursor flags */
}
/* zoom area by mouse drag */
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) &&
@ -1191,7 +1290,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} /* else if( event == ButtonRelease) */
if(need_redraw || need_all_redraw) {
setup_graph_data(i, 0, gr);
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in each graph box */
draw_graph(i, 1 + 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), gr, NULL); /* draw data in each graph box */
}
} /* for(i=0; i< xctx->rects[GRIDLAYER]; i++ */
@ -2699,17 +2798,27 @@ int rstate; /* (reduced state, without ShiftMask) */
}
if(key==XK_Right && state == ControlMask) {
int save = xctx->semaphore;
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
if(xctx->semaphore >= 2) break;
xctx->semaphore = 0;
tcleval("next_tab");
xctx->semaphore = save;
break;
}
if(key==XK_Left && state == ControlMask) {
int save = xctx->semaphore;
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
if(xctx->semaphore >= 2) break;
xctx->semaphore = 0;
tcleval("prev_tab");
xctx->semaphore = save;
break;
}
if(key==XK_Right && !(state & ControlMask)) /* left */
{
@ -3589,20 +3698,32 @@ int rstate; /* (reduced state, without ShiftMask) */
break;
}
if(key=='A' && rstate == ControlMask) /* only for graph (toggle hcursor1 if graph_use_ctrl_key set) */
{
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
break;
}
if(key=='A' && rstate == 0) /* toggle show netlist */
{
int net_s;
net_s = tclgetboolvar("netlist_show");
net_s = !net_s;
if(net_s) {
tcleval("alert_ { enabling show netlist window} {}");
tclsetvar("netlist_show","1");
}
else {
tcleval("alert_ { disabling show netlist window } {}");
tclsetvar("netlist_show","0");
}
break;
int net_s;
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
net_s = tclgetboolvar("netlist_show");
net_s = !net_s;
if(net_s) {
tcleval("alert_ { enabling show netlist window} {}");
tclsetvar("netlist_show","1");
}
else {
tcleval("alert_ { disabling show netlist window } {}");
tclsetvar("netlist_show","0");
}
break;
}
if(key=='>') {
if(xctx->semaphore >= 2) break;
@ -3628,8 +3749,20 @@ int rstate; /* (reduced state, without ShiftMask) */
}
break;
}
if(key=='B' && rstate == ControlMask) /* only for graph (toggle hcursor2 if graph_use_ctrl_key set) */
{
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
break;
}
if(key=='B' && rstate == 0) /* edit schematic header/license */
{
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
}
tcleval("update_schematic_header");
}
if(key=='b' && rstate==0) /* merge schematic */

View File

@ -2905,7 +2905,18 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->digital = 0;
gr->rainbow = 0;
gr->linewidth_mult = tclgetdoublevar("graph_linewidth_mult");
xctx->graph_flags &= ~(128 | 256); /* clear hcursor flags */
gr->hcursor1_y = gr->hcursor2_y = 0.0;
val = get_tok_value(r->prop_ptr,"hcursor1_y", 0);
if(val[0]) {
gr->hcursor1_y = atof_spice(val);
xctx->graph_flags |= 128;
}
val = get_tok_value(r->prop_ptr,"hcursor2_y", 0);
if(val[0]) {
gr->hcursor2_y = atof_spice(val);
xctx->graph_flags |= 256;
}
if(!skip) {
gr->gx1 = 0;
gr->gx2 = 1e-6;
@ -3016,9 +3027,9 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->gh = gr->gy2 - gr->gy1;
/* set margins */
tmp = gr->rw * 0.14;
gr->marginx = tmp < 30 ? 30 : tmp;
gr->marginx = tmp < 50 ? 50 : tmp;
tmp = gr->rh * 0.14;
gr->marginy = tmp < 35 ? 35 : tmp;
gr->marginy = tmp < 40 ? 40 : tmp;
/* calculate graph bounding box (container - margin)
* This is the box where plot is done */
@ -3031,7 +3042,7 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->h = gr->y2 - gr->y1;
/* label text size calculations */
gr->txtsizelab = gr->marginy * 0.007;
gr->txtsizelab = gr->marginy * 0.006;
/*
* tmp = gr->w * 0.00044;
* if(tmp < gr->txtsizelab) gr->txtsizelab = tmp;
@ -3042,8 +3053,8 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->digtxtsizelab = 0.001200 * fabs( gr->h / gr->posh * gr->gh );
/* x axis, y axis text sizes */
gr->txtsizey = gr->h / gr->divy * 0.009;
tmp = gr->marginx * 0.005;
gr->txtsizey = gr->h / gr->divy * 0.0095;
tmp = gr->marginx * 0.003;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
tmp = gr->marginy * 0.02;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
@ -3136,7 +3147,7 @@ static void draw_cursor_difference(double c1, double c2, Graph_ctx *gr)
}
}
static void draw_hcursor(double active_cursory, double other_cursory, int cursor_color, Graph_ctx *gr)
static void draw_hcursor(double active_cursory, int cursor_color, Graph_ctx *gr)
{
double yy, pos = active_cursory;
double tx1, ty1, tx2, ty2, dtmp;
@ -3145,10 +3156,11 @@ static void draw_hcursor(double active_cursory, double other_cursory, int cursor
double txtsize = gr->txtsizey;
double th;
if(gr->digital) return;
if(gr->logy) pos = mylog10(pos);
yy = W_Y(pos);
if(yy >= gr->y1 && yy <= gr->y2) {
drawline(cursor_color, NOW, gr->rx1, yy, gr->rx2, yy, 1, NULL);
drawline(cursor_color, NOW, gr->rx1 + 10, yy, gr->rx2 - 10, yy, 1, NULL);
if(gr->unity != 1.0)
my_snprintf(tmpstr, S(tmpstr), " %.5g%c ", gr->unity * active_cursory , gr->unity_suffix);
else
@ -3164,7 +3176,41 @@ static void draw_hcursor(double active_cursory, double other_cursory, int cursor
static void draw_hcursor_difference(double c1, double c2, Graph_ctx *gr)
{
/* <<<<< */
int tmp;
char tmpstr[100];
double txtsize = gr->txtsizey;
double tx1, ty1, tx2, ty2;
double cc1 = gr->logy ? mylog10(c1) : c1;
double cc2 = gr->logy ? mylog10(c2) : c2;
double aa = W_Y(cc1);
double a = CLIP(aa, gr->y1, gr->y2);
double bb = W_Y(cc2);
double b = CLIP(bb, gr->y1, gr->y2);
double diff = fabs(b - a);
double diffh;
double yy = ( a + b ) * 0.5;
double xx = gr->rx1 + 5;
double dtmp;
double xline;
if(gr->digital) return;
diffh = fabs(c2 - c1);
if(gr->unity != 1.0)
my_snprintf(tmpstr, S(tmpstr), " %.4g%c ", gr->unity * diffh , gr->unity_suffix);
else
my_snprintf(tmpstr, S(tmpstr), " %s ", dtoa_eng(diffh));
text_bbox(tmpstr, txtsize, txtsize, 0, 0, 0, 1, xx, yy, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
if( 2 * (ty2 - ty1) < diff ) {
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
draw_string(3, NOW, tmpstr, 0, 0, 0, 1, xx, yy, txtsize, txtsize);
if( a > b) {
dtmp = a; a = b; b = dtmp;
}
xline = tx1 + 10;
if( ty1 - a > 4.0) drawline(3, NOW, xline, a + 2, xline, ty1 - 2, 1, NULL);
if( b - ty2 > 4.0) drawline(3, NOW, xline, ty2 + 2, xline, b - 2, 1, NULL);
}
}
/* sweep variables on x-axis, node labels */
@ -3747,7 +3793,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
#if 0
dbg(0, "draw_graph(): window: %d %d %d %d\n", xctx->areax1, xctx->areay1, xctx->areax2, xctx->areay2);
dbg(0, "draw_graph(): graph: %g %g %g %g\n", gr->sx1, gr->sy1, gr->sx2, gr->sy2);
dbg(0, "draw_graph(): i = %d, flags = %d\n", i, flags);
dbg(0, "draw_graph(): i = %d, flags = %d graph_flags=%d\n", i, flags, xctx->graph_flags);
#endif
/* draw stuff */
@ -4074,12 +4120,12 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
if((flags & 4)) draw_cursor(cursor2, cursor1, 3, gr);
/* difference between cursors */
if((flags & 2) && (flags & 4)) draw_cursor_difference(cursor1, cursor2, gr);
/* hcursor1 */
if(flags & 128) draw_hcursor(9.012345, 15.0, 15, gr);
/* hcursor2 */
if(flags & 256) draw_hcursor(15.0, 9.012345, 16, gr);
/* difference between hcursors */
if((flags & 128) && (flags & 256)) draw_hcursor_difference(9.012345, 15.00, gr);
if((flags & 128) && (flags & 256)) draw_hcursor_difference(gr->hcursor1_y, gr->hcursor2_y, gr);
/* hcursor1 */
if(flags & 128) draw_hcursor(gr->hcursor1_y, 15, gr);
/* hcursor2 */
if(flags & 256) draw_hcursor(gr->hcursor2_y, 19, gr);
}
if(flags & 1) { /* copy save buffer to screen */
if(!xctx->draw_window) {
@ -4130,8 +4176,10 @@ static void draw_graph_all(int flags)
if(xctx->enable_layer[GRIDLAYER]) for(i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
xRect *r = &xctx->rect[GRIDLAYER][i];
if(r->flags & 1) {
int flags2;
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, flags, &xctx->graph_struct, NULL); /* draw data in each graph box */
flags2 = flags | (xctx->graph_flags & (128 | 256)); /* include drawing hcursors if enabled */
draw_graph(i, flags2, &xctx->graph_struct, NULL); /* draw data in each graph box */
}
}
}

View File

@ -877,14 +877,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
int i = atoi(argv[2]);
setup_graph_data(i, 0, &xctx->graph_struct);
if(argc > 3) {
flags = atoi(argv[3]);
} else {
/* 2: draw cursor 1
* 4: draw cursor 2 */
flags = 1 + 8 + (xctx->graph_flags & (2 + 4));
* 4: draw cursor 2
* 128: draw hcursor 1
* 256: draw hcursor 2 */
flags = 1 + 8 + (xctx->graph_flags & (2 + 4 + 128 + 256));
}
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, flags, &xctx->graph_struct, NULL);
}
Tcl_ResetResult(interp);

View File

@ -888,6 +888,7 @@ typedef struct {
int logx, logy;
int rainbow; /* draw multiple datasets with incrementing colors */
double linewidth_mult; /* multiply factor for waveforms line width */
double hcursor1_y, hcursor2_y; /* hcursor positions */
} Graph_ctx;
typedef struct {