From b60a5a4c4b01d36e4a8684e8798d5400df0df0a2 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Tue, 31 Oct 2023 18:39:42 +0100 Subject: [PATCH] Add command `xschem setprop text n txt_ptr value` to change a text object text field, set stdout in line buffer mode if used in a pipe, better protect some commands against no X connection --- doc/xschem_man/developer_info.html | 6 ++- src/main.c | 2 +- src/scheduler.c | 65 +++++++++++++---------- src/xschem.tcl | 84 +++++++++++++++++------------- 4 files changed, 91 insertions(+), 66 deletions(-) diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 16dc7648..5eef8115 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -520,6 +520,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" +
  • abort_operation
  • @@ -1231,8 +1232,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
            setprop rect 2 n fullyzoom
        These commands do full x/y zoom of graph 'n' (on layer 2, this is hardcoded).
           
    -       setprop text n tok [val] [fast|fastundo]
    +       setprop text n [tok] [val] [fast|fastundo]
        Set attribute 'tok' of text number 'n'
    +   If 'tok' not specified set text string (txt_ptr) to value
    +   If "txt_ptr" is given as token replace the text txt_ptr ("the text")
        If 'val' not given (no attribute value) delete attribute from text
        If 'fast' argument is given does not redraw and is not undoable
        If 'fastundo' s given same as above but action is undoable.
    @@ -1398,6 +1401,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" + diff --git a/src/main.c b/src/main.c index 0d6a180c..606878a4 100644 --- a/src/main.c +++ b/src/main.c @@ -102,8 +102,8 @@ int main(int argc, char **argv) #ifdef __unix__ /* if invoked in background (and not invoked from a command pipeline) detach from console */ - if(!fstat(0, &statbuf)) { + setvbuf(stdout, NULL, _IOLBF, 0); /* set to line buffer mode */ if(statbuf.st_mode & S_IFIFO) stdin_is_a_fifo = 1; /* input coming from a command pipe */ } diff --git a/src/scheduler.c b/src/scheduler.c index 312efe22..21916f53 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -4152,8 +4152,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg * setprop rect 2 n fullyzoom * These commands do full x/y zoom of graph 'n' (on layer 2, this is hardcoded). * - * setprop text n tok [val] [fast|fastundo] + * setprop text n [tok] [val] [fast|fastundo] * Set attribute 'tok' of text number 'n' + * If 'tok' not specified set text string (txt_ptr) to value + * If "txt_ptr" is given as token replace the text txt_ptr ("the text") * If 'val' not given (no attribute value) delete attribute from text * If 'fast' argument is given does not redraw and is not undoable * If 'fastundo' s given same as above but action is undoable. @@ -4335,11 +4337,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } Tcl_ResetResult(interp); - } else if(argc > 4 && !strcmp(argv[2], "text")) { - /* 0 1 2 3 4 5 6 - * xschem setprop text n token value [fast] */ + } else if(argc > 3 && !strcmp(argv[2], "text")) { + /* 0 1 2 3 4 5 6 + * xschem setprop text n [token] value [fast|fastundo] + * if "txt_ptr" is given as token replace the text txt_ptr ("the text") */ int change_done = 0; - int tmp, fast = 0; + int argc_copy, i, tmp, fast = 0; double xx1, xx2, yy1, yy2, dtmp; xText *t; int n = atoi(argv[3]); @@ -4348,37 +4351,42 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg return TCL_ERROR; } t = &xctx->text[n]; - if(argc > 6) { - if(!strcmp(argv[6], "fast")) { + + argc_copy = argc; + for(i = 5; i < argc_copy; i++) { + if(!strcmp(argv[i], "fast")) { fast = 1; - argc = 6; + argc--; } - if(!strcmp(argv[6], "fastundo")) { + if(!strcmp(argv[i], "fastundo")) { fast = 3; - argc = 6; - } - } - else if(argc > 5) { - if(!strcmp(argv[5], "fast")) { - fast = 1; - argc = 5; - } - if(!strcmp(argv[5], "fastundo")) { - fast = 3; - argc = 5; + argc--; } } if(!fast) { bbox(START,0.0,0.0,0.0,0.0); } if(argc > 5) { + if(!fast) { + text_bbox(get_text_floater(n), t->xscale, + t->yscale, t->rot, t->flip, t->hcenter, + t->vcenter, t->x0, t->y0, + &xx1,&yy1,&xx2,&yy2, &tmp, &dtmp); + bbox(ADD, xx1, yy1, xx2, yy2); + } /* verify if there is some difference */ - if(strcmp(argv[5], get_tok_value(t->prop_ptr, argv[4], 0))) { + if(!strcmp(argv[4], "txt_ptr")) { + if(strcmp(argv[5], t->txt_ptr)) { + change_done = 1; + if(fast == 3 || fast == 0) xctx->push_undo(); + my_strdup2(_ALLOC_ID_, &t->txt_ptr, argv[5]); + } + } else if(strcmp(argv[5], get_tok_value(t->prop_ptr, argv[4], 0))) { change_done = 1; if(fast == 3 || fast == 0) xctx->push_undo(); my_strdup2(_ALLOC_ID_, &t->prop_ptr, subst_token(t->prop_ptr, argv[4], argv[5])); } - } else { + } else if(argc > 4) { get_tok_value(t->prop_ptr, argv[4], 0); if(xctx->tok_size) { change_done = 1; @@ -4386,18 +4394,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg my_strdup2(_ALLOC_ID_, &t->prop_ptr, subst_token(t->prop_ptr, argv[4], NULL)); /* delete attr */ } } - if(change_done) set_modify(1); - set_text_flags(t); - text_bbox(get_text_floater(n), t->xscale, + if(change_done) { + set_modify(1); + set_text_flags(t); + text_bbox(get_text_floater(n), t->xscale, t->yscale, t->rot, t->flip, t->hcenter, t->vcenter, t->x0, t->y0, &xx1,&yy1,&xx2,&yy2, &tmp, &dtmp); - + if(!fast) bbox(ADD, xx1, yy1, xx2, yy2); + } if(!fast) { - bbox(ADD, xx1, yy1, xx2, yy2); /* redraw rect with new props */ bbox(SET,0.0,0.0,0.0,0.0); - draw(); + if(change_done) draw(); bbox(END,0.0,0.0,0.0,0.0); } Tcl_ResetResult(interp); diff --git a/src/xschem.tcl b/src/xschem.tcl index a8225bea..b826b302 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -226,7 +226,7 @@ proc set_ne { var val } { # # execute service function proc execute_fileevent {id} { - global execute OS + global execute OS has_x append execute(data,$id) [read $execute(pipe,$id) 1024] if { $OS != {Windows} } { @@ -282,7 +282,7 @@ proc execute_fileevent {id} { unset execute(status,$id) unset execute(cmd,$id) # apply a delay, process does not disappear immediately. - if {[winfo exists .processlist]} { after 250 {insert_running_cmds .processlist.f2.lb}} + if {[info exists has_x] && [winfo exists .processlist]} { after 250 {insert_running_cmds .processlist.f2.lb}} } } @@ -343,7 +343,7 @@ proc execute {status args} { set execute(data,$id) "" # Apply a delay to catch the new process. - if {[winfo exists .processlist]} { after 250 {insert_running_cmds .processlist.f2.lb}} + if {[info exists has_x] && [winfo exists .processlist]} { after 250 {insert_running_cmds .processlist.f2.lb}} fconfigure $pipe -blocking 0 if {[regexp {line} $status]} { fconfigure $pipe -buffering line @@ -387,9 +387,10 @@ proc insert_running_cmds {lb} { # periodically update status proc update_process_status {lb} { - global execute + global execute has_x set exists 0 set selected [$lb curselection] + if { ![info exists has_x]} {return} if { [winfo exists .pstat] } { set pos [lindex [.pstat.text yview] 1] if {$pos == 1} { @@ -418,9 +419,10 @@ proc update_process_status {lb} { # display stdout of selected sub-process proc view_process_status {lb} { - global execute + global execute has_x set exists 0 - if { [winfo exists .pstat] } { + if {![info exists has_x]} {return} + if {[winfo exists .pstat] } { .pstat.text delete 1.0 end set exists 1 } @@ -448,7 +450,9 @@ proc view_process_status {lb} { # top level dialog displaying running sub-processes proc list_running_cmds {} { + global has_x set top .processlist + if {![info exists has_x]} {return} if {[winfo exists $top]} {return} toplevel $top -class Dialog # wm transient $top . @@ -1945,13 +1949,13 @@ proc graph_edit_wave {n n_wave} { # add nodes from provided list of {node color} .... # used in hilight_net() proc graph_add_nodes_from_list {nodelist} { - global graph_bus graph_selected graph_schname + global graph_bus graph_selected graph_schname has_x if {$graph_bus} { set sep , } else { set sep \n } - if { [winfo exists .graphdialog] } { + if { [info exists has_x] && [winfo exists .graphdialog] } { set sel {} set current_node_list [.graphdialog.center.right.text1 get 1.0 {end - 1 chars}] set col [xschem getprop rect 2 $graph_selected color] @@ -2212,7 +2216,9 @@ proc graph_set_linewidth {graph_sel} { proc graph_edit_properties {n} { global graph_bus graph_sort graph_digital graph_selected colors graph_sel_color global graph_unlocked graph_schname graph_logx graph_logy cadlayers graph_rainbow - global graph_linewidth_mult graph_change_done + global graph_linewidth_mult graph_change_done has_x + + if { ![info exists has_x]} {return} set graph_change_done 0 set geom {} if { [winfo exists .graphdialog]} { @@ -2694,8 +2700,9 @@ proc graph_edit_properties {n} { } proc graph_show_measure {{action show}} { - global measure_id measure_text + global measure_id measure_text has_x + if {![info exists has_x]} return; set_ne measure_text "y=\nx=" if { [info exists measure_id] } { after cancel $measure_id @@ -2879,26 +2886,30 @@ proc cleanup {} { } proc display {} { - variable c_t - if { [winfo exists $c_t(w)]} { - set w $c_t(w) - set n $c_t(n) - cleanup - destroy $w.title - for {set i 0} {$i < $n} {incr i} { - destroy $w.b$i - } - set i $c_t(top) - button $w.title -text Recent -pady 0 -padx 0 -width 7 -state disabled -disabledforeground black \ - -background grey60 -highlightthickness 0 -borderwidth 0 -font {TkDefaultFont 12 bold} - pack $w.title -side top -fill x - while {1} { - button $w.b$i -text $c_t($i,text) -pady 0 -padx 0 -command $c_t($i,command) -width 7 - pack $w.b$i -side top -fill x - set i [expr {($i + 1) % $n}] - if { $i == $c_t(top) } break - } + global has_x + variable c_t + + if {![info exists has_x]} {return} + + if { [winfo exists $c_t(w)]} { + set w $c_t(w) + set n $c_t(n) + cleanup + destroy $w.title + for {set i 0} {$i < $n} {incr i} { + destroy $w.b$i } + set i $c_t(top) + button $w.title -text Recent -pady 0 -padx 0 -width 7 -state disabled -disabledforeground black \ + -background grey60 -highlightthickness 0 -borderwidth 0 -font {TkDefaultFont 12 bold} + pack $w.title -side top -fill x + while {1} { + button $w.b$i -text $c_t($i,text) -pady 0 -padx 0 -command $c_t($i,command) -width 7 + pack $w.b$i -side top -fill x + set i [expr {($i + 1) % $n}] + if { $i == $c_t(top) } break + } + } } proc add {f} { @@ -3014,7 +3025,7 @@ proc load_file_dialog_mkdir {dir} { if { $dir ne {} } { if {[catch {file mkdir "${myload_dir1}/$dir"} err]} { puts $err - if {$has_x} { + if {[info exists has_x]} { tk_messageBox -message "$err" -icon error -parent [xschem get topwindow] -type ok } } @@ -3645,7 +3656,7 @@ proc simuldir {} { set simdir [xschem get current_dirname]/simulation if {[catch {file mkdir "$simdir"} err]} { puts $err - if {$has_x} { + if {[info exists has_x]} { tk_messageBox -message "$err" -icon error -parent [xschem get topwindow] -type ok } } @@ -3674,7 +3685,7 @@ proc set_netlist_dir { force {dir {} }} { if {![file exist $netlist_dir]} { if {[catch {file mkdir "$netlist_dir"} err]} { puts $err - if {$has_x} { + if {[info exists has_x]} { tk_messageBox -message "$err" -icon error -parent [xschem get topwindow] -type ok } } @@ -3704,7 +3715,7 @@ proc set_netlist_dir { force {dir {} }} { if {![file exist $new_dir]} { if {[catch {file mkdir "$new_dir"} err]} { puts $err - if {$has_x} { + if {[info exists has_x]} { tk_messageBox -message "$err" -icon error -parent [xschem get topwindow] -type ok } } @@ -4961,7 +4972,8 @@ proc textwindow {filename {ro {}}} { proc viewdata {data {ro {}} {win .view}} { global viewdata_wcounter rcode viewdata_filename - global viewdata_w OS viewdata_fileid env + global viewdata_w OS viewdata_fileid env has_x + if {![info exists has_x]} {return} # set viewdata_w .view$viewdata_wcounter # catch {destroy $viewdata_w} if {$win eq {.view}} { @@ -5138,7 +5150,7 @@ proc download_url {url} { if {![file exists ${XSCHEM_TMP_DIR}/xschem_web]} { if {[catch {file mkdir "${XSCHEM_TMP_DIR}/xschem_web"} err]} { puts $err - if {$has_x} { + if {[info exists has_x]} { tk_messageBox -message "$err" -icon error -parent [xschem get topwindow] -type ok } } @@ -5325,7 +5337,7 @@ proc swap_compare_schematics {} { proc input_line {txt {cmd {}} {preset {}} {w 12}} { global wm_fix retval set retval {} - if { [winfo exists .dialog] } return + if { [winfo exists .dialog] } {return} xschem set semaphore [expr {[xschem get semaphore] +1}] toplevel .dialog -class Dialog wm title .dialog {Input number}