fix arbitrary widths in shapes, add "xschem get change_lw", "xschem get min_lw", "xschem set change_lw", cached tcl var "change_lw" into xctx->change_lw

This commit is contained in:
stefan schippers 2025-12-01 10:11:19 +01:00
parent 6bea824fdc
commit a61f2cba2a
9 changed files with 54 additions and 26 deletions

View File

@ -782,6 +782,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> build_date </kbd> time and date this file was built. </li> <li><kbd> build_date </kbd> time and date this file was built. </li>
<li><kbd> cadlayers </kbd> number of layers </li> <li><kbd> cadlayers </kbd> number of layers </li>
<li><kbd> case_insensitive </kbd> case_insensitive symbol matching </li> <li><kbd> case_insensitive </kbd> case_insensitive symbol matching </li>
<li><kbd> change_lw </kbd> change line width when zooming </li>
<li><kbd> color_ps </kbd> color postscript flag </li> <li><kbd> color_ps </kbd> color postscript flag </li>
<li><kbd> constr_mv </kbd> color postscript flag </li> <li><kbd> constr_mv </kbd> color postscript flag </li>
<li><kbd> current_dirname </kbd> directory name of current design </li> <li><kbd> current_dirname </kbd> directory name of current design </li>
@ -807,6 +808,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> lastsel </kbd> number of selected objects </li> <li><kbd> lastsel </kbd> number of selected objects </li>
<li><kbd> line_width </kbd> get line width </li> <li><kbd> line_width </kbd> get line width </li>
<li><kbd> lines </kbd> (xschem get lines n) number of lines on layer 'n' </li> <li><kbd> lines </kbd> (xschem get lines n) number of lines on layer 'n' </li>
<li><kbd> min_lw </kbd> minimum line width </li>
<li><kbd> modified </kbd> schematic is in modified state (needs a save) </li> <li><kbd> modified </kbd> schematic is in modified state (needs a save) </li>
<li><kbd> netlist_name </kbd> netlist name if set. If 'fallback' given get default name </li> <li><kbd> netlist_name </kbd> netlist name if set. If 'fallback' given get default name </li>
<li><kbd> netlist_type </kbd> get current netlist type (spice/vhdl/verilog/tedax) </li> <li><kbd> netlist_type </kbd> get current netlist type (spice/vhdl/verilog/tedax) </li>
@ -1503,6 +1505,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<ul> <ul>
<li><kbd> cadgrid </kbd> set cad grid (default: 20) </li> <li><kbd> cadgrid </kbd> set cad grid (default: 20) </li>
<li><kbd> cadsnap </kbd> set mouse snap (default: 10) </li> <li><kbd> cadsnap </kbd> set mouse snap (default: 10) </li>
<li><kbd> change_lw </kbd> allow change line width when zooming </li>
<li><kbd> color_ps </kbd> set color psoscript (1 or 0) </li> <li><kbd> color_ps </kbd> set color psoscript (1 or 0) </li>
<li><kbd> crosshair_layer </kbd> set layer for mouse crosshair </li> <li><kbd> crosshair_layer </kbd> set layer for mouse crosshair </li>
<li><kbd> constr_mv </kbd> set constrained move (1=horiz, 2=vert, 0=none) </li> <li><kbd> constr_mv </kbd> set constrained move (1=horiz, 2=vert, 0=none) </li>

View File

@ -2896,7 +2896,7 @@ void zoom_full(int dr, int sel, int flags, double shrink)
double bboxw, bboxh, schw, schh; double bboxw, bboxh, schw, schh;
double cs = tclgetdoublevar("cadsnap"); double cs = tclgetdoublevar("cadsnap");
if(flags & 1) { if(flags & 1) {
if(tclgetboolvar("change_lw")) { if(xctx->change_lw) {
xctx->lw = 1.; xctx->lw = 1.;
} }
xctx->areax1 = -2*INT_LINE_W(xctx->lw); xctx->areax1 = -2*INT_LINE_W(xctx->lw);

View File

@ -3724,13 +3724,15 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
break; break;
case '_': /* toggle change line width */ case '_': /* toggle change line width */
if(!tclgetboolvar("change_lw")) { if(!xctx->change_lw) {
tcleval("alert_ { enabling change line width} {}"); tcleval("alert_ { enabling change line width} {}");
tclsetvar("change_lw","1"); tclsetvar("change_lw","1");
xctx->change_lw = 1;
} }
else { else {
tcleval("alert_ { disabling change line width} {}"); tcleval("alert_ { disabling change line width} {}");
tclsetvar("change_lw","0"); tclsetvar("change_lw","0");
xctx->change_lw = 0;
} }
break; break;

View File

@ -1345,7 +1345,7 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub
width = INT_BUS_WIDTH(xctx->lw); width = INT_BUS_WIDTH(xctx->lw);
} else if(bus > 0.0) { } else if(bus > 0.0) {
what = NOW; what = NOW;
width = (int) (bus * xctx->mooz); width = XLINEWIDTH(bus * xctx->mooz);
} else { } else {
width = XLINEWIDTH(xctx->lw); width = XLINEWIDTH(xctx->lw);
} }
@ -1424,9 +1424,9 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub
if(dash) { if(dash) {
dash_arr[0] = dash_arr[1] = (char) dash; dash_arr[0] = dash_arr[1] = (char) dash;
XSetDashes(display, xctx->gc[c], 0, dash_arr, 1); XSetDashes(display, xctx->gc[c], 0, dash_arr, 1);
XSetLineAttributes (display, xctx->gc[c], INT_BUS_WIDTH(xctx->lw), xDashType, xCap, xJoin); XSetLineAttributes (display, xctx->gc[c], width, xDashType, xCap, xJoin);
} else { } else {
XSetLineAttributes (display, xctx->gc[c], INT_BUS_WIDTH(xctx->lw), LineSolid, LINECAP, LINEJOIN); XSetLineAttributes (display, xctx->gc[c], width, LineSolid, LINECAP, LINEJOIN);
} }
if(xctx->draw_window) XDrawLine(display, xctx->window, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); if(xctx->draw_window) XDrawLine(display, xctx->window, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2);
if(xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); if(xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2);
@ -1748,7 +1748,7 @@ void drawarc(int c, int what, double x, double y, double r, double a, double b,
width = INT_BUS_WIDTH(xctx->lw); width = INT_BUS_WIDTH(xctx->lw);
} else if(bus > 0.0) { } else if(bus > 0.0) {
what = NOW; what = NOW;
width = (int) (bus * xctx->mooz); width = XLINEWIDTH(bus * xctx->mooz);
} else { } else {
width = XLINEWIDTH(xctx->lw); width = XLINEWIDTH(xctx->lw);
} }
@ -2103,7 +2103,7 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil
if(bus == -1.0) { if(bus == -1.0) {
width = INT_BUS_WIDTH(xctx->lw); width = INT_BUS_WIDTH(xctx->lw);
} else if(bus > 0.0) { } else if(bus > 0.0) {
width = (int) (bus * xctx->mooz); width = XLINEWIDTH(bus * xctx->mooz);
} else { } else {
width = XLINEWIDTH(xctx->lw); width = XLINEWIDTH(xctx->lw);
} }
@ -2237,7 +2237,7 @@ void drawrect(int c, int what, double rectx1,double recty1,double rectx2,double
width = INT_BUS_WIDTH(xctx->lw); width = INT_BUS_WIDTH(xctx->lw);
} else if(bus > 0.0) { } else if(bus > 0.0) {
what = NOW; what = NOW;
width = (int) (bus * xctx->mooz); width = XLINEWIDTH(bus * xctx->mooz);
} else { } else {
width = XLINEWIDTH(xctx->lw); width = XLINEWIDTH(xctx->lw);
} }

View File

@ -1048,9 +1048,11 @@ static int edit_rect_property(int x)
(char *) tclgetvar("tctx::retval")); (char *) tclgetvar("tctx::retval"));
} }
bus = xctx->rect[c][n].bus = get_attr_val(get_tok_value(xctx->rect[c][n].prop_ptr,"bus",0)); bus = xctx->rect[c][n].bus = get_attr_val(get_tok_value(xctx->rect[c][n].prop_ptr,"bus",0));
if(bus > 0.0) width = bus / 2.0;
if(bus > 0.0) width = XLINEWIDTH(bus) / 2.0;
else width = INT_BUS_WIDTH(xctx->lw) / 2.0; else width = INT_BUS_WIDTH(xctx->lw) / 2.0;
if(oldbus / 2.0 > width) width = oldbus / 2.0; if(oldbus / 2.0 > width) width = XLINEWIDTH(oldbus) / 2.0;
set_rect_flags(&xctx->rect[c][n]); /* set cached .flags bitmask from attributes */ set_rect_flags(&xctx->rect[c][n]); /* set cached .flags bitmask from attributes */
set_rect_extraptr(0, &xctx->rect[c][n]); set_rect_extraptr(0, &xctx->rect[c][n]);
@ -1144,9 +1146,9 @@ static int edit_line_property(void)
} }
bus = xctx->line[c][n].bus = get_attr_val(get_tok_value(xctx->line[c][n].prop_ptr,"bus",0)); bus = xctx->line[c][n].bus = get_attr_val(get_tok_value(xctx->line[c][n].prop_ptr,"bus",0));
if(bus > 0.0) width = bus / 2.0; if(bus > 0.0) width = XLINEWIDTH(bus) / 2.0;
else width = INT_BUS_WIDTH(xctx->lw) / 2.0; else width = INT_BUS_WIDTH(xctx->lw) / 2.0;
if(oldbus / 2.0 > width) width = oldbus / 2.0; if(oldbus / 2.0 > width) width = XLINEWIDTH(oldbus) / 2.0;
dash = get_tok_value(xctx->line[c][n].prop_ptr,"dash",0); dash = get_tok_value(xctx->line[c][n].prop_ptr,"dash",0);
if( strcmp(dash, "") ) { if( strcmp(dash, "") ) {
@ -1209,9 +1211,9 @@ static int edit_wire_property(void)
} }
xctx->wire[k].bus = bus = get_attr_val(get_tok_value(xctx->wire[k].prop_ptr,"bus",0)); xctx->wire[k].bus = bus = get_attr_val(get_tok_value(xctx->wire[k].prop_ptr,"bus",0));
if(bus > 0.0) width = bus / 2.0; if(bus > 0.0) width = XLINEWIDTH(bus) / 2.0;
else width = INT_BUS_WIDTH(xctx->lw / 2.0); else width = INT_BUS_WIDTH(xctx->lw) / 2.0;
if(oldbus / 2.0 > width) width = oldbus / 2.0; if(oldbus / 2.0 > width) width = XLINEWIDTH(oldbus) / 2.0;
ov = width > xctx->cadhalfdotsize ? width : xctx->cadhalfdotsize; ov = width > xctx->cadhalfdotsize ? width : xctx->cadhalfdotsize;
if(xctx->wire[k].y1 < xctx->wire[k].y2) { y1 = xctx->wire[k].y1-ov; y2 = xctx->wire[k].y2+ov; } if(xctx->wire[k].y1 < xctx->wire[k].y2) { y1 = xctx->wire[k].y1-ov; y2 = xctx->wire[k].y2+ov; }
@ -1280,9 +1282,9 @@ static int edit_arc_property(void)
xctx->arc[c][i].dash = 0; xctx->arc[c][i].dash = 0;
bus = xctx->arc[c][i].bus = get_attr_val(get_tok_value(xctx->arc[c][i].prop_ptr,"bus",0)); bus = xctx->arc[c][i].bus = get_attr_val(get_tok_value(xctx->arc[c][i].prop_ptr,"bus",0));
if(bus > 0.0) width = bus / 2.0; if(bus > 0.0) width = XLINEWIDTH(bus) / 2.0;
else width = INT_BUS_WIDTH(xctx->lw) / 2.0; else width = INT_BUS_WIDTH(xctx->lw) / 2.0;
if(oldbus / 2.0 > width) width = oldbus / 2.0; if(oldbus / 2.0 > width) width = XLINEWIDTH(oldbus) / 2.0;
if(oldbus != bus || old_fill != xctx->arc[c][i].fill || old_dash != xctx->arc[c][i].dash) { if(oldbus != bus || old_fill != xctx->arc[c][i].fill || old_dash != xctx->arc[c][i].dash) {
if(!drw) { if(!drw) {
@ -1349,10 +1351,9 @@ static int edit_polygon_property(void)
bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr,"bezier",0),"true") ; bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr,"bezier",0),"true") ;
xctx->poly[c][i].bus = bus = get_attr_val(get_tok_value(xctx->poly[c][i].prop_ptr,"bus",0)); xctx->poly[c][i].bus = bus = get_attr_val(get_tok_value(xctx->poly[c][i].prop_ptr,"bus",0));
if(bus > 0.0) width = bus / 2.0; if(bus > 0.0) width = XLINEWIDTH(bus) / 2.0;
else width = xctx->cadhalfdotsize > INT_BUS_WIDTH(xctx->lw) / 2.0 ? else width = MAJOR(INT_BUS_WIDTH(xctx->lw) / 2.0, xctx->cadhalfdotsize);
xctx->cadhalfdotsize : INT_BUS_WIDTH(xctx->lw) / 2.0; if(oldbus / 2.0 > width) width = XLINEWIDTH(oldbus) / 2.0;
if(oldbus / 2.0 > width) width = oldbus / 2.0;
fill_ptr = get_tok_value(xctx->poly[c][i].prop_ptr,"fill",0); fill_ptr = get_tok_value(xctx->poly[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr,"full") ) if( !strcmp(fill_ptr,"full") )

View File

@ -1420,6 +1420,10 @@ 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(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, my_itoa(xctx->case_insensitive), TCL_VOLATILE); Tcl_SetResult(interp, my_itoa(xctx->case_insensitive), TCL_VOLATILE);
} }
else if(!strcmp(argv[2], "change_lw")) { /* change line width when zooming */
if(xctx->change_lw != 0 ) Tcl_SetResult(interp, "1",TCL_STATIC);
else Tcl_SetResult(interp, "0",TCL_STATIC);
}
else if(!strcmp(argv[2], "color_ps")) { /* color postscript flag */ else if(!strcmp(argv[2], "color_ps")) { /* color postscript flag */
if(color_ps != 0 ) Tcl_SetResult(interp, "1",TCL_STATIC); if(color_ps != 0 ) Tcl_SetResult(interp, "1",TCL_STATIC);
else Tcl_SetResult(interp, "0",TCL_STATIC); else Tcl_SetResult(interp, "0",TCL_STATIC);
@ -1555,6 +1559,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
} }
break; break;
case 'm': case 'm':
if(!strcmp(argv[2], "min_lw")) { /* minimum line width */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, dtoa(xctx->min_lw),TCL_VOLATILE);
}
if(!strcmp(argv[2], "modified")) { /* schematic is in modified state (needs a save) */ if(!strcmp(argv[2], "modified")) { /* schematic is in modified state (needs a save) */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, my_itoa(xctx->modified),TCL_VOLATILE); Tcl_SetResult(interp, my_itoa(xctx->modified),TCL_VOLATILE);
@ -5422,6 +5430,11 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
change_linewidth(-1.); change_linewidth(-1.);
draw(); draw();
} }
else if(!strcmp(argv[2], "change_lw")) { /* allow change line width when zooming */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
xctx->change_lw = atoi(argv[3]);
tclsetboolvar("change_lw", xctx->change_lw);
}
else if(!strcmp(argv[2], "color_ps")) { /* set color psoscript (1 or 0) */ else if(!strcmp(argv[2], "color_ps")) { /* set color psoscript (1 or 0) */
color_ps=atoi(argv[3]); color_ps=atoi(argv[3]);
} }

View File

@ -716,6 +716,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->x_strcmp = strcmp; xctx->x_strcmp = strcmp;
xctx->fill_pattern = 1; xctx->fill_pattern = 1;
xctx->draw_window = 0; xctx->draw_window = 0;
xctx->change_lw = 1;
xctx->do_copy_area = 1; xctx->do_copy_area = 1;
xctx->time_last_modify = 0; xctx->time_last_modify = 0;
} }
@ -2147,7 +2148,7 @@ void change_linewidth(double w)
dbg(1, "change_linewidth(): w = %g, win_path=%s lw=%g\n", w, xctx->current_win_path, xctx->lw); dbg(1, "change_linewidth(): w = %g, win_path=%s lw=%g\n", w, xctx->current_win_path, xctx->lw);
if(w<0. || xctx->lw == -1.0) { if(w<0. || xctx->lw == -1.0) {
double cs = tclgetdoublevar("cadsnap"); double cs = tclgetdoublevar("cadsnap");
if(tclgetboolvar("change_lw")) { if(xctx->change_lw) {
xctx->lw=xctx->mooz * 0.09 * cs * (1.0 + MAJOR(xctx->min_lw, 1.0) / 4.0); xctx->lw=xctx->mooz * 0.09 * cs * (1.0 + MAJOR(xctx->min_lw, 1.0) / 4.0);
if(xctx->lw > 100.) xctx->lw = 100.; if(xctx->lw > 100.) xctx->lw = 100.;
xctx->cadhalfdotsize = CADHALFDOTSIZE * (cs < 20. ? cs : 20.) / 10.; xctx->cadhalfdotsize = CADHALFDOTSIZE * (cs < 20. ? cs : 20.) / 10.;
@ -2404,6 +2405,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
#endif #endif
int i; int i;
double l_width; double l_width;
int change_lw;
struct stat buf; struct stat buf;
int running_in_src_dir; int running_in_src_dir;
int fs; int fs;
@ -2868,6 +2870,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
tclsetboolvar("color_ps", color_ps); tclsetboolvar("color_ps", color_ps);
} }
l_width=tclgetdoublevar("line_width"); l_width=tclgetdoublevar("line_width");
change_lw=tclgetboolvar("change_lw");
cadlayers=tclgetintvar("cadlayers"); cadlayers=tclgetintvar("cadlayers");
fix_broken_tiled_fill = tclgetboolvar("fix_broken_tiled_fill"); fix_broken_tiled_fill = tclgetboolvar("fix_broken_tiled_fill");
fix_mouse_coord = tclgetboolvar("fix_mouse_coord"); fix_mouse_coord = tclgetboolvar("fix_mouse_coord");
@ -3021,7 +3024,8 @@ int Tcl_AppInit(Tcl_Interp *inter)
tclsetvar("has_cairo","1"); tclsetvar("has_cairo","1");
#endif #endif
xctx->min_lw = (int)l_width; xctx->min_lw = (int)l_width;
if(tclgetboolvar("change_lw")) l_width = -1.0; xctx->change_lw = change_lw;
if(xctx->change_lw) l_width = -1.0;
change_linewidth(l_width); change_linewidth(l_width);
dbg(1, "Tcl_AppInit(): done xinit()\n"); dbg(1, "Tcl_AppInit(): done xinit()\n");
/* Set backing store window attribute */ /* Set backing store window attribute */

View File

@ -429,9 +429,13 @@ do { \
#define SWAP(a,b, tmp) do { tmp = a; a = b; b = tmp; } while(0) #define SWAP(a,b, tmp) do { tmp = a; a = b; b = tmp; } while(0)
#define XLINEWIDTH(x) MAJOR((tclgetboolvar("change_lw") ? ((int)(x) == 0 ? 1 : (int)(x)) : (int)(x)), xctx->min_lw) #define XLINEWIDTH(x) MAJOR((xctx->change_lw ? \
((int)(x) == 0 ? 1 : (int)(x)) : \
(int)(x)), xctx->min_lw)
#define INT_LINE_W(x) MAJOR(((int)(x) == 0 ? 1 : (int)(x)), xctx->min_lw) #define INT_LINE_W(x) MAJOR(((int)(x) == 0 ? 1 : (int)(x)), xctx->min_lw)
#define INT_BUS_WIDTH(x) ( (int)( (BUS_WIDTH) * (x) ) == 0 ? 1 : (int)( (BUS_WIDTH) * (x) ) ) #define INT_BUS_WIDTH(x) MAJOR((xctx->change_lw ? \
((int)( (BUS_WIDTH) * (x) ) == 0 ? 1 : (int)((BUS_WIDTH) * (x))) : \
(int)((BUS_WIDTH) * (x)) ), xctx->min_lw)
/* set do double if you need more precision at the expense of memory */ /* set do double if you need more precision at the expense of memory */
#define SPICE_DATA double #define SPICE_DATA double
@ -1167,6 +1171,7 @@ typedef struct {
int fill_pattern; int fill_pattern;
int draw_pixmap; /* pixmap used as 2nd buffer */ int draw_pixmap; /* pixmap used as 2nd buffer */
int draw_window; /* MIRRORED IN TCL */ int draw_window; /* MIRRORED IN TCL */
int change_lw; /* cached valiue of TCL change_lw */
int do_copy_area; int do_copy_area;
double cadhalfdotsize; double cadhalfdotsize;
time_t time_last_modify; time_t time_last_modify;

View File

@ -10161,7 +10161,7 @@ proc build_widgets { {topwin {} } } {
} }
$topwin.menubar.view add checkbutton -label "Toggle variable line width" -variable change_lw \ $topwin.menubar.view add checkbutton -label "Toggle variable line width" -variable change_lw \
-selectcolor $selectcolor -accelerator {_} -selectcolor $selectcolor -accelerator {_} -command "xschem set change_lw $change_lw"
$topwin.menubar.view add command -label "Set line width" -accelerator {Alt+-} \ $topwin.menubar.view add command -label "Set line width" -accelerator {Alt+-} \
-command { -command {
input_line "Enter linewidth (float):" "xschem line_width" input_line "Enter linewidth (float):" "xschem line_width"