From 4d767085347731f120213265182810ca4f97fcc7 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Sun, 5 Jan 2025 11:27:18 +0100
Subject: [PATCH 01/21] save_schematic(): remove set_modify(2) if same name.
need to add a dedicated parameter for save without title update
---
src/save.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/save.c b/src/save.c
index 24e38d02..d9ac258a 100644
--- a/src/save.c
+++ b/src/save.c
@@ -3322,7 +3322,6 @@ int save_schematic(const char *schname) /* 20171020 added return value */
xRect *rect;
int rects;
char msg[PATH_MAX + 100];
- int same_name = 0;
if(!schname || !strcmp(schname, "")) return 0;
@@ -3338,7 +3337,6 @@ int save_schematic(const char *schname) /* 20171020 added return value */
set_modify(-1); /* set title to new filename */
}
else { /* user asks to save to same filename */
- same_name = 1;
if(!stat(xctx->sch[xctx->currsch], &buf)) {
if(xctx->time_last_modify && xctx->time_last_modify != buf.st_mtime) {
tclvareval("ask_save_optional \"Schematic file: ", xctx->sch[xctx->currsch],
@@ -3374,8 +3372,7 @@ int save_schematic(const char *schname) /* 20171020 added return value */
* xctx->prep_hash_wires=0;
*/
if(!strstr(xctx->sch[xctx->currsch], ".xschem_embedded_")) {
- if(same_name) set_modify(2); /* clear only modified flag, do not set window title etc */
- else set_modify(0);
+ set_modify(0);
}
tclvareval(xctx->top_path, ".menubar entryconfigure Simulate -background $simulate_bg", NULL);
tclvareval("set tctx::", xctx->current_win_path, "_simulate $simulate_bg", NULL);
From 783fa04eb6eb1a7b9508ebbaae82ee0d664e5556 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Sun, 5 Jan 2025 13:27:49 +0100
Subject: [PATCH 02/21] `xschem save` --> save_schematic(): added `fast`
argument (do not update window/tab/sim button states for speed); `xschem
select instance` --> select_element(): added `nodraw` argument in addition to
existing `fast` (avoid drawing selected item for speed)
---
doc/xschem_man/developer_info.html | 7 +++++--
src/actions.c | 21 +++++++++++----------
src/callback.c | 4 ++--
src/save.c | 7 ++++---
src/scheduler.c | 23 ++++++++++++++++-------
src/select.c | 8 ++++++--
src/xschem.h | 4 ++--
src/xschem.tcl | 4 ++--
8 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html
index 90222099..e4f6ed33 100644
--- a/doc/xschem_man/developer_info.html
+++ b/doc/xschem_man/developer_info.html
@@ -1342,8 +1342,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
if x0, y0 not given use mouse coordinates
rotate_in_place
Rotate selected objects around their 0,0 coordinate point
- save
- Save schematic if modified. Does not ask confirmation!
+ save [fast]
+ Save schematic if modified. Does not ask confirmation!
+ if 'fast' is given it is passed to save_schematic() to avoid
+ updating window/tab/sim button states
saveas [file] [type]
save current schematic as 'file'
if file is empty ({}) use current schematic name
@@ -1393,6 +1395,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
for all other objects 'id' is the position in the respective arrays
if 'clear' is specified does an unselect operation
if 'fast' is specified avoid sending information to infowindow and status bar
+ if 'nodraw' is given on select instance do not draw selection
returns 1 if something selected, 0 otherwise
select_all
Selects all objects in schematic
diff --git a/src/actions.c b/src/actions.c
index 1d52d0b5..ab8af011 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -536,8 +536,9 @@ const char *get_file_path(char *f)
* 1 : file saved or not needed to save since no change
* -1 : user cancel
* 0 : file not saved due to errors or per user request
+ * confirm:
*/
-int save(int confirm)
+int save(int confirm, int fast)
{
struct stat buf;
char *name = xctx->sch[xctx->currsch];
@@ -556,10 +557,10 @@ int save(int confirm)
if(confirm) {
tcleval("ask_save_optional");
if(!strcmp(tclresult(), "") ) return -1; /* user clicks "Cancel" */
- else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch]);
+ else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch], fast);
else return 0; /* user clicks "no" */
} else {
- return save_schematic(xctx->sch[xctx->currsch]);
+ return save_schematic(xctx->sch[xctx->currsch], fast);
}
}
return 1; /* circuit not changed: always succeeed */
@@ -592,7 +593,7 @@ void saveas(const char *f, int type) /* changed name from ask_save_file to save
if(!res[0]) return;
dbg(1, "saveas(): res = %s\n", res);
- save_schematic(res);
+ save_schematic(res, 0);
tclvareval("update_recent_file {", res,"}", NULL);
return;
}
@@ -603,7 +604,7 @@ void ask_new_file(void)
if(!has_x) return;
if(xctx->modified) {
- if(save(1) == -1 ) return; /* user cancels save, so do nothing. */
+ if(save(1, 0) == -1 ) return; /* user cancels save, so do nothing. */
}
tcleval("load_file_dialog {Load file} *.\\{sch,sym,tcl\\} INITIALLOADDIR");
my_snprintf(f, S(f),"%s", tclresult());
@@ -2231,7 +2232,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
my_strncpy(res, tclresult(), S(res));
if(!res[0]) return 0;
dbg(1, "descend_schematic(): saving: %s\n",res);
- save_ok = save_schematic(res);
+ save_ok = save_schematic(res, 0);
if(save_ok==0) return 0;
}
n = xctx->sel_array[0].n;
@@ -2248,7 +2249,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
if(xctx->modified) {
int ret;
- ret = save(1);
+ ret = save(1, 0);
/* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights
* save() return value:
@@ -2402,10 +2403,10 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
{
if(confirm) {
tcleval("ask_save_optional");
- if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch]);
+ if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
else if(!strcmp(tclresult(), "") ) return;
} else {
- save_ok = save_schematic(xctx->sch[xctx->currsch]);
+ save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
}
}
if(save_ok==0) {
@@ -2458,7 +2459,7 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
void clear_schematic(int cancel, int symbol)
{
- if(cancel == 1) cancel=save(1);
+ if(cancel == 1) cancel=save(1, 0);
if(cancel != -1) { /* -1 means user cancel save request */
char name[PATH_MAX];
struct stat buf;
diff --git a/src/callback.c b/src/callback.c
index 25da6526..429e1f69 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -2831,7 +2831,7 @@ int rstate; /* (reduced state, without ShiftMask) */
if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) {
saveas(NULL, SCHEMATIC);
} else {
- save(1);
+ save(1, 0);
}
break;
}
@@ -2907,7 +2907,7 @@ int rstate; /* (reduced state, without ShiftMask) */
"-message {do you want to make symbol view ?}");
if(strcmp(tclresult(),"ok")==0)
{
- save_schematic(xctx->sch[xctx->currsch]);
+ save_schematic(xctx->sch[xctx->currsch], 0);
make_symbol();
}
break;
diff --git a/src/save.c b/src/save.c
index d9ac258a..bf880b1d 100644
--- a/src/save.c
+++ b/src/save.c
@@ -3315,7 +3315,7 @@ Sch_pin_record *sort_schematic_pins(int *npins)
* 0 : did not save
* 1 : schematic saved
*/
-int save_schematic(const char *schname) /* 20171020 added return value */
+int save_schematic(const char *schname, int fast) /* 20171020 added return value */
{
FILE *fd;
struct stat buf;
@@ -3372,7 +3372,8 @@ int save_schematic(const char *schname) /* 20171020 added return value */
* xctx->prep_hash_wires=0;
*/
if(!strstr(xctx->sch[xctx->currsch], ".xschem_embedded_")) {
- set_modify(0);
+ if(fast) set_modify(2); /* only clear modified flag, no title/tab/sim buttons update */
+ else set_modify(0);
}
tclvareval(xctx->top_path, ".menubar entryconfigure Simulate -background $simulate_bg", NULL);
tclvareval("set tctx::", xctx->current_win_path, "_simulate $simulate_bg", NULL);
@@ -5067,7 +5068,7 @@ void descend_symbol(void)
if(xctx->modified)
{
int ret;
- ret = save(1);
+ ret = save(1, 1);
/* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights
* save() return value:
diff --git a/src/scheduler.c b/src/scheduler.c
index e66b69d7..e63088df 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -914,7 +914,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
rebuild_selected_array();
if(xctx->lastsel==0 ) {
- save_schematic(xctx->sch[xctx->currsch]); /* sync data with disk file before editing file */
+ save_schematic(xctx->sch[xctx->currsch], 0); /* sync data with disk file before editing file */
my_snprintf(name, S(name), "edit_file {%s}",
abs_sym_path(xctx->sch[xctx->currsch], ""));
tcleval(name);
@@ -2815,7 +2815,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f);
my_strncpy(f, tclresult(), S(f));
- if(force || !has_x || !xctx->modified || save(1) != -1 ) { /* save(1)==-1 --> user cancel */
+ if(force || !has_x || !xctx->modified || save(1, 0) != -1 ) { /* save(1)==-1 --> user cancel */
char win_path[WINDOW_PATH_SIZE];
int skip = 0;
dbg(1, "scheduler(): load: filename=%s\n", argv[2]);
@@ -3049,7 +3049,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(has_x) tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
"-message {do you want to make symbol view ?}");
if(!has_x || strcmp(tclresult(), "ok")==0) {
- save_schematic(xctx->sch[xctx->currsch]);
+ save_schematic(xctx->sch[xctx->currsch], 0);
make_symbol();
}
Tcl_ResetResult(interp);
@@ -4590,16 +4590,23 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else { cmd_found = 0;}
break;
case 's': /*----------------------------------------------*/
- /* save
- * Save schematic if modified. Does not ask confirmation! */
+ /* save [fast]
+ * Save schematic if modified. Does not ask confirmation!
+ * if 'fast' is given it is passed to save_schematic() to avoid
+ * updating window/tab/sim button states */
if(!strcmp(argv[1], "save"))
{
+ int fast = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
dbg(1, "scheduler(): saving: current schematic\n");
+ for(i = 2; i < argc; i++) {
+ if(!strcmp(argv[i], "fast")) fast |= 1;
+ }
+
if(!strcmp(xctx->sch[xctx->currsch], "")) { /* check if unnamed schematic, use saveas in this case... */
saveas(NULL, SCHEMATIC);
} else {
- save(0);
+ save(0, fast);
}
}
@@ -4745,6 +4752,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* for all other objects 'id' is the position in the respective arrays
* if 'clear' is specified does an unselect operation
* if 'fast' is specified avoid sending information to infowindow and status bar
+ * if 'nodraw' is given on select instance do not draw selection
* returns 1 if something selected, 0 otherwise */
else if(!strcmp(argv[1], "select"))
{
@@ -4766,7 +4774,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int i;
for(i = 4; i < argc; i++) {
if(!strcmp(argv[i], "clear")) sel = 0;
- if(!strcmp(argv[i], "fast")) fast = 1;
+ if(!strcmp(argv[i], "fast")) fast |= 1;
+ if(!strcmp(argv[i], "nodraw") && !strcmp(argv[2], "instance")) fast |= 2;
}
}
if(!strcmp(argv[2], "instance") && argc > 3) {
diff --git a/src/select.c b/src/select.c
index bf8f3c92..324dac19 100644
--- a/src/select.c
+++ b/src/select.c
@@ -937,6 +937,10 @@ void select_wire(int i,unsigned short select_mode, int fast)
xctx->need_reb_sel_arr=1;
}
+/* fast == 1: do not update status line
+ * fast == 2: do not draw / undraw selected elements
+ * fast == 3: 1 + 2
+ */
void select_element(int i,unsigned short select_mode, int fast, int override_lock)
{
int c, j;
@@ -946,7 +950,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
if(!strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
my_strncpy(s,xctx->inst[i].prop_ptr!=NULL?xctx->inst[i].prop_ptr:"",S(s));
- if( !fast )
+ if( !(fast & 1) )
{
my_snprintf(str, S(str), "Info: selected element %d: %s\nproperties:\n%s", i,
xctx->inst[i].name ? xctx->inst[i].name : "" , s);
@@ -976,7 +980,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
}
xctx->inst[i].sel = select_mode;
if(select_mode == SELECTED) set_first_sel(ELEMENT, i, 0);
- if(!fast) {
+ if(!(fast & 2) ) {
if(select_mode) {
for(c=0;cgc[SELLAYER], i,c,0,0,0.0,0.0);
diff --git a/src/xschem.h b/src/xschem.h
index 3f59ee9b..60bfd767 100644
--- a/src/xschem.h
+++ b/src/xschem.h
@@ -1310,7 +1310,7 @@ extern void new_xschem_process(const char *cell, int symbol);
extern void ask_new_file(void);
extern void saveas(const char *f, int type);
extern const char *get_file_path(char *f);
-extern int save(int confirm);
+extern int save(int confirm, int fast);
extern void save_ascii_string(const char *ptr, FILE *fd, int newline);
extern Hilight_hashentry *bus_hilight_hash_lookup(const char *token, int value, int what) ;
/* wrapper function to hash highlighted instances, avoid clash with net names */
@@ -1496,7 +1496,7 @@ extern int sym_vs_sch_pins(int all);
extern char *get_generator_command(const char *str);
extern int match_symbol(const char name[]);
extern Sch_pin_record *sort_schematic_pins(int *npins);
-extern int save_schematic(const char *); /* 20171020 added return value */
+extern int save_schematic(const char *, int fast); /* 20171020 added return value */
extern void copy_symbol(xSymbol *dest_sym, xSymbol *src_sym);
extern void push_undo(void);
extern void pop_undo(int redo, int set_modify_status);
diff --git a/src/xschem.tcl b/src/xschem.tcl
index e2ef5c13..3ee1dd12 100644
--- a/src/xschem.tcl
+++ b/src/xschem.tcl
@@ -1904,7 +1904,7 @@ proc traversal_setlabels {w parent_sch instname inst_sch sym_sch default_sch ins
xschem setprop instance $instname schematic [$w get] fast ;# set schematic attr on instance
}
xschem set_modify 3 ;# set only modified flag to force a save, do not update window/tab titles
- xschem save
+ xschem save fast
set inst_sch [$w get]
# puts "inst_sch set to: $inst_sch"
xschem load $current noundoreset nodraw
@@ -2083,7 +2083,7 @@ proc hier_traversal {{level 0} {only_subckts 0} {all_hierarchy 1}} {
set done_print 1
if {$type eq {subcircuit} && $all_hierarchy} {
- xschem select instance $i fast
+ xschem select instance $i fast nodraw
set descended [xschem descend 1 6]
if {$descended} {
incr level
From 9fda7e2f9687de394fb67892b1d20093b84fa8e3 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Mon, 6 Jan 2025 13:14:12 +0100
Subject: [PATCH 03/21] wip: put code in place for horiz cursors in graphs
---
src/callback.c | 8 +++++--
src/draw.c | 63 ++++++++++++++++++++++++++++++++++++++------------
src/xschem.tcl | 7 +++---
3 files changed, 58 insertions(+), 20 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 429e1f69..89613a82 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -346,9 +346,13 @@ void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
* 2: draw x-cursor1
* 4: draw x-cursor2
* 8: dnu, reserved, used in draw_graphs()
- * 16: move cursor1
- * 32: move cursor2
+ * 16: move x-cursor1
+ * 32: move x-cursor2
* 64: show measurement tooltip
+ * 128: draw y-cursor1 (hcursor)
+ * 256: draw y-cursor2 (hcursor)
+ * 512: move y-cursor1
+ * 1024: move y-cursor2
*/
static int waves_callback(int event, int mx, int my, KeySym key, int button, int aux, int state)
{
diff --git a/src/draw.c b/src/draw.c
index cf376639..9ab5857d 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -3136,6 +3136,37 @@ 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)
+{
+ double yy, pos = active_cursory;
+ double tx1, ty1, tx2, ty2, dtmp;
+ int tmp;
+ char tmpstr[100];
+ double txtsize = gr->txtsizey;
+ double th;
+
+ 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);
+ if(gr->unity != 1.0)
+ my_snprintf(tmpstr, S(tmpstr), " %.5g%c ", gr->unity * active_cursory , gr->unity_suffix);
+ else
+ my_snprintf(tmpstr, S(tmpstr), " %s ", dtoa_eng(active_cursory));
+ text_bbox(tmpstr, txtsize, txtsize, 0, 0, 0, 0, gr->rx1 + 5, yy, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
+ th = (ty2 - ty1) / 2.; /* half text height */
+ ty1 -= th;
+ ty2 -= th;
+ filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
+ draw_string(cursor_color, NOW, tmpstr, 0, 0, 0, 0, gr->rx1 + 5, yy - th, txtsize, txtsize);
+ }
+}
+
+static void draw_hcursor_difference(double c1, double c2, Graph_ctx *gr)
+{
+ /* <<<<< */
+}
+
/* sweep variables on x-axis, node labels */
static void draw_graph_variables(int wcnt, int wave_color, int n_nodes, int sweep_idx,
int flags, const char *ntok, const char *stok, const char *bus_msb, Graph_ctx *gr)
@@ -3654,12 +3685,14 @@ int find_closest_wave(int i, Graph_ctx *gr)
/* flags:
- * 1: do final XCopyArea (copy 2nd buffer areas to screen)
- * If draw_graph_all() is called from draw() no need to do XCopyArea, as draw() does it already.
- * This makes drawing faster and removes a 'tearing' effect when moving around.
- * 2: draw x-cursor1
- * 4: draw x-cursor2
- * 8: all drawing, if not set do only XCopyArea / x-cursor if specified
+ * 1: do final XCopyArea (copy 2nd buffer areas to screen)
+ * If draw_graph_all() is called from draw() no need to do XCopyArea, as draw() does it already.
+ * This makes drawing faster and removes a 'tearing' effect when moving around.
+ * 2: draw x-cursor1
+ * 4: draw x-cursor2
+ * 128: draw y-cursor1
+ * 256: draw y-cursor2
+ * 8: all drawing, if not set do only XCopyArea / x-cursor if specified
* ct is a pointer used in windows for cairo
*/
void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
@@ -4036,17 +4069,17 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
*/
if(flags & 8) {
/* cursor1 */
- if((flags & 2)) {
- draw_cursor(cursor1, cursor2, 1, gr);
- }
+ if((flags & 2)) draw_cursor(cursor1, cursor2, 1, gr);
/* cursor2 */
- if((flags & 4)) {
- draw_cursor(cursor2, cursor1, 3, gr);
- }
+ if((flags & 4)) draw_cursor(cursor2, cursor1, 3, gr);
/* difference between cursors */
- if((flags & 2) && (flags & 4)) {
- draw_cursor_difference(cursor1, cursor2, gr);
- }
+ 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 & 1) { /* copy save buffer to screen */
if(!xctx->draw_window) {
diff --git a/src/xschem.tcl b/src/xschem.tcl
index 3ee1dd12..f7cb1e58 100644
--- a/src/xschem.tcl
+++ b/src/xschem.tcl
@@ -1785,16 +1785,17 @@ proc cellview_setlabels {w symbol sym_sch default_sch sym_spice_sym_def} {
$w configure -bg [option get . background {}]
if { $sym_spice_sym_def ne {}} {
$w configure -fg $symfg
- } elseif { ![file exists [abs_sym_path [$w get]]] } {
- $w configure -bg $missingbg
} else {
if {[$w get] eq $default_sch} {
- # ....
+ puts "need to clear schematic attr in symbol"
} elseif {[$w get] eq $sym_sch} {
$w configure -bg $symbg
} else {
puts "need to update:[$w get] --> $sym_sch"
}
+ if { ![file exists [abs_sym_path [$w get]]] } {
+ $w configure -bg $missingbg
+ }
}
}
From a3e7610d83f64a480b69dae401467dbc823fdbb9 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Tue, 7 Jan 2025 04:20:32 +0100
Subject: [PATCH 04/21] horizontal cursors in graphs
---
doc/xschem_man/graphs.html | 21 +++--
src/callback.c | 179 ++++++++++++++++++++++++++++++++-----
src/draw.c | 80 +++++++++++++----
src/scheduler.c | 8 +-
src/xschem.h | 1 +
5 files changed, 241 insertions(+), 48 deletions(-)
diff --git a/doc/xschem_man/graphs.html b/doc/xschem_man/graphs.html
index a485bb2e..df60995d 100644
--- a/doc/xschem_man/graphs.html
+++ b/doc/xschem_man/graphs.html
@@ -66,9 +66,6 @@ p{padding: 15px 30px 10px;}
Waves->Op | Ac | Dc | Tran | Tran | Noise | Sp . This command loads the user selected
.raw file produced by a ngspice/Xyce simulation.
-
- Ensure the circuit.raw is saved in binary format (no set filetype=ascii in your testbench)
-
The raw file is usually located in the simulation/netlisting directory
Simulation ->set netlist dir.
@@ -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 +).
+
+
+ if set graph_use_ctrl_key 1 is set in the xschemrc file all bind keys shown
+ below will need the Control 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 Control
+ key pressed the usual functions on schematic are performed instead of graph functions.
+ Example: the key a 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 set graph_use_ctrl_key 1 option
+ you will need to press Control-a with the mouse pointer inside a graph to show a cursor.
+
+
if the mouse is outside the graph the usual Xschem functions will be available to operate on schematics:
@@ -87,13 +95,14 @@ p{padding: 15px 30px 10px;}
- Pressing f with the mouse on the left of the Y axis will do a full Y-axis zoom.
- Pressing Left/Right or Up/Down arrow keys while the mouse is inside a graph will
move the waveforms to the left/right or zoom in/zoom out respectively.
- - Pressing Left/Right or Up/Down 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.
+ - Pressing Left/Right arrow keys while the mouse is on the left of the Y-axis
+ will zoom in/zoom out in the Y direction.
- Pressing the left mouse button while the pointer is in the center of the graph
will move the waves left or right following the pointer X movement.
- Pressing the left 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.
- - Doing the above with the Shift key pressed will zoom in/out instead of moving.
+ - pressing A and/or B will show a horizontal cursor.
+ The difference between the A and the B cursor is shown.
- pressing a and/or b will show a vertical cursor.
The sweep variable difference between the a and the b cursor is shown and
the values of all signals at the X position of the a cursor is shown.
diff --git a/src/callback.c b/src/callback.c
index 89613a82..bdfd30a6 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -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 */
diff --git a/src/draw.c b/src/draw.c
index 9ab5857d..36660d3b 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -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 */
}
}
}
diff --git a/src/scheduler.c b/src/scheduler.c
index e63088df..38b1fca0 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -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);
diff --git a/src/xschem.h b/src/xschem.h
index 60bfd767..884076d2 100644
--- a/src/xschem.h
+++ b/src/xschem.h
@@ -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 {
From 15738bbf5194a43386acf949f6899abb39c1835f Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Tue, 7 Jan 2025 12:03:49 +0100
Subject: [PATCH 05/21] better drag waves in x direction (continue even if
dragging outside of graph)
---
src/callback.c | 12 +++++++-----
src/xinit.c | 2 +-
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index bdfd30a6..bba19131 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -52,7 +52,9 @@ static int waves_selected(int event, KeySym key, int state, int button)
r = &xctx->rect[GRIDLAYER][i];
if(!(r->flags & 1) ) continue;
if(!strboolcmp(get_tok_value(xctx->rect[GRIDLAYER][i].prop_ptr, "lock", 0), "true")) continue;
+
check =
+ (xctx->ui_state & GRAPHPAN) ||
(event != -3 &&
(
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 20, r->y1 + 8, r->x2 - 20, r->y2 - 8) ||
@@ -64,7 +66,8 @@ static int waves_selected(int event, KeySym key, int state, int button)
(POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2 - 40, r->y1 + 20) ||
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 20, r->y1, r->x2 - 30, r->y2 - 10))
);
- if( (xctx->ui_state & GRAPHPAN) || check) {
+
+ if(check) {
is_inside = 1;
if(draw_xhair) draw_crosshair(1);
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
@@ -389,10 +392,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(!(r->flags & 1) ) continue;
/* check if this is the master graph (the one containing the mouse pointer) */
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
- if( POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2)) {
- dbg(1, "mouse inside: %d\n", i);
+ if( (xctx->ui_state & GRAPHPAN) || POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2)) {
+ dbg(1, "mouse inside: %d mousex=%g\n", i, xctx->mousex);
setup_graph_data(i, 0, gr);
-
/* move hcursor1 */
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 512 )) {
double c;
@@ -1302,7 +1304,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* update saved mouse position after processing all graphs */
if(save_mouse_at_end) {
if( fabs(xctx->mx_double_save - xctx->mousex_snap) > fabs(gr->master_cx * gr->master_gw) * delta_threshold) {
- dbg(1, "save mose pos\n");
+ dbg(1, "save mouse pos\n");
xctx->mx_double_save = xctx->mousex_snap;
xctx->my_double_save = xctx->mousey_snap;
}
diff --git a/src/xinit.c b/src/xinit.c
index 5dd8e26c..5ec8745f 100644
--- a/src/xinit.c
+++ b/src/xinit.c
@@ -484,7 +484,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->extra_idx = 0;
xctx->extra_prev_idx = 0;
xctx->extra_raw_n = 0;
- xctx->graph_master = 0;
+ xctx->graph_master = -1;
xctx->graph_cursor1_x = 0;
xctx->graph_cursor2_x = 0;
xctx->graph_flags = 0;
From d2321f1eeb9c59505ade520ea76fbf46745ccf6f Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Tue, 7 Jan 2025 13:04:41 +0100
Subject: [PATCH 06/21] cleanup code in waves_callback()
---
src/callback.c | 545 +++++++++++++++++++++++++------------------------
1 file changed, 273 insertions(+), 272 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index bba19131..2c85b90a 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -69,12 +69,16 @@ static int waves_selected(int event, KeySym key, int state, int button)
if(check) {
is_inside = 1;
+ if(! (xctx->ui_state & GRAPHPAN) ) {
+ xctx->graph_master = i;
+ }
if(draw_xhair) draw_crosshair(1);
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
break;
}
}
if(!is_inside) {
+ xctx->graph_master = -1;
if(draw_xhair)
tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL);
else
@@ -386,266 +390,150 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
#endif
gr = &xctx->graph_struct;
for(i=0; i < xctx->rects[GRIDLAYER]; ++i) {
- if( (xctx->ui_state & GRAPHPAN) && i != xctx->graph_master) continue;
+ if(i != xctx->graph_master) continue;
r = &xctx->rect[GRIDLAYER][i];
/* process only graph boxes */
if(!(r->flags & 1) ) continue;
/* check if this is the master graph (the one containing the mouse pointer) */
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
- if( (xctx->ui_state & GRAPHPAN) || POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2)) {
- dbg(1, "mouse inside: %d mousex=%g\n", i, xctx->mousex);
- 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;
+ dbg(1, "mouse inside: %d mousex=%g\n", i, xctx->mousex);
+ 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, "hcursor2_y", dtoa(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 cursor1 */
- /* set cursor position from master graph x-axis */
- else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
- double 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)));
+ }
- c = G_X(xctx->mousex);
- if(gr->logx) c = pow(10, c);
- if(r->flags & 4) { /* private_cursor */
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c)));
- } else {
- xctx->graph_cursor1_x = c;
- }
- }
- /* move cursor2 */
- /* set cursor position from master graph x-axis */
- else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) {
- double c;
- int floaters = there_are_floaters();
+ /* move cursor1 */
+ /* set cursor position from master graph x-axis */
+ else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
+ double c;
- c = G_X(xctx->mousex);
- if(gr->logx) c = pow(10, c);
- if(r->flags & 4) { /* private_cursor */
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c)));
- } else {
- xctx->graph_cursor2_x = c;
- }
- if(tclgetboolvar("live_cursor2_backannotate")) {
- backannotate_at_cursor_b_pos(r, gr);
- if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
- }
- }
- gr->master_gx1 = gr->gx1;
- gr->master_gx2 = gr->gx2;
- gr->master_gw = gr->gw;
- gr->master_cx = gr->cx;
- if(xctx->ui_state & GRAPHPAN) break; /* After GRAPHPAN only need to check Motion events for cursors */
- if(xctx->mousey_snap < W_Y(gr->gy2)) {
- xctx->graph_top = 1;
+ c = G_X(xctx->mousex);
+ if(gr->logx) c = pow(10, c);
+ if(r->flags & 4) { /* private_cursor */
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c)));
} else {
- xctx->graph_top = 0;
+ xctx->graph_cursor1_x = c;
}
- if(xctx->mousex_snap < W_X(gr->gx1)) {
- xctx->graph_left = 1;
+ }
+ /* move cursor2 */
+ /* set cursor position from master graph x-axis */
+ else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) {
+ double c;
+ int floaters = there_are_floaters();
+
+ c = G_X(xctx->mousex);
+ if(gr->logx) c = pow(10, c);
+ if(r->flags & 4) { /* private_cursor */
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c)));
} else {
- xctx->graph_left = 0;
+ xctx->graph_cursor2_x = c;
+ }
+ if(tclgetboolvar("live_cursor2_backannotate")) {
+ backannotate_at_cursor_b_pos(r, gr);
+ if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
+ redraw_all_at_end = 1;
}
- if(xctx->mousey_snap > W_Y(gr->gy1)) {
- xctx->graph_bottom = 1;
- } else {
- xctx->graph_bottom = 0;
- }
- xctx->graph_master = i;
- zoom_m = (xctx->mousex - gr->x1) / gr->w;
- if(event == ButtonPress && button == Button1) {
- /* dragging cursors when mouse is very close */
- 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 */
- }
+ }
+ gr->master_gx1 = gr->gx1;
+ gr->master_gx2 = gr->gx2;
+ gr->master_gw = gr->gw;
+ gr->master_cx = gr->cx;
+ if(xctx->ui_state & GRAPHPAN) break; /* After GRAPHPAN only need to check Motion events for cursors */
+ if(xctx->mousey_snap < W_Y(gr->gy2)) {
+ xctx->graph_top = 1;
+ } else {
+ xctx->graph_top = 0;
+ }
+ if(xctx->mousex_snap < W_X(gr->gx1)) {
+ xctx->graph_left = 1;
+ } else {
+ xctx->graph_left = 0;
+ }
+ if(xctx->mousey_snap > W_Y(gr->gy1)) {
+ xctx->graph_bottom = 1;
+ } else {
+ xctx->graph_bottom = 0;
+ }
+ zoom_m = (xctx->mousex - gr->x1) / gr->w;
+ if(event == ButtonPress && button == Button1) {
+ /* dragging cursors when mouse is very close */
+ if(xctx->graph_flags & 128) { /* hcursor1 */
+ double cursor;
+ cursor = gr->hcursor1_y;
+ if(gr->logy ) {
+ cursor = mylog10(cursor);
}
- 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(fabs(xctx->mousey - W_Y(cursor)) < 10) {
+ xctx->graph_flags |= 512; /* Start move hcursor1 */
}
- 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);
- if(s[0]) {
- cursor1 = atof(s);
- } else {
- cursor1 = xctx->graph_cursor1_x;
- }
+ }
+ 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);
+ if(s[0]) {
+ cursor1 = atof(s);
} else {
cursor1 = xctx->graph_cursor1_x;
}
- if(gr->logx ) {
- cursor1 = mylog10(cursor1);
- }
- if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
- xctx->graph_flags |= 16; /* Start move cursor1 */
- }
+ } else {
+ cursor1 = xctx->graph_cursor1_x;
}
- 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);
- if(s[0]) {
- cursor2 = atof_spice(s);
- } else {
- cursor2 = xctx->graph_cursor2_x;
- }
- } else {
- cursor2 = xctx->graph_cursor2_x;
- }
- if(gr->logx) {
- cursor2 = mylog10(cursor2);
- }
- if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
- xctx->graph_flags |= 32; /* Start move cursor2 */
- }
+ if(gr->logx ) {
+ cursor1 = mylog10(cursor1);
+ }
+ if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
+ xctx->graph_flags |= 16; /* Start move cursor1 */
}
}
- else if(event == ButtonPress && button == Button3) {
- /* Numerically set cursor position */
- if(xctx->graph_flags & 2) {
- double cursor1;
- if(r->flags & 4) { /* private_cursor */
- const char *s = get_tok_value(r->prop_ptr, "cursor1_x", 0);
- if(s[0]) {
- cursor1 = atof_spice(s);
- } else {
- cursor1 = xctx->graph_cursor1_x;
- }
- } else {
- cursor1 = xctx->graph_cursor1_x;
- }
- if(gr->logx ) {
- cursor1 = mylog10(cursor1);
- }
- if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
- tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor1), NULL);
- cursor1 = atof_spice(tclresult());
- if(r->flags & 4) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(cursor1)));
- } else {
- xctx->graph_cursor1_x = cursor1;
- }
-
-
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
- }
- redraw_all_at_end = 1;
- }
- /* Numerically set cursor position */
- if(xctx->graph_flags & 4) {
- double cursor2;
- if(r->flags & 4) { /* private_cursor */
- const char *s = get_tok_value(r->prop_ptr, "cursor2_x", 0);
- if(s[0]) {
- cursor2 = atof_spice(s);
- } else {
- cursor2 = xctx->graph_cursor2_x;
- }
+ 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);
+ if(s[0]) {
+ cursor2 = atof_spice(s);
} else {
cursor2 = xctx->graph_cursor2_x;
}
- if(gr->logx) {
- cursor2 = mylog10(cursor2);
- }
- if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
- tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor2), NULL);
- cursor2 = atof_spice(tclresult());
- if(r->flags & 4) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(cursor2)));
- } else {
- xctx->graph_cursor2_x = cursor2;
- }
-
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
- }
- redraw_all_at_end = 1;
+ } else {
+ cursor2 = xctx->graph_cursor2_x;
+ }
+ if(gr->logx) {
+ cursor2 = mylog10(cursor2);
+ }
+ if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
+ xctx->graph_flags |= 32; /* Start move cursor2 */
}
}
- else if(event == -3 && button == Button1) {
- if(!edit_wave_attributes(1, i, gr)) {
- tclvareval("graph_edit_properties ", my_itoa(i), NULL);
- }
- }
- /* x cursor1 toggle */
- else if(key == 'a' && access_cond) {
- xctx->graph_flags ^= 2;
- need_all_redraw = 1;
- if(xctx->graph_flags & 2) {
- double c = G_X(xctx->mousex);
-
- if(gr->logx) c = pow(10, c);
- if(r->flags & 4) {
- if(!get_tok_value(r->prop_ptr, "cursor1_x", 0)[0]) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c)));
- }
- } else {
- xctx->graph_cursor1_x = c;
- }
- }
- }
- /* x cursor2 toggle */
- else if(key == 'b' && access_cond) {
- int floaters = there_are_floaters();
-
- xctx->graph_flags ^= 4;
- if(xctx->graph_flags & 4) {
- double c = G_X(xctx->mousex);
-
- if(gr->logx) c = pow(10, c);
- if(r->flags & 4) {
- if(!get_tok_value(r->prop_ptr, "cursor2_x", 0)[0]) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c)));
- }
- } else {
- xctx->graph_cursor2_x = c;
- }
- if(tclgetboolvar("live_cursor2_backannotate")) {
- backannotate_at_cursor_b_pos(r, gr);
- if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
- } else {
- need_all_redraw = 1;
- }
- } else if(xctx->raw) {
- xctx->raw->annot_p = -1;
- xctx->raw->annot_sweep_idx = -1;
- /* need_all_redraw = 1; */
- redraw_all_at_end = 1;
- }
- }
- /* swap cursors */
- else if((key == 's' && access_cond) ) {
- double tmp, cursor1, cursor2;
- int floaters = there_are_floaters();
-
+ }
+ else if(event == ButtonPress && button == Button3) {
+ /* Numerically set cursor position */
+ if(xctx->graph_flags & 2) {
+ double cursor1;
if(r->flags & 4) { /* private_cursor */
const char *s = get_tok_value(r->prop_ptr, "cursor1_x", 0);
if(s[0]) {
@@ -656,63 +544,176 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
cursor1 = xctx->graph_cursor1_x;
}
+ if(gr->logx ) {
+ cursor1 = mylog10(cursor1);
+ }
+ if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
+ tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor1), NULL);
+ cursor1 = atof_spice(tclresult());
+ if(r->flags & 4) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(cursor1)));
+ } else {
+ xctx->graph_cursor1_x = cursor1;
+ }
+
+ event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
+ }
+ redraw_all_at_end = 1;
+ }
+ /* Numerically set cursor position */
+ if(xctx->graph_flags & 4) {
+ double cursor2;
if(r->flags & 4) { /* private_cursor */
const char *s = get_tok_value(r->prop_ptr, "cursor2_x", 0);
- if(s[0]) {
+ if(s[0]) {
cursor2 = atof_spice(s);
- } else {
+ } else {
cursor2 = xctx->graph_cursor2_x;
- }
- } else {
+ }
+ } else {
cursor2 = xctx->graph_cursor2_x;
}
-
- tmp = cursor2;
- cursor2 = cursor1;
- cursor1 = tmp;
-
- if(r->flags & 4) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(cursor1)));
- } else {
- xctx->graph_cursor1_x = cursor1;
+ if(gr->logx) {
+ cursor2 = mylog10(cursor2);
}
+ if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
+ tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor2), NULL);
+ cursor2 = atof_spice(tclresult());
+ if(r->flags & 4) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(cursor2)));
+ } else {
+ xctx->graph_cursor2_x = cursor2;
+ }
+
+ event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
+ }
+ redraw_all_at_end = 1;
+ }
+ }
+ else if(event == -3 && button == Button1) {
+ if(!edit_wave_attributes(1, i, gr)) {
+ tclvareval("graph_edit_properties ", my_itoa(i), NULL);
+ }
+ }
+ /* x cursor1 toggle */
+ else if(key == 'a' && access_cond) {
+ xctx->graph_flags ^= 2;
+ need_all_redraw = 1;
+ if(xctx->graph_flags & 2) {
+ double c = G_X(xctx->mousex);
+
+ if(gr->logx) c = pow(10, c);
if(r->flags & 4) {
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(cursor2)));
+ if(!get_tok_value(r->prop_ptr, "cursor1_x", 0)[0]) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c)));
+ }
} else {
- xctx->graph_cursor2_x = cursor2;
+ xctx->graph_cursor1_x = c;
+ }
+ }
+ }
+ /* x cursor2 toggle */
+ else if(key == 'b' && access_cond) {
+ int floaters = there_are_floaters();
+
+ xctx->graph_flags ^= 4;
+ if(xctx->graph_flags & 4) {
+ double c = G_X(xctx->mousex);
+
+ if(gr->logx) c = pow(10, c);
+ if(r->flags & 4) {
+ if(!get_tok_value(r->prop_ptr, "cursor2_x", 0)[0]) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c)));
+ }
+ } else {
+ xctx->graph_cursor2_x = c;
}
if(tclgetboolvar("live_cursor2_backannotate")) {
backannotate_at_cursor_b_pos(r, gr);
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
redraw_all_at_end = 1;
+ } else {
+ need_all_redraw = 1;
}
- else need_all_redraw = 1;
+ } else if(xctx->raw) {
+ xctx->raw->annot_p = -1;
+ xctx->raw->annot_sweep_idx = -1;
+ /* need_all_redraw = 1; */
+ redraw_all_at_end = 1;
}
- /* measurement tooltip */
- else if((key == 'm') && access_cond) {
- xctx->graph_flags ^= 64;
- if(!(xctx->graph_flags & 64)) {
- tcleval("graph_show_measure stop");
+ }
+ /* swap cursors */
+ else if((key == 's' && access_cond) ) {
+ double tmp, cursor1, cursor2;
+ int floaters = there_are_floaters();
+
+ if(r->flags & 4) { /* private_cursor */
+ const char *s = get_tok_value(r->prop_ptr, "cursor1_x", 0);
+ if(s[0]) {
+ cursor1 = atof_spice(s);
+ } else {
+ cursor1 = xctx->graph_cursor1_x;
+ }
+ } else {
+ cursor1 = xctx->graph_cursor1_x;
+ }
+
+ if(r->flags & 4) { /* private_cursor */
+ const char *s = get_tok_value(r->prop_ptr, "cursor2_x", 0);
+ if(s[0]) {
+ cursor2 = atof_spice(s);
+ } else {
+ cursor2 = xctx->graph_cursor2_x;
+ }
+ } else {
+ cursor2 = xctx->graph_cursor2_x;
+ }
+
+ tmp = cursor2;
+ cursor2 = cursor1;
+ cursor1 = tmp;
+
+ if(r->flags & 4) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(cursor1)));
+ } else {
+ xctx->graph_cursor1_x = cursor1;
+ }
+ if(r->flags & 4) {
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(cursor2)));
+ } else {
+ xctx->graph_cursor2_x = cursor2;
+ }
+ if(tclgetboolvar("live_cursor2_backannotate")) {
+ backannotate_at_cursor_b_pos(r, gr);
+ if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
+ redraw_all_at_end = 1;
+ }
+ else need_all_redraw = 1;
+ }
+ /* measurement tooltip */
+ else if((key == 'm') && access_cond) {
+ xctx->graph_flags ^= 64;
+ if(!(xctx->graph_flags & 64)) {
+ tcleval("graph_show_measure stop");
+ }
+ }
+ else if(key == 't' && access_cond) {
+ if(!gr->digital) {
+ const char *d = get_tok_value(r->prop_ptr, "dataset", 0);
+ if(d[0]) {
+ track_dset = atoi(d);
+ } else {
+ track_dset = -1;
+ }
+ if(track_dset < 0) {
+ track_dset = find_closest_wave(i, gr);
+ } else {
+ track_dset = -1;
}
}
- else if(key == 't' && access_cond) {
- if(!gr->digital) {
- const char *d = get_tok_value(r->prop_ptr, "dataset", 0);
- if(d[0]) {
- track_dset = atoi(d);
- } else {
- track_dset = -1;
- }
- if(track_dset < 0) {
- track_dset = find_closest_wave(i, gr);
- } else {
- track_dset = -1;
- }
- }
- } /* key == 't' */
- break;
- } /* if( POINTINSIDE(...) */
+ } /* key == 't' */
+ break;
} /* for(i=0; i < xctx->rects[GRIDLAYER]; ++i) */
dbg(1, "out of 1st loop: i=%d\n", i);
From 149ee5fdc02dbf9efe42c7962ae68796f6a5b8f4 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Tue, 7 Jan 2025 14:31:26 +0100
Subject: [PATCH 07/21] further refactoring of waves_callback() (reduce first
loop over graphs to single iteration on graph_master)
---
src/callback.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 2c85b90a..22f31340 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -389,11 +389,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
cairo_font_face_destroy(xctx->cairo_font);
#endif
gr = &xctx->graph_struct;
- for(i=0; i < xctx->rects[GRIDLAYER]; ++i) {
- if(i != xctx->graph_master) continue;
- r = &xctx->rect[GRIDLAYER][i];
- /* process only graph boxes */
- if(!(r->flags & 1) ) continue;
+ if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) {
/* check if this is the master graph (the one containing the mouse pointer) */
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
dbg(1, "mouse inside: %d mousex=%g\n", i, xctx->mousex);
@@ -452,7 +448,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
gr->master_gx2 = gr->gx2;
gr->master_gw = gr->gw;
gr->master_cx = gr->cx;
- if(xctx->ui_state & GRAPHPAN) break; /* After GRAPHPAN only need to check Motion events for cursors */
+ if(xctx->ui_state & GRAPHPAN) goto finish; /* After GRAPHPAN only need to check Motion events for cursors */
if(xctx->mousey_snap < W_Y(gr->gy2)) {
xctx->graph_top = 1;
} else {
@@ -704,17 +700,17 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(d[0]) {
track_dset = atoi(d);
} else {
- track_dset = -1;
+ track_dset = -1; /* all datasets */
}
if(track_dset < 0) {
track_dset = find_closest_wave(i, gr);
} else {
- track_dset = -1;
+ track_dset = -1; /* all datasets */
}
}
} /* key == 't' */
- break;
- } /* for(i=0; i < xctx->rects[GRIDLAYER]; ++i) */
+ } /* if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) */
+ finish:
dbg(1, "out of 1st loop: i=%d\n", i);
/* check if user clicked on a wave label -> draw wave in bold */
@@ -789,7 +785,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
- /* second loop: after having determined the master graph do the others */
+ /* loop: after having operated on the master graph do the others */
for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
r = &xctx->rect[GRIDLAYER][i];
need_redraw = 0;
@@ -993,7 +989,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
else if(key == 't' && access_cond ) {
- if(track_dset != -2) {
+ if(track_dset != -2) { /* -2 means no dataset selection ('t' key) was started */
/*
const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
*/
From 182b55adf8c39e433faf8f95c195484e1bc0ccb8 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 01:21:05 +0100
Subject: [PATCH 08/21] fix some issues when setting numerical position of
cursors (spurious activation of `GRAPHPAN`); proc input_line: return `preset`
argument on Cancel
---
src/callback.c | 47 ++++++++---------------------------------------
src/xschem.tcl | 2 +-
2 files changed, 9 insertions(+), 40 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 22f31340..710612e4 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -553,7 +553,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
+ event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
redraw_all_at_end = 1;
}
@@ -582,7 +582,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xctx->graph_cursor2_x = cursor2;
}
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
+ event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
redraw_all_at_end = 1;
}
@@ -710,8 +710,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
} /* key == 't' */
} /* if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) */
- finish:
- dbg(1, "out of 1st loop: i=%d\n", i);
/* check if user clicked on a wave label -> draw wave in bold */
if(event == ButtonPress && button == Button3 &&
@@ -734,6 +732,8 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
dbg(1, "graph_master=%d\n", xctx->graph_master);
+ finish:
+
/* parameters for absolute positioning by mouse drag in bottom graph area */
if( xctx->raw && event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
int idx;
@@ -767,9 +767,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
pp = (xctx->mousex_snap - ddx) / ccx;
xx1 = pp - delta / 2.0;
xx2 = pp + delta / 2.0;
-
if(switched) extra_rawfile(5, NULL, NULL, -1.0, -1.0); /* switch back to previous raw file */
-
}
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) && !xctx->graph_left && !xctx->graph_top) {
/* parameters for zoom area by mouse drag */
@@ -783,8 +781,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(xx1 == xx2) xx2 += 1e-6;
}
-
-
/* loop: after having operated on the master graph do the others */
for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
r = &xctx->rect[GRIDLAYER][i];
@@ -904,6 +900,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* Numerically set hcursor position */
if(xctx->graph_flags & 128) {
double cursor;
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
cursor = gr->hcursor1_y;
if(gr->logy ) {
cursor = mylog10(cursor);
@@ -918,6 +915,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* Numerically set hcursor position */
if(xctx->graph_flags & 256) {
double cursor;
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
cursor = gr->hcursor2_y;
if(gr->logy ) {
cursor = mylog10(cursor);
@@ -1227,28 +1225,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* selected or locked or master */
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- /*
- * this calculation is done in 1st loop, only for master graph
- * and applied to all locked graphs
- int idx = get_raw_index(find_nth(get_tok_value(r->prop_ptr, "sweep", 0), ", ", "\"", 0, 1), NULL);
- int dset = dataset == -1 ? 0 : dataset;
- double wwx1, wwx2, pp, delta, ccx, ddx;
-
- if(idx < 0 ) idx = 0;
- delta = gr->gw;
- wwx1 = get_raw_value(dset, idx, 0);
- wwx2 = get_raw_value(dset, idx, xctx->raw->npoints[dset] - 1);
- if(gr->logx) {
- wwx1 = mylog10(wwx1);
- wwx2 = mylog10(wwx2);
- }
- ccx = (gr->x2 - gr->x1) / (wwx2 - wwx1);
- ddx = gr->x1 - wwx1 * ccx;
- pp = (xctx->mousex_snap - ddx) / ccx;
- xx1 = pp - delta / 2.0;
- xx2 = pp + delta / 2.0;
- */
-
+ /* xx1 and xx2 calculated for master graph above */
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
need_redraw = 1;
@@ -1269,15 +1246,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(xctx->mx_double_save != xctx->mousex_snap) {
clear_graphpan_at_end = 1;
- /*
- * this calculation is done in 1st loop above,
- * only for graph master and applied to all locked graphs
- xx1 = G_X(xctx->mx_double_save);
- xx2 = G_X(xctx->mousex_snap);
- if(xx2 < xx1) { tmp = xx1; xx1 = xx2; xx2 = tmp; }
- if(xx1 == xx2) xx2 += 1e-6;
- */
- if(xx1 == xx2) xx2 += 1e-6;
+ /* xx1 and xx2 calculated for master graph above */
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
need_redraw = 1;
diff --git a/src/xschem.tcl b/src/xschem.tcl
index f7cb1e58..98be581e 100644
--- a/src/xschem.tcl
+++ b/src/xschem.tcl
@@ -6571,7 +6571,7 @@ proc swap_compare_schematics {} {
}
proc input_line {txt {cmd {}} {preset {}} {w 12}} {
global wm_fix retval
- set retval {}
+ set retval $preset
if { [winfo exists .dialog] } {return}
xschem set semaphore [expr {[xschem get semaphore] +1}]
toplevel .dialog -class Dialog
From 12a9276ee07d91c05dbe9b31aee1e203ee6c5e2e Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 13:27:07 +0100
Subject: [PATCH 09/21] optimization in plotting routines: skip unwanted
datasets, if no dc simulation there is no need to detect sweep variable wraps
---
src/callback.c | 13 +++++++++---
src/draw.c | 21 ++++++++++++++++++
xschem_library/ngspice/autozero_comp.sch | 27 ++++++++++++++++++++++--
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 710612e4..617c5a0b 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -282,6 +282,10 @@ void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
first = -1;
prev_prev_x = prev_x = 0;
last = ofs;
+
+ /* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
+ if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
+
for(p = ofs ; p < ofs_end; p++) {
xx = gv[p];
wrap = ( cnt > 1 && XSIGN(xx - prev_x) != XSIGN(prev_x - prev_prev_x));
@@ -295,13 +299,13 @@ void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
xx, cursor2, first, last, start, end, p, wrap, sweepvar_wrap, ofs);
if(first == -1) first = p;
if(p == first) {
- if(xx == cursor2) {goto done;}
+ if(xx == cursor2) {goto found;}
s = XSIGN0(xx - cursor2);
dbg(1, "s=%d\n", s);
} else {
int ss = XSIGN0(xx - cursor2);
dbg(1, "s=%d, ss=%d\n", s, ss);
- if(ss != s) {goto done;}
+ if(ss != s) {goto found;}
}
last = p;
}
@@ -311,10 +315,13 @@ void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
prev_x = xx;
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
/* offset pointing to next dataset */
+
+ done:
+
ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
- done:
+ found:
if(first != -1) {
if(p > last) {
double sweep0, sweep1;
diff --git a/src/draw.c b/src/draw.c
index 36660d3b..31015f93 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -2514,6 +2514,9 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset)
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
ofs_end = ofs + raw->npoints[dset];
+
+ /* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
+ if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
for(p = ofs ; p < ofs_end; p++) {
if(gr->logx) xx = mylog10(gv[p]);
else xx = gv[p];
@@ -2539,6 +2542,9 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset)
++cnt;
}
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
+
+ done:
+
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
@@ -3528,6 +3534,9 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
ofs_end = ofs + raw->npoints[dset];
first = -1;
last = ofs;
+
+ /* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
+ if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
for(p = ofs ; p < ofs_end; p++) {
if(gr->logx)
xx = mylog10(gv[p]);
@@ -3560,6 +3569,9 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
idx = plot_raw_custom_data(sweep_idx, first, last, express, NULL);
}
}
+
+ done:
+
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
@@ -3984,6 +3996,10 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
* p loop split repeated 2 timed (for x and y points) to preserve cache locality */
prev_x = 0;
last = ofs;
+
+ /* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
+ if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
+
for(p = ofs ; p < ofs_end; p++) {
double xxprevious, xxfollowing;
@@ -4059,6 +4075,8 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
} /* if(xx >= start && xx <= end) */
prev_x = xx;
} /* for(p = ofs ; p < ofs + xctx->raw->npoints[dset]; p++) */
+
+
if(first != -1) {
if(dataset == -1 || dataset == sweepvar_wrap) {
/* plot graph. Bus bundles are not plotted if graph is not digital.*/
@@ -4075,6 +4093,9 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
}
}
}
+
+ done:
+
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
diff --git a/xschem_library/ngspice/autozero_comp.sch b/xschem_library/ngspice/autozero_comp.sch
index f3d4ef1f..50073e61 100644
--- a/xschem_library/ngspice/autozero_comp.sch
+++ b/xschem_library/ngspice/autozero_comp.sch
@@ -53,10 +53,12 @@ color="8 6"
linewidth_mult=1.0
hilight_wave=-1
-dataset=-1
+dataset=188
rawfile=$netlist_dir/autozero_comp.raw
sim_type=tran
-rainbow=0}
+rainbow=0
+hcursor1_y=0.13350312
+hcursor2_y=0.58853305}
B 2 270 -1160 680 -1030 {flags=graph,unlocked
y1 = 0.647319
y2 = 0.652563
@@ -135,6 +137,27 @@ saout
sweep="freq0 freq1 freq0"
mode=HistoH
xlabmag=2.0}
+B 2 270 -1610 680 -1450 {flags=graph,unlocked
+y1 = 0
+y2 = 0.9
+divy = 5
+x1=1.9099218e-07
+x2=3.4920522e-07
+divx=5
+subdivx=4
+unitx=n
+node="zero0
+zero1
+zero2"
+color="12 4 7"
+
+linewidth_mult=0.1
+hilight_wave=-1
+
+rawfile=$netlist_dir/autozero_comp.raw
+sim_type=tran
+rainbow=0
+dataset=235}
T {CAL} 140 -180 0 1 0.4 0.4 {}
T {EN} 140 -130 0 1 0.4 0.4 {}
T {CALIBRATION
From 0d7d1f5364c784cd425e545a19f9a4740b420a73 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 15:05:11 +0100
Subject: [PATCH 10/21] implemented drag with right-button pressed on left of Y
axis to do a Y area zoom
---
src/callback.c | 44 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 38 insertions(+), 6 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 617c5a0b..1ad7016d 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -374,7 +374,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
Graph_ctx *gr;
int rstate; /* reduced state wit ShiftMask bit filtered out */
int graph_use_ctrl_key = tclgetboolvar("graph_use_ctrl_key");
- int i, redraw_all_at_end = 0, need_all_redraw = 0, need_redraw = 0, dataset = 0;
+ int i, redraw_all_at_end = 0, need_all_redraw = 0, need_redraw = 0, need_redraw_master = 0, dataset = 0;
double xx1 = 0.0, xx2 = 0.0, yy1, yy2;
double delta_threshold = 0.25;
double zoom_m = 0.5;
@@ -558,8 +558,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
xctx->graph_cursor1_x = cursor1;
}
-
-
event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
redraw_all_at_end = 1;
@@ -588,7 +586,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
xctx->graph_cursor2_x = cursor2;
}
-
event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
redraw_all_at_end = 1;
@@ -1245,7 +1242,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xctx->ui_state &= ~GRAPHPAN;
xctx->graph_flags &= ~(16 | 32 | 512 | 1024); /* clear move cursor flags */
}
- /* zoom area by mouse drag */
+ /* zoom X area by mouse drag */
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) &&
!xctx->graph_left && !xctx->graph_top) {
/* selected or locked or master */
@@ -1262,8 +1259,43 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
+ /* zoom Y area by mouse drag */
+ else if(button == Button3 && (xctx->ui_state & GRAPHPAN) &&
+ xctx->graph_left && !xctx->graph_top) {
+ /* Only on master */
+ if(i == xctx->graph_master) {
+ if(xctx->my_double_save != xctx->mousey_snap) {
+ double yy1, yy2;
+ clear_graphpan_at_end = 1;
+ if(!gr->digital) {
+ yy1 = G_Y(xctx->my_double_save);
+ yy2 = G_Y(xctx->mousey_snap);
+ if(state & ShiftMask) {
+ if(yy1 < yy2) { double tmp; tmp = yy1; yy1 = yy2; yy2 = tmp; }
+ } else {
+ if(yy2 < yy1) { double tmp; tmp = yy1; yy1 = yy2; yy2 = tmp; }
+ }
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ } else {
+ yy1 = DG_Y(xctx->my_double_save);
+ yy2 = DG_Y(xctx->mousey_snap);
+ if(state & ShiftMask) {
+ if(yy1 < yy2) { double tmp; tmp = yy1; yy1 = yy2; yy2 = tmp; }
+ } else {
+ if(yy2 < yy1) { double tmp; tmp = yy1; yy1 = yy2; yy2 = tmp; }
+ }
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
+ }
+ need_redraw = 1;
+ } else if(i == xctx->graph_master) {
+ clear_graphpan_at_end = 1;
+ }
+ }
+ }
} /* else if( event == ButtonRelease) */
- if(need_redraw || need_all_redraw) {
+ if(need_redraw || need_all_redraw || ( i == xctx->graph_master && need_redraw_master) ) {
setup_graph_data(i, 0, gr);
draw_graph(i, 1 + 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), gr, NULL); /* draw data in each graph box */
}
From e6e135049b885385020f547789b056058d385170 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 15:31:00 +0100
Subject: [PATCH 11/21] update docs on graphs y-zoom
---
doc/xschem_man/graphs.html | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/xschem_man/graphs.html b/doc/xschem_man/graphs.html
index df60995d..2fc8660f 100644
--- a/doc/xschem_man/graphs.html
+++ b/doc/xschem_man/graphs.html
@@ -113,6 +113,8 @@ p{padding: 15px 30px 10px;}
configuration dialog box, where you can change many graph parameters.
- Pressing the right mouse button in the graph area and dragging some distance in the X direction
will zoom in the waveforms to that X range.
+ - Pressing the right mouse button to the left of the Y axis and dragging some distance in the Y direction
+ will zoom in the waveforms to that Y range.

From bbdfd3c61a62837038bef3c649c7271937c242f8 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 16:36:45 +0100
Subject: [PATCH 12/21] refactoring and cleanup of wave_callback()
---
src/callback.c | 334 ++++++++++++++++++++++++++-----------------------
1 file changed, 178 insertions(+), 156 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 1ad7016d..c0def1e7 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -374,7 +374,8 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
Graph_ctx *gr;
int rstate; /* reduced state wit ShiftMask bit filtered out */
int graph_use_ctrl_key = tclgetboolvar("graph_use_ctrl_key");
- int i, redraw_all_at_end = 0, need_all_redraw = 0, need_redraw = 0, need_redraw_master = 0, dataset = 0;
+ int i, dataset = 0;
+ int need_fullredraw = 0, need_all_redraw = 0, need_redraw = 0, need_redraw_master = 0;
double xx1 = 0.0, xx2 = 0.0, yy1, yy2;
double delta_threshold = 0.25;
double zoom_m = 0.5;
@@ -408,6 +409,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
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)));
+ need_redraw_master = 1;
}
/* move hcursor2 */
@@ -417,6 +419,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
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)));
+ need_redraw_master = 1;
}
/* move cursor1 */
@@ -431,6 +434,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
xctx->graph_cursor1_x = c;
}
+ need_all_redraw = 1;
}
/* move cursor2 */
/* set cursor position from master graph x-axis */
@@ -448,7 +452,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(tclgetboolvar("live_cursor2_backannotate")) {
backannotate_at_cursor_b_pos(r, gr);
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
+ } else {
+ need_all_redraw = 1;
}
}
gr->master_gx1 = gr->gx1;
@@ -558,9 +564,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
xctx->graph_cursor1_x = cursor1;
}
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
+ event = 0; button = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
}
/* Numerically set cursor position */
if(xctx->graph_flags & 4) {
@@ -586,9 +592,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} else {
xctx->graph_cursor2_x = cursor2;
}
- event = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
+ event = 0; button = 0; /* avoid further processing ButtonPress that might set GRAPHPAN */
}
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
}
}
else if(event == -3 && button == Button1) {
@@ -632,7 +638,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(tclgetboolvar("live_cursor2_backannotate")) {
backannotate_at_cursor_b_pos(r, gr);
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
} else {
need_all_redraw = 1;
}
@@ -640,7 +646,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xctx->raw->annot_p = -1;
xctx->raw->annot_sweep_idx = -1;
/* need_all_redraw = 1; */
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
}
}
/* swap cursors */
@@ -687,7 +693,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(tclgetboolvar("live_cursor2_backannotate")) {
backannotate_at_cursor_b_pos(r, gr);
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
+ need_fullredraw = 1;
}
else need_all_redraw = 1;
}
@@ -836,27 +842,23 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} /* if(xctx->graph_flags & 64) */
} /* if(i == xctx->graph_master) */
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)) {
- 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 */
- else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) {
- if(tclgetboolvar("live_cursor2_backannotate")) {
- redraw_all_at_end = 1;
- }
- else need_redraw = 1;
- }
- else /* drag waves with mouse */
+
+
+
+
+
+
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
!(xctx->graph_flags & (16 | 32 | 512 | 1024))) {
double delta;
+ /* vertical move of waveforms */
if(xctx->graph_left) {
if(i == xctx->graph_master) {
if(gr->digital) {
@@ -883,7 +885,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
- } else {
+ }
+ /* horizontal move of waveforms */
+ else {
save_mouse_at_end = 1;
delta = gr->gw;
delta_threshold = 0.01;
@@ -932,8 +936,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
need_redraw = 1;
}
}
- else if((button == Button5 && !(state & ShiftMask))) {
+ else if(event == ButtonPress && button == Button5 && !(state & ShiftMask)) {
double delta;
+ /* vertical move of waveforms with mouse wheel */
if(xctx->graph_left) {
if(i == xctx->graph_master) {
if(gr->digital) {
@@ -953,7 +958,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
need_redraw = 1;
}
}
- } else {
+ }
+ /* horizontal move of waveforms with mouse wheel */
+ else {
/* selected or locked or master */
if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
delta = gr->gw;
@@ -966,86 +973,9 @@ 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) { /* -2 means no dataset selection ('t' key) was started */
- /*
- const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
- */
- int unlocked = r->flags & 2;
- int floaters = there_are_floaters();
- if(i == xctx->graph_master || !unlocked) {
- gr->dataset = track_dset;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(track_dset)));
-
- }
- /* do this here to update texts printing current dataset in graph
- * tcleval([xschem getprop rect 2 n dataset]) */
- if(i == xctx->graph_master && floaters) {
- set_modify(-2); /* update floater caches to reflect actual backannotation */
- redraw_all_at_end = 1;
- }
- if((xctx->graph_flags & 4) && tclgetboolvar("live_cursor2_backannotate")) {
- if(i == xctx->graph_master) {
- backannotate_at_cursor_b_pos(r, gr);
- }
- redraw_all_at_end = 1;
- } else {
- if(!redraw_all_at_end) need_redraw = 1;
- }
-
- }
- } /* key == 't' */
- else if(key == XK_Left) {
- double delta;
- if(xctx->graph_left) {
- if(!gr->digital && i == xctx->graph_master) {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = gr->gh;
- double var = delta * 0.2;
- yy2 = gr->gy2 + var * b / delta;
- yy1 = gr->gy1 - var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- need_redraw = 1;
- }
- } else {
- delta = gr->gw;
- delta_threshold = 0.05;
- xx1 = gr->gx1 - delta * delta_threshold;
- xx2 = gr->gx2 - delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- else if(button == Button4 && !(state & ShiftMask)) {
+ else if(event == ButtonPress && button == Button4 && !(state & ShiftMask)) {
double delta;
+ /* vertical move of waveforms with mouse wheel */
if(xctx->graph_left) {
if(i == xctx->graph_master) {
if(gr->digital) {
@@ -1065,7 +995,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
need_redraw = 1;
}
}
- } else {
+ }
+ /* horizontal move of waveforms with mouse wheel */
+ else {
/* selected or locked or master */
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
delta = gr->gw;
@@ -1078,32 +1010,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
- else if(key == XK_Right) {
- double delta;
- if(xctx->graph_left) {
- if(!gr->digital && i == xctx->graph_master) {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = gr->gh;
- double var = delta * 0.2;
- yy2 = gr->gy2 - var * b / delta;
- yy1 = gr->gy1 + var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- need_redraw = 1;
- }
- } else {
- delta = gr->gw;
- delta_threshold = 0.05;
- xx1 = gr->gx1 + delta * delta_threshold;
- xx2 = gr->gx2 + delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- else if(button == Button5 && (state & ShiftMask)) {
+ else if(event == ButtonPress && button == Button5 && (state & ShiftMask)) {
if(xctx->graph_left) {
if(i == xctx->graph_master) {
if(gr->digital) {
@@ -1143,20 +1050,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
- else if(key == XK_Down) {
- if(!xctx->graph_left) {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- double var = 0.2 * gr->gw;
- xx2 = gr->gx2 + var * (1 - zoom_m);
- xx1 = gr->gx1 - var * zoom_m;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- else if(button == Button4 && (state & ShiftMask)) {
+ else if(event == ButtonPress && button == Button4 && (state & ShiftMask)) {
if(xctx->graph_left) {
if(i == xctx->graph_master) {
if(gr->digital) {
@@ -1195,7 +1089,123 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
- else if(key == XK_Up) {
+ /* y hcursor1 toggle */
+ else if(event == KeyPress && 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(event == KeyPress && 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(event == KeyPress && key == 't' && access_cond ) {
+ if(track_dset != -2) { /* -2 means no dataset selection ('t' key) was started */
+ /*
+ const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
+ */
+ int unlocked = r->flags & 2;
+ int floaters = there_are_floaters();
+ if(i == xctx->graph_master || !unlocked) {
+ gr->dataset = track_dset;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(track_dset)));
+
+ }
+ /* do this here to update texts printing current dataset in graph
+ * tcleval([xschem getprop rect 2 n dataset]) */
+ if(i == xctx->graph_master && floaters) {
+ set_modify(-2); /* update floater caches to reflect actual backannotation */
+ need_fullredraw = 1;
+ }
+ if((xctx->graph_flags & 4) && tclgetboolvar("live_cursor2_backannotate")) {
+ if(i == xctx->graph_master) {
+ backannotate_at_cursor_b_pos(r, gr);
+ }
+ need_fullredraw = 1;
+ } else {
+ if(!need_fullredraw) need_redraw = 1;
+ }
+
+ }
+ } /* key == 't' */
+ else if(event == KeyPress && key == XK_Left) {
+ double delta;
+ if(xctx->graph_left) {
+ if(!gr->digital && i == xctx->graph_master) {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = gr->gh;
+ double var = delta * 0.2;
+ yy2 = gr->gy2 + var * b / delta;
+ yy1 = gr->gy1 - var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ need_redraw = 1;
+ }
+ } else {
+ delta = gr->gw;
+ delta_threshold = 0.05;
+ xx1 = gr->gx1 - delta * delta_threshold;
+ xx2 = gr->gx2 - delta * delta_threshold;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ else if(event == KeyPress && key == XK_Right) {
+ double delta;
+ if(xctx->graph_left) {
+ if(!gr->digital && i == xctx->graph_master) {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = gr->gh;
+ double var = delta * 0.2;
+ yy2 = gr->gy2 - var * b / delta;
+ yy1 = gr->gy1 + var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ need_redraw = 1;
+ }
+ } else {
+ delta = gr->gw;
+ delta_threshold = 0.05;
+ xx1 = gr->gx1 + delta * delta_threshold;
+ xx2 = gr->gx2 + delta * delta_threshold;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ else if(event == KeyPress && key == XK_Down) {
+ if(!xctx->graph_left) {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ double var = 0.2 * gr->gw;
+ xx2 = gr->gx2 + var * (1 - zoom_m);
+ xx1 = gr->gx1 - var * zoom_m;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ }
+ else if(event == KeyPress && key == XK_Up) {
if(!xctx->graph_left) {
/* selected or locked or master */
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
@@ -1208,7 +1218,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
- else if(key == 'f' && access_cond) {
+ else if(event == KeyPress && key == 'f' && access_cond) {
if(xctx->raw && xctx->raw->values) {
if(xctx->graph_left) { /* full Y zoom*/
if(i == xctx->graph_master) {
@@ -1223,8 +1233,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} /* raw->values */
} /* key == 'f' */
/* absolute positioning by mouse drag in bottom graph area */
- else if( event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
-
+ else if(event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
if(xctx->raw && xctx->raw->values) {
/* selected or locked or master */
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
@@ -1236,8 +1245,21 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
}
}
+
+
+
+
+
+
} /* if( event == KeyPress || event == ButtonPress || event == MotionNotify ) */
- else if( event == ButtonRelease) {
+
+
+
+
+
+
+
+ else if(event == ButtonRelease) {
if(button != Button3) {
xctx->ui_state &= ~GRAPHPAN;
xctx->graph_flags &= ~(16 | 32 | 512 | 1024); /* clear move cursor flags */
@@ -1301,9 +1323,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
} /* for(i=0; i< xctx->rects[GRIDLAYER]; i++ */
- if(redraw_all_at_end ==1) {
+ if(need_fullredraw ==1) {
draw();
- redraw_all_at_end = 0;
+ need_fullredraw = 0;
}
if(clear_graphpan_at_end) xctx->ui_state &= ~GRAPHPAN;
/* update saved mouse position after processing all graphs */
From d1e2328eb370092b3ec1b1dc05ab718a1b4dd83a Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 21:12:59 +0100
Subject: [PATCH 13/21] refactoring and cleanup of wave_callback() -2-
---
src/callback.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index c0def1e7..227c9d30 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -729,10 +729,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
/* save mouse position when doing pan operations */
else if(
- (
- (event == ButtonPress && (button == Button1 || button == Button3)) ||
- (event == MotionNotify && (state & (Button1Mask | Button3Mask)))
- ) &&
+ ( event == ButtonPress && (button == Button1 || button == Button3)) &&
!(xctx->ui_state & GRAPHPAN) &&
!xctx->graph_top /* && !xctx->graph_bottom */
) {
From 444eb47eb53a47dae5fd5c9af71fbe562b838e85 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Wed, 8 Jan 2025 22:19:58 +0100
Subject: [PATCH 14/21] refactoring and cleanup of wave_callback() -3-
---
src/callback.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 227c9d30..da57f25d 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -400,8 +400,12 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) {
/* check if this is the master graph (the one containing the mouse pointer) */
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
- dbg(1, "mouse inside: %d mousex=%g\n", i, xctx->mousex);
setup_graph_data(i, 0, gr);
+
+ gr->master_gx1 = gr->gx1;
+ gr->master_gx2 = gr->gx2;
+ gr->master_gw = gr->gw;
+ gr->master_cx = gr->cx;
/* move hcursor1 */
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 512 )) {
double c;
@@ -457,10 +461,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
need_all_redraw = 1;
}
}
- gr->master_gx1 = gr->gx1;
- gr->master_gx2 = gr->gx2;
- gr->master_gw = gr->gw;
- gr->master_cx = gr->cx;
if(xctx->ui_state & GRAPHPAN) goto finish; /* After GRAPHPAN only need to check Motion events for cursors */
if(xctx->mousey_snap < W_Y(gr->gy2)) {
xctx->graph_top = 1;
From 45a0af8005038d28ea0afc7c27d7ef531b7c9152 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 00:11:04 +0100
Subject: [PATCH 15/21] fix unwanted clear of GRAPHPAN bit in button3
operations in wave_callback()
---
src/callback.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index da57f25d..daab52a2 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -384,9 +384,10 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xRect *r = NULL;
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
+ dbg(0, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
if(event != -3 && !xctx->raw) return 0;
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
- rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sifficient */
+ rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
#if HAS_CAIRO==1
cairo_save(xctx->cairo_ctx);
cairo_save(xctx->cairo_save_ctx);
@@ -905,12 +906,12 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* Numerically set hcursor position */
if(xctx->graph_flags & 128) {
double cursor;
- xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
cursor = gr->hcursor1_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
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)));
@@ -920,12 +921,12 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* Numerically set hcursor position */
if(xctx->graph_flags & 256) {
double cursor;
- xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
cursor = gr->hcursor2_y;
if(gr->logy ) {
cursor = mylog10(cursor);
}
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
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)));
From ed9dc9b2119b80b77ad586f17bacd00071f36076 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 00:12:07 +0100
Subject: [PATCH 16/21] disable debug msg
---
src/callback.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/callback.c b/src/callback.c
index daab52a2..35c9d4ff 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -384,7 +384,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xRect *r = NULL;
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
- dbg(0, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
+ dbg(1, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
if(event != -3 && !xctx->raw) return 0;
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
From 7d7b381b7b20e8f816a61c1017fd0811c3d0d291 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 00:17:55 +0100
Subject: [PATCH 17/21] refactoring and cleanup of wave_callback() -4-
---
src/callback.c | 717 ++++++++++++++++++++++++-------------------------
1 file changed, 347 insertions(+), 370 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 35c9d4ff..1bce118c 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -842,345 +842,151 @@ 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 ) {
-
-
-
-
-
-
- if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
- !(xctx->graph_flags & (16 | 32 | 512 | 1024))) {
- double delta;
- /* vertical move of waveforms */
- if(xctx->graph_left) {
- if(i == xctx->graph_master) {
- if(gr->digital) {
- delta = gr->posh;
- delta_threshold = 0.01;
- if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->dcy * delta) * delta_threshold) {
- yy1 = gr->ypos1 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
- yy2 = gr->ypos2 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
- xctx->my_double_save = xctx->mousey_snap;
- need_redraw = 1;
- }
- } else {
- delta = gr->gh / gr->divy;
- delta_threshold = 0.01;
- if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->cy * delta) * delta_threshold) {
- yy1 = gr->gy1 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
- yy2 = gr->gy2 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- xctx->my_double_save = xctx->mousey_snap;
- need_redraw = 1;
- }
- }
- }
- }
- /* horizontal move of waveforms */
- else {
- save_mouse_at_end = 1;
- delta = gr->gw;
- delta_threshold = 0.01;
- /* selected or locked or master */
- if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- dbg(1, "moving waves: %d\n", i);
- if(fabs(xctx->mx_double_save - xctx->mousex_snap) > fabs(gr->cx * delta) * delta_threshold) {
- xx1 = gr->gx1 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
- xx2 = gr->gx2 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- }
- 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) {
- xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
- 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) {
- xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
- 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(event == ButtonPress && button == Button5 && !(state & ShiftMask)) {
- double delta;
- /* vertical move of waveforms with mouse wheel */
- if(xctx->graph_left) {
- if(i == xctx->graph_master) {
- if(gr->digital) {
- delta = gr->posh * 0.05;
- yy1 = gr->ypos1 + delta;
- yy2 = gr->ypos2 + delta;
+ if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
+ !(xctx->graph_flags & (16 | 32 | 512 | 1024))) {
+ double delta;
+ /* vertical move of waveforms */
+ if(xctx->graph_left) {
+ if(i == xctx->graph_master) {
+ if(gr->digital) {
+ delta = gr->posh;
+ delta_threshold = 0.01;
+ if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->dcy * delta) * delta_threshold) {
+ yy1 = gr->ypos1 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
+ yy2 = gr->ypos2 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
- need_redraw = 1;
- } else {
- delta = gr->gh/ gr->divy;
- delta_threshold = 1.0;
- yy1 = gr->gy1 + delta * delta_threshold;
- yy2 = gr->gy2 + delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ xctx->my_double_save = xctx->mousey_snap;
need_redraw = 1;
}
- }
- }
- /* horizontal move of waveforms with mouse wheel */
- else {
- /* selected or locked or master */
- if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- delta = gr->gw;
- delta_threshold = 0.05;
- xx1 = gr->gx1 - delta * delta_threshold;
- xx2 =gr->gx2 - delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- else if(event == ButtonPress && button == Button4 && !(state & ShiftMask)) {
- double delta;
- /* vertical move of waveforms with mouse wheel */
- if(xctx->graph_left) {
- if(i == xctx->graph_master) {
- if(gr->digital) {
- delta = gr->posh * 0.05;
- yy1 = gr->ypos1 - delta;
- yy2 = gr->ypos2 - delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
- need_redraw = 1;
- } else {
- delta = gr->gh / gr->divy;
- delta_threshold = 1.0;
- yy1 = gr->gy1 - delta * delta_threshold;
- yy2 = gr->gy2 - delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- need_redraw = 1;
- }
- }
- }
- /* horizontal move of waveforms with mouse wheel */
- else {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- delta = gr->gw;
- delta_threshold = 0.05;
- xx1 = gr->gx1 + delta * delta_threshold;
- xx2 = gr->gx2 + delta * delta_threshold;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- else if(event == ButtonPress && button == Button5 && (state & ShiftMask)) {
- if(xctx->graph_left) {
- if(i == xctx->graph_master) {
- if(gr->digital) {
- double m = DG_Y(xctx->mousey);
- double a = m - gr->ypos1;
- double b = gr->ypos2 -m;
- double delta = gr->posh;
- double var = delta * 0.05;
- yy2 = gr->ypos2 + var * b / delta;
- yy1 = gr->ypos1 - var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
- need_redraw = 1;
-
- } else {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = (gr->gy2 - gr->gy1);
- double var = delta * 0.2;
- yy2 = gr->gy2 + var * b / delta;
- yy1 = gr->gy1 - var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- need_redraw = 1;
- }
- }
- } else {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- double var = 0.2 * gr->gw;
- xx2 = gr->gx2 + var * (1 - zoom_m);
- xx1 = gr->gx1 - var * zoom_m;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- else if(event == ButtonPress && button == Button4 && (state & ShiftMask)) {
- if(xctx->graph_left) {
- if(i == xctx->graph_master) {
- if(gr->digital) {
- double m = DG_Y(xctx->mousey);
- double a = m - gr->ypos1;
- double b = gr->ypos2 -m;
- double delta = (gr->ypos2 - gr->ypos1);
- double var = delta * 0.05;
- yy2 = gr->ypos2 - var * b / delta;
- yy1 = gr->ypos1 + var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
- need_redraw = 1;
- } else {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = (gr->gy2 - gr->gy1);
- double var = delta * 0.2;
- yy2 = gr->gy2 - var * b / delta;
- yy1 = gr->gy1 + var * a / delta;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
- need_redraw = 1;
- }
- }
- } else {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- double var = 0.2 * gr->gw;
- xx2 = gr->gx2 - var * (1 - zoom_m);
- xx1 = gr->gx1 + var * zoom_m;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
- }
- }
- /* y hcursor1 toggle */
- else if(event == KeyPress && 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(event == KeyPress && 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(event == KeyPress && key == 't' && access_cond ) {
- if(track_dset != -2) { /* -2 means no dataset selection ('t' key) was started */
- /*
- const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
- */
- int unlocked = r->flags & 2;
- int floaters = there_are_floaters();
- if(i == xctx->graph_master || !unlocked) {
- gr->dataset = track_dset;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(track_dset)));
-
- }
- /* do this here to update texts printing current dataset in graph
- * tcleval([xschem getprop rect 2 n dataset]) */
- if(i == xctx->graph_master && floaters) {
- set_modify(-2); /* update floater caches to reflect actual backannotation */
- need_fullredraw = 1;
- }
- if((xctx->graph_flags & 4) && tclgetboolvar("live_cursor2_backannotate")) {
- if(i == xctx->graph_master) {
- backannotate_at_cursor_b_pos(r, gr);
- }
- need_fullredraw = 1;
} else {
- if(!need_fullredraw) need_redraw = 1;
+ delta = gr->gh / gr->divy;
+ delta_threshold = 0.01;
+ if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->cy * delta) * delta_threshold) {
+ yy1 = gr->gy1 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
+ yy2 = gr->gy2 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ xctx->my_double_save = xctx->mousey_snap;
+ need_redraw = 1;
+ }
}
-
}
- } /* key == 't' */
- else if(event == KeyPress && key == XK_Left) {
- double delta;
- if(xctx->graph_left) {
- if(!gr->digital && i == xctx->graph_master) {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = gr->gh;
- double var = delta * 0.2;
- yy2 = gr->gy2 + var * b / delta;
- yy1 = gr->gy1 - var * a / delta;
+ }
+ /* horizontal move of waveforms */
+ else {
+ save_mouse_at_end = 1;
+ delta = gr->gw;
+ delta_threshold = 0.01;
+ /* selected or locked or master */
+ if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ dbg(1, "moving waves: %d\n", i);
+ if(fabs(xctx->mx_double_save - xctx->mousex_snap) > fabs(gr->cx * delta) * delta_threshold) {
+ xx1 = gr->gx1 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
+ xx2 = gr->gx2 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ }
+ }
+ 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) {
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
+ 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) {
+ xctx->ui_state &= ~GRAPHPAN; /* we are setting a cursor so clear GRAPHPAN set before */
+ 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(event == ButtonPress && button == Button5 && !(state & ShiftMask)) {
+ double delta;
+ /* vertical move of waveforms with mouse wheel */
+ if(xctx->graph_left) {
+ if(i == xctx->graph_master) {
+ if(gr->digital) {
+ delta = gr->posh * 0.05;
+ yy1 = gr->ypos1 + delta;
+ yy2 = gr->ypos2 + delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
+ need_redraw = 1;
+ } else {
+ delta = gr->gh/ gr->divy;
+ delta_threshold = 1.0;
+ yy1 = gr->gy1 + delta * delta_threshold;
+ yy2 = gr->gy2 + delta * delta_threshold;
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
need_redraw = 1;
}
- } else {
+ }
+ }
+ /* horizontal move of waveforms with mouse wheel */
+ else {
+ /* selected or locked or master */
+ if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
delta = gr->gw;
delta_threshold = 0.05;
xx1 = gr->gx1 - delta * delta_threshold;
- xx2 = gr->gx2 - delta * delta_threshold;
+ xx2 =gr->gx2 - delta * delta_threshold;
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
need_redraw = 1;
}
}
- else if(event == KeyPress && key == XK_Right) {
- double delta;
- if(xctx->graph_left) {
- if(!gr->digital && i == xctx->graph_master) {
- double m = G_Y(xctx->mousey);
- double a = m - gr->gy1;
- double b = gr->gy2 -m;
- double delta = gr->gh;
- double var = delta * 0.2;
- yy2 = gr->gy2 - var * b / delta;
- yy1 = gr->gy1 + var * a / delta;
+ }
+ else if(event == ButtonPress && button == Button4 && !(state & ShiftMask)) {
+ double delta;
+ /* vertical move of waveforms with mouse wheel */
+ if(xctx->graph_left) {
+ if(i == xctx->graph_master) {
+ if(gr->digital) {
+ delta = gr->posh * 0.05;
+ yy1 = gr->ypos1 - delta;
+ yy2 = gr->ypos2 - delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
+ need_redraw = 1;
+ } else {
+ delta = gr->gh / gr->divy;
+ delta_threshold = 1.0;
+ yy1 = gr->gy1 - delta * delta_threshold;
+ yy2 = gr->gy2 - delta * delta_threshold;
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
need_redraw = 1;
}
- } else {
+ }
+ }
+ /* horizontal move of waveforms with mouse wheel */
+ else {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
delta = gr->gw;
delta_threshold = 0.05;
xx1 = gr->gx1 + delta * delta_threshold;
@@ -1190,71 +996,242 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
need_redraw = 1;
}
}
- else if(event == KeyPress && key == XK_Down) {
- if(!xctx->graph_left) {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- double var = 0.2 * gr->gw;
- xx2 = gr->gx2 + var * (1 - zoom_m);
- xx1 = gr->gx1 - var * zoom_m;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ }
+ else if(event == ButtonPress && button == Button5 && (state & ShiftMask)) {
+ if(xctx->graph_left) {
+ if(i == xctx->graph_master) {
+ if(gr->digital) {
+ double m = DG_Y(xctx->mousey);
+ double a = m - gr->ypos1;
+ double b = gr->ypos2 -m;
+ double delta = gr->posh;
+ double var = delta * 0.05;
+ yy2 = gr->ypos2 + var * b / delta;
+ yy1 = gr->ypos1 - var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
+ need_redraw = 1;
+
+ } else {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = (gr->gy2 - gr->gy1);
+ double var = delta * 0.2;
+ yy2 = gr->gy2 + var * b / delta;
+ yy1 = gr->gy1 - var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
need_redraw = 1;
}
}
+ } else {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ double var = 0.2 * gr->gw;
+ xx2 = gr->gx2 + var * (1 - zoom_m);
+ xx1 = gr->gx1 - var * zoom_m;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
}
- else if(event == KeyPress && key == XK_Up) {
- if(!xctx->graph_left) {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- double var = 0.2 * gr->gw;
- xx2 = gr->gx2 - var * (1 - zoom_m);
- xx1 = gr->gx1 + var * zoom_m;
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ }
+ else if(event == ButtonPress && button == Button4 && (state & ShiftMask)) {
+ if(xctx->graph_left) {
+ if(i == xctx->graph_master) {
+ if(gr->digital) {
+ double m = DG_Y(xctx->mousey);
+ double a = m - gr->ypos1;
+ double b = gr->ypos2 -m;
+ double delta = (gr->ypos2 - gr->ypos1);
+ double var = delta * 0.05;
+ yy2 = gr->ypos2 - var * b / delta;
+ yy1 = gr->ypos1 + var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
+ need_redraw = 1;
+ } else {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = (gr->gy2 - gr->gy1);
+ double var = delta * 0.2;
+ yy2 = gr->gy2 - var * b / delta;
+ yy1 = gr->gy1 + var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
need_redraw = 1;
}
}
- }
- else if(event == KeyPress && key == 'f' && access_cond) {
- if(xctx->raw && xctx->raw->values) {
- if(xctx->graph_left) { /* full Y zoom*/
- if(i == xctx->graph_master) {
- need_redraw = graph_fullyzoom(r, gr, dataset);
- } /* graph_master */
- } else { /* not graph_left, full X zoom*/
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
- need_redraw = graph_fullxzoom(i, gr, dataset);
- }
- }
- } /* raw->values */
- } /* key == 'f' */
- /* absolute positioning by mouse drag in bottom graph area */
- else if(event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
- if(xctx->raw && xctx->raw->values) {
- /* selected or locked or master */
- if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
-
- /* xx1 and xx2 calculated for master graph above */
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
- my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
- need_redraw = 1;
- }
+ } else {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ double var = 0.2 * gr->gw;
+ xx2 = gr->gx2 - var * (1 - zoom_m);
+ xx1 = gr->gx1 + var * zoom_m;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
}
}
+ }
+ /* y hcursor1 toggle */
+ else if(event == KeyPress && 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(event == KeyPress && 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(event == KeyPress && key == 't' && access_cond ) {
+ if(track_dset != -2) { /* -2 means no dataset selection ('t' key) was started */
+ /*
+ const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
+ */
+ int unlocked = r->flags & 2;
+ int floaters = there_are_floaters();
+ if(i == xctx->graph_master || !unlocked) {
+ gr->dataset = track_dset;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(track_dset)));
+
+ }
+ /* do this here to update texts printing current dataset in graph
+ * tcleval([xschem getprop rect 2 n dataset]) */
+ if(i == xctx->graph_master && floaters) {
+ set_modify(-2); /* update floater caches to reflect actual backannotation */
+ need_fullredraw = 1;
+ }
+ if((xctx->graph_flags & 4) && tclgetboolvar("live_cursor2_backannotate")) {
+ if(i == xctx->graph_master) {
+ backannotate_at_cursor_b_pos(r, gr);
+ }
+ need_fullredraw = 1;
+ } else {
+ if(!need_fullredraw) need_redraw = 1;
+ }
+ }
+ } /* key == 't' */
+ else if(event == KeyPress && key == XK_Left) {
+ double delta;
+ if(xctx->graph_left) {
+ if(!gr->digital && i == xctx->graph_master) {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = gr->gh;
+ double var = delta * 0.2;
+ yy2 = gr->gy2 + var * b / delta;
+ yy1 = gr->gy1 - var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ need_redraw = 1;
+ }
+ } else {
+ delta = gr->gw;
+ delta_threshold = 0.05;
+ xx1 = gr->gx1 - delta * delta_threshold;
+ xx2 = gr->gx2 - delta * delta_threshold;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ else if(event == KeyPress && key == XK_Right) {
+ double delta;
+ if(xctx->graph_left) {
+ if(!gr->digital && i == xctx->graph_master) {
+ double m = G_Y(xctx->mousey);
+ double a = m - gr->gy1;
+ double b = gr->gy2 -m;
+ double delta = gr->gh;
+ double var = delta * 0.2;
+ yy2 = gr->gy2 - var * b / delta;
+ yy1 = gr->gy1 + var * a / delta;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
+ need_redraw = 1;
+ }
+ } else {
+ delta = gr->gw;
+ delta_threshold = 0.05;
+ xx1 = gr->gx1 + delta * delta_threshold;
+ xx2 = gr->gx2 + delta * delta_threshold;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ else if(event == KeyPress && key == XK_Down) {
+ if(!xctx->graph_left) {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ double var = 0.2 * gr->gw;
+ xx2 = gr->gx2 + var * (1 - zoom_m);
+ xx1 = gr->gx1 - var * zoom_m;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ }
+ else if(event == KeyPress && key == XK_Up) {
+ if(!xctx->graph_left) {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ double var = 0.2 * gr->gw;
+ xx2 = gr->gx2 - var * (1 - zoom_m);
+ xx1 = gr->gx1 + var * zoom_m;
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ }
+ else if(event == KeyPress && key == 'f' && access_cond) {
+ if(xctx->raw && xctx->raw->values) {
+ if(xctx->graph_left) { /* full Y zoom*/
+ if(i == xctx->graph_master) {
+ need_redraw = graph_fullyzoom(r, gr, dataset);
+ } /* graph_master */
+ } else { /* not graph_left, full X zoom*/
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
+ need_redraw = graph_fullxzoom(i, gr, dataset);
+ }
+ }
+ } /* raw->values */
+ } /* key == 'f' */
+ /* absolute positioning by mouse drag in bottom graph area */
+ else if(event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
+ if(xctx->raw && xctx->raw->values) {
+ /* selected or locked or master */
+ if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
-
-
-
-
- } /* if( event == KeyPress || event == ButtonPress || event == MotionNotify ) */
-
-
-
-
-
+ /* xx1 and xx2 calculated for master graph above */
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
+ my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
+ need_redraw = 1;
+ }
+ }
+ }
else if(event == ButtonRelease) {
From ff7c767c4d1c9b0d42b523723f2d1cca8f005504 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 00:31:11 +0100
Subject: [PATCH 18/21] propagate drawing graph Hcursor functions to SVG/PDF
exports
---
src/draw.c | 2 +-
src/psprint.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/draw.c b/src/draw.c
index 31015f93..6693b3e4 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -4803,7 +4803,7 @@ void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2,
xRect *r = &xctx->rect[GRIDLAYER][i];
if(r->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
- draw_graph(i, 8, &xctx->graph_struct, (void *)ct);
+ draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
}
#endif
diff --git a/src/psprint.c b/src/psprint.c
index 00393055..c944ec7d 100644
--- a/src/psprint.c
+++ b/src/psprint.c
@@ -341,7 +341,7 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
xRect* r2 = &xctx->rect[GRIDLAYER][i];
if (r2->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
- draw_graph(i, 8, &xctx->graph_struct, (void*)ct);
+ draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
}
#endif
From 52b9cc1ee6e3b70efea620f4189e0d5b3278af56 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 00:46:42 +0100
Subject: [PATCH 19/21] refactoring and cleanup of wave_callback() -5-
---
src/callback.c | 89 +++++++++++++++++++++++---------------------------
1 file changed, 41 insertions(+), 48 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 1bce118c..501cb9c7 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -403,6 +403,47 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
setup_graph_data(i, 0, gr);
+ /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
+ return 0;
+ }
+
+ /* destroy / show measurement widget */
+ if(xctx->graph_flags & 64) {
+ char sx[100], sy[100];
+ double xval, yval;
+ if(gr->digital) {
+ double deltag = gr->gy2 - gr->gy1;
+ double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
+ double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
+ double c = s1 * deltag;
+ deltag = deltag * s1 / s2;
+ yval=(DG_Y(xctx->mousey) - c) / s2;
+ yval=fmod(yval, deltag ) + gr->gy1;
+ if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
+ } else {
+ yval = G_Y(xctx->mousey);
+ }
+
+ xval = G_X(xctx->mousex);
+ if(gr->logx) xval = pow(10, xval);
+ if(gr->logy) yval = pow(10, yval);
+ if(gr->unitx != 1.0)
+ my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
+ else
+ my_strncpy(sx, dtoa_eng(xval), S(sx));
+
+ if(gr->unitx != 1.0)
+ my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
+ else
+ my_strncpy(sy, dtoa_eng(yval), S(sy));
+
+ tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
+ tcleval("graph_show_measure");
+ } /* if(xctx->graph_flags & 64) */
+
gr->master_gx1 = gr->gx1;
gr->master_gx2 = gr->gx2;
gr->master_gw = gr->gw;
@@ -416,7 +457,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
need_redraw_master = 1;
}
-
/* move hcursor2 */
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 1024 )) {
double c;
@@ -426,7 +466,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
need_redraw_master = 1;
}
-
/* move cursor1 */
/* set cursor position from master graph x-axis */
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
@@ -721,13 +760,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
} /* key == 't' */
} /* if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) */
-
- /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
- return 0;
- }
/* save mouse position when doing pan operations */
else if(
( event == ButtonPress && (button == Button1 || button == Button3)) &&
@@ -800,45 +832,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
setup_graph_data(i, 1, gr); /* skip flag set, no reload x1 and x2 fields */
if(gr->dataset >= 0 /* && gr->dataset < xctx->raw->datasets */) dataset =gr->dataset;
else dataset = -1;
- /* destroy / show measurement widget */
- if(i == xctx->graph_master) {
- if(xctx->graph_flags & 64) {
- if( POINTINSIDE(xctx->mousex, xctx->mousey, gr->x1, gr->y1, gr->x2, gr->y2)) {
- char sx[100], sy[100];
- double xval, yval;
- if(gr->digital) {
- double deltag = gr->gy2 - gr->gy1;
- double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
- double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
- double c = s1 * deltag;
- deltag = deltag * s1 / s2;
- yval=(DG_Y(xctx->mousey) - c) / s2;
- yval=fmod(yval, deltag ) + gr->gy1;
- if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
- } else {
- yval = G_Y(xctx->mousey);
- }
-
- xval = G_X(xctx->mousex);
- if(gr->logx) xval = pow(10, xval);
- if(gr->logy) yval = pow(10, yval);
- if(gr->unitx != 1.0)
- my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
- else
- my_strncpy(sx, dtoa_eng(xval), S(sx));
-
- if(gr->unitx != 1.0)
- my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
- else
- my_strncpy(sy, dtoa_eng(yval), S(sy));
-
- tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
- tcleval("graph_show_measure");
- } else {
- tcleval("graph_show_measure stop");
- }
- } /* if(xctx->graph_flags & 64) */
- } /* if(i == xctx->graph_master) */
dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
From cd3eaf23ea57cdc5d2c21cb8669d6c2179c95626 Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 04:11:30 +0100
Subject: [PATCH 20/21] refactoring and cleanup of wave_callback() -6-
---
src/callback.c | 96 ++++++++++++++++++++++++++++----------------------
1 file changed, 53 insertions(+), 43 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index 501cb9c7..cc62c7fb 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -39,7 +39,9 @@ static int waves_selected(int event, KeySym key, int state, int button)
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
if(xctx->ui_state & excl) skip = 1;
/* else if(event != -3 && sch_waves_loaded() < 0 ) skip = 1; */
- else if(graph_use_ctrl_key && !(state & ControlMask)) skip = 1;
+ /* allow to work on graphs even if ctrl released while in GRAPHPAN mode
+ * This is useful on touchpads with TappingDragLock enabled */
+ else if(graph_use_ctrl_key && !(state & ControlMask) && !(xctx->ui_state & GRAPHPAN)) skip = 1;
else if(SET_MODMASK) skip = 1;
else if(event == MotionNotify && (state & Button2Mask)) skip = 1;
else if(event == MotionNotify && (state & Button1Mask) && (state & ShiftMask)) skip = 1;
@@ -79,6 +81,7 @@ static int waves_selected(int event, KeySym key, int state, int button)
}
if(!is_inside) {
xctx->graph_master = -1;
+ xctx->ui_state &= ~GRAPHPAN; /* terminate ongoing GRAPHPAN to avoid deadlocks */
if(draw_xhair)
tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL);
else
@@ -384,7 +387,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xRect *r = NULL;
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
- dbg(1, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
+ dbg(0, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
if(event != -3 && !xctx->raw) return 0;
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
@@ -403,47 +406,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
setup_graph_data(i, 0, gr);
- /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
- return 0;
- }
-
- /* destroy / show measurement widget */
- if(xctx->graph_flags & 64) {
- char sx[100], sy[100];
- double xval, yval;
- if(gr->digital) {
- double deltag = gr->gy2 - gr->gy1;
- double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
- double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
- double c = s1 * deltag;
- deltag = deltag * s1 / s2;
- yval=(DG_Y(xctx->mousey) - c) / s2;
- yval=fmod(yval, deltag ) + gr->gy1;
- if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
- } else {
- yval = G_Y(xctx->mousey);
- }
-
- xval = G_X(xctx->mousex);
- if(gr->logx) xval = pow(10, xval);
- if(gr->logy) yval = pow(10, yval);
- if(gr->unitx != 1.0)
- my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
- else
- my_strncpy(sx, dtoa_eng(xval), S(sx));
-
- if(gr->unitx != 1.0)
- my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
- else
- my_strncpy(sy, dtoa_eng(yval), S(sy));
-
- tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
- tcleval("graph_show_measure");
- } /* if(xctx->graph_flags & 64) */
-
gr->master_gx1 = gr->gx1;
gr->master_gx2 = gr->gx2;
gr->master_gw = gr->gw;
@@ -457,6 +419,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
need_redraw_master = 1;
}
+
/* move hcursor2 */
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 1024 )) {
double c;
@@ -466,6 +429,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
need_redraw_master = 1;
}
+
/* move cursor1 */
/* set cursor position from master graph x-axis */
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
@@ -760,6 +724,13 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
}
} /* key == 't' */
} /* if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) */
+
+ /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
+ return 0;
+ }
/* save mouse position when doing pan operations */
else if(
( event == ButtonPress && (button == Button1 || button == Button3)) &&
@@ -832,6 +803,45 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
setup_graph_data(i, 1, gr); /* skip flag set, no reload x1 and x2 fields */
if(gr->dataset >= 0 /* && gr->dataset < xctx->raw->datasets */) dataset =gr->dataset;
else dataset = -1;
+ /* destroy / show measurement widget */
+ if(i == xctx->graph_master) {
+ if(xctx->graph_flags & 64) {
+ if( POINTINSIDE(xctx->mousex, xctx->mousey, gr->x1, gr->y1, gr->x2, gr->y2)) {
+ char sx[100], sy[100];
+ double xval, yval;
+ if(gr->digital) {
+ double deltag = gr->gy2 - gr->gy1;
+ double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
+ double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
+ double c = s1 * deltag;
+ deltag = deltag * s1 / s2;
+ yval=(DG_Y(xctx->mousey) - c) / s2;
+ yval=fmod(yval, deltag ) + gr->gy1;
+ if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
+ } else {
+ yval = G_Y(xctx->mousey);
+ }
+
+ xval = G_X(xctx->mousex);
+ if(gr->logx) xval = pow(10, xval);
+ if(gr->logy) yval = pow(10, yval);
+ if(gr->unitx != 1.0)
+ my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
+ else
+ my_strncpy(sx, dtoa_eng(xval), S(sx));
+
+ if(gr->unitx != 1.0)
+ my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
+ else
+ my_strncpy(sy, dtoa_eng(yval), S(sy));
+
+ tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
+ tcleval("graph_show_measure");
+ } else {
+ tcleval("graph_show_measure stop");
+ }
+ } /* if(xctx->graph_flags & 64) */
+ } /* if(i == xctx->graph_master) */
dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
From c6a4e8b942ff756016f782af5df96908e735977a Mon Sep 17 00:00:00 2001
From: stefan schippers
Date: Thu, 9 Jan 2025 04:23:23 +0100
Subject: [PATCH 21/21] refactoring and cleanup of wave_callback() -7-
---
src/callback.c | 102 +++++++++++++++++++++++++------------------------
1 file changed, 53 insertions(+), 49 deletions(-)
diff --git a/src/callback.c b/src/callback.c
index cc62c7fb..1835e307 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -387,7 +387,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
xRect *r = NULL;
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
- dbg(0, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
+ dbg(1, "uistate=%d, graph_flags=%d\n", xctx->ui_state, xctx->graph_flags);
if(event != -3 && !xctx->raw) return 0;
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sufficient */
@@ -406,6 +406,57 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
setup_graph_data(i, 0, gr);
+
+
+
+
+ /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
+ return 0;
+ }
+
+ /* destroy / show measurement widget */
+ if(xctx->graph_flags & 64) {
+ char sx[100], sy[100];
+ double xval, yval;
+ if(gr->digital) {
+ double deltag = gr->gy2 - gr->gy1;
+ double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
+ double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
+ double c = s1 * deltag;
+ deltag = deltag * s1 / s2;
+ yval=(DG_Y(xctx->mousey) - c) / s2;
+ yval=fmod(yval, deltag ) + gr->gy1;
+ if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
+ } else {
+ yval = G_Y(xctx->mousey);
+ }
+
+ xval = G_X(xctx->mousex);
+ if(gr->logx) xval = pow(10, xval);
+ if(gr->logy) yval = pow(10, yval);
+ if(gr->unitx != 1.0)
+ my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
+ else
+ my_strncpy(sx, dtoa_eng(xval), S(sx));
+
+ if(gr->unitx != 1.0)
+ my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
+ else
+ my_strncpy(sy, dtoa_eng(yval), S(sy));
+
+ tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
+ tcleval("graph_show_measure");
+ } /* if(xctx->graph_flags & 64) */
+
+
+
+
+
+
+
gr->master_gx1 = gr->gx1;
gr->master_gx2 = gr->gx2;
gr->master_gw = gr->gw;
@@ -725,14 +776,8 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
} /* key == 't' */
} /* if((i = xctx->graph_master) >= 0 && ((r = &xctx->rect[GRIDLAYER][i])->flags & 1)) */
- /* 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 & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
- return 0;
- }
/* save mouse position when doing pan operations */
- else if(
+ if(
( event == ButtonPress && (button == Button1 || button == Button3)) &&
!(xctx->ui_state & GRAPHPAN) &&
!xctx->graph_top /* && !xctx->graph_bottom */
@@ -803,47 +848,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
setup_graph_data(i, 1, gr); /* skip flag set, no reload x1 and x2 fields */
if(gr->dataset >= 0 /* && gr->dataset < xctx->raw->datasets */) dataset =gr->dataset;
else dataset = -1;
- /* destroy / show measurement widget */
- if(i == xctx->graph_master) {
- if(xctx->graph_flags & 64) {
- if( POINTINSIDE(xctx->mousex, xctx->mousey, gr->x1, gr->y1, gr->x2, gr->y2)) {
- char sx[100], sy[100];
- double xval, yval;
- if(gr->digital) {
- double deltag = gr->gy2 - gr->gy1;
- double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
- double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
- double c = s1 * deltag;
- deltag = deltag * s1 / s2;
- yval=(DG_Y(xctx->mousey) - c) / s2;
- yval=fmod(yval, deltag ) + gr->gy1;
- if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
- } else {
- yval = G_Y(xctx->mousey);
- }
-
- xval = G_X(xctx->mousex);
- if(gr->logx) xval = pow(10, xval);
- if(gr->logy) yval = pow(10, yval);
- if(gr->unitx != 1.0)
- my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
- else
- my_strncpy(sx, dtoa_eng(xval), S(sx));
-
- if(gr->unitx != 1.0)
- my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
- else
- my_strncpy(sy, dtoa_eng(yval), S(sy));
-
- tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
- tcleval("graph_show_measure");
- } else {
- tcleval("graph_show_measure stop");
- }
- } /* if(xctx->graph_flags & 64) */
- } /* if(i == xctx->graph_master) */
- dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
-
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
!(xctx->graph_flags & (16 | 32 | 512 | 1024))) {