Merge pull request #13 from TheSUPERCD/upstream-clone

Resolve remaining merge conflicts
This commit is contained in:
Chayan Deb 2025-02-20 13:16:25 +05:30 committed by GitHub
commit 634f8f5376
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 2869 additions and 2337 deletions

View File

@ -254,6 +254,7 @@
<ClCompile Include="..\src\verilog_netlist.c" />
<ClCompile Include="..\src\vhdl_netlist.c" />
<ClCompile Include="..\src\xinit.c" />
<ClCompile Include="eval_expr.c" />
<ClCompile Include="expandlabel.c" />
<ClCompile Include="parselabel.c" />
</ItemGroup>
@ -261,6 +262,7 @@
<ClInclude Include="..\src\cairo_jpg.h" />
<ClInclude Include="..\src\xschem.h" />
<ClInclude Include="config.h" />
<ClInclude Include="eval_expr.h" />
<ClInclude Include="expandlabel.h" />
</ItemGroup>
<ItemGroup>
@ -284,6 +286,11 @@
</CustomBuild>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\src\eval_expr.y">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">bison -p kk -o eval_expr.c ..\src\eval_expr.y </Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">eval_expr.c</Outputs>
</CustomBuild>
<None Include="..\src\xschem.tcl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -254,6 +254,7 @@
<ClCompile Include="..\src\verilog_netlist.c" />
<ClCompile Include="..\src\vhdl_netlist.c" />
<ClCompile Include="..\src\xinit.c" />
<ClCompile Include="eval_expr.c" />
<ClCompile Include="expandlabel.c" />
<ClCompile Include="parselabel.c" />
</ItemGroup>
@ -261,6 +262,7 @@
<ClInclude Include="..\src\cairo_jpg.h" />
<ClInclude Include="..\src\xschem.h" />
<ClInclude Include="config.h" />
<ClInclude Include="eval_expr.h" />
<ClInclude Include="expandlabel.h" />
</ItemGroup>
<ItemGroup>
@ -284,6 +286,11 @@
</CustomBuild>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\src\eval_expr.y">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">bison -p kk -o eval_expr.c ..\src\eval_expr.y </Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">eval_expr.c</Outputs>
</CustomBuild>
<None Include="..\src\xschem.tcl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -250,10 +250,7 @@
<Component Id="CMPPLACESYMPINS">
<File Id="PLACESYMPINS" KeyPath="yes" Source="../../src/place_sym_pins.tcl" />
</Component>
<Component Id="CMPCREATESYMBOL">
<File Id="CREATESYMBOL" KeyPath="yes" Source="../../src/create_symbol.tcl" />
</Component>
<Directory Id="SYSTEMLIBFOLDER" Name="systemlib">
<Component Id="CMPSYSTEMLIBFONTSCH">
<File Id="FONTSCH" KeyPath="yes" Source="../../src/systemlib/font.sch" />
@ -374,7 +371,6 @@
<ComponentRef Id="CMPTRADUCIAWK" />
<ComponentRef Id="CMPPLACEPLINS" />
<ComponentRef Id="CMPPLACESYMPINS" />
<ComponentRef Id="CMPCREATESYMBOL" />
<ComponentRef Id="CMPVERILOGAWK" />
<ComponentRef Id="CMPVHDLAWK" />
<ComponentRef Id="CMPXSCHEMHELP" />

File diff suppressed because it is too large Load Diff

View File

@ -293,6 +293,9 @@
<Component Id="cmpC76DA8327344C4B4AB04EF665B72B736" Guid="{2ACADB68-D803-40D4-BCA3-ECA604ED7AE9}">
<File Id="filCC0547DA9E32AACF4F88B5E7AD58DEC0" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\sqwsource.sym" />
</Component>
<Component Id="cmp57911CE62A560E61564C339A78C10282" Guid="{62F8D0F6-D4FF-4255-8B5B-FC912F25C3BB}">
<File Id="fil4085D9852FFDBCA1DA05DFA41B6B63A2" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\stop.sym" />
</Component>
<Component Id="cmpA4CE7D272C69DDD6A95DF0D02AC0D3C0" Guid="{C1242779-E7D6-43A3-B210-D631DEFDF56B}">
<File Id="filEB57C82FF4DA64043A496E5A9ABF6802" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\switch.sym" />
</Component>
@ -457,6 +460,7 @@
<ComponentRef Id="cmpC0CDD9987356F9D8308F1F96CAA35403" />
<ComponentRef Id="cmp530072B273A8627AFC7F2E628B5116CE" />
<ComponentRef Id="cmpC76DA8327344C4B4AB04EF665B72B736" />
<ComponentRef Id="cmp57911CE62A560E61564C339A78C10282" />
<ComponentRef Id="cmpA4CE7D272C69DDD6A95DF0D02AC0D3C0" />
<ComponentRef Id="cmp92D378095B64443F3454801FDB1FBF50" />
<ComponentRef Id="cmpB88C8475423DC9A430B279627C98B455" />

View File

@ -171,8 +171,14 @@
#### this is the default:
# set initial_geometry {900x600}
#### initial geometry of load /save / insert component file selector
# set file_dialog_default_geometry 800x600
#### initial size of the load_file_dialog (the file selector) dialog box
# set file_dialog_default_geometry 700x680+100+40
#### load_file_dialog directory list (+ recent if shown) X width in pixels
# set file_dialog_sp0 350
#### load_file_dialog recent components list X width in pixels
# set file_dialog_sp1 100
#### load_file_dialog components list Y height in pixels
# set file_dialog_v_sp0 420
#### display full path (1) or only name (0) for component directories. Default: 1
# set load_file_dialog_fullpath 1
@ -195,6 +201,11 @@
#### default: 0
# set persistent_command 1
#### if set to 0 users must click a point after hitting a command key
#### like 'w(ire)', 'l(ine)' and so on.
#### default is 1 (hitting the command key sets also the first point).
# set infix_interface 0
#### if set to 1 allow click & drag objects in the schematic
#### to move them without keyboard commands ('m')
#### default: enabled (1)
@ -256,8 +267,24 @@
#### enable drawing crosshairs at mouse coordinates. Default: disabled (0)
# set draw_crosshair 1
#### set crosshair layer; Default 3 (TEXTLAYER)
# set crosshair_layer 3
#### set crosshair layer; Default 8 (Yellow)
# set crosshair_layer 8
#### set crosshair size; Default: 0 (full screen spanning crosshair)
# set crosshair_size 5
#### enable drawing a diamond-shaped cursor at the closest circuit endpoint. Default: disabled (0)
# set snap_cursor 1
#### set snap_cursor_size; Default: 6 (Diamond-shaped cursor that snaps to nearest circuit endpoint)
# set snap_cursor_size 6
#### set cadence_compat; Default: 0 (Cadence-style keybinds are not used by default)
# set cadence_compat 1
#### if set, then, when cursor (regardless of style) is on an object, and user clicks (though mouse pointer is not on the object),
#### the object is selected. Default: 0
# set use_cursor_for_selection 1
#### enable to scale grid point size as done with lines at close zoom, default: 0
# set big_grid_points 0
@ -510,7 +537,10 @@ set editor {notepad.exe}
# }
# }
###########################################################################
#### TCL COMMANDS TO BE EXECUTED AFTER GENERATING NETLIST
###########################################################################
# set netlist_postprocess {textfile $netlist_dir/[xschem get netlist_name fallback]}
###########################################################################
#### WEB URL DOWNLOAD HELPER APPLICATION
@ -553,6 +583,14 @@ set editor {notepad.exe}
#### default: 0 (not set)
# set show_hidden_texts 1
###########################################################################
#### USE CTRL MODIFIER TO OPERATE ON GRAPHS WITH MOUSE & KEYBOARD
###########################################################################
#### if enabled forces to hold Control key pressed to operate on graphs
#### to prevent "graph event stealing to schematic"
#### Default: 0 (not set)
# set graph_use_ctrl_key 1
###########################################################################
#### HIDE GRAPHS IF NO SPICE DATA LOADED
###########################################################################
@ -560,6 +598,16 @@ set editor {notepad.exe}
#### default: not enabled (0)
# set hide_empty_graphs 0
###########################################################################
#### ATTACH HOOK FUNCTION TO CURSOR 2 MOVEMENT
###########################################################################
#### if enabled whenever the cursor2 is moved the specified script is
#### executed. Examples:
#### set cursor_2_hook {conducting_devices 10e-3 nodraw}
#### set cursor_2_hook {hilight_high_nets 0 1.8 nodraw}
#### this can be used to add backannotation actions.
###########################################################################
#### LIVE BACKANNOTATION OF DATA AT CURSOR 2 (B) POSITION
###########################################################################
@ -591,3 +639,6 @@ set editor {notepad.exe}
#### Default: not enabled (0)
# set fix_mouse_coord 0
#### redefine some variables to emulate Cadence UI / bindkeys
# source /home/schippes/share/xschem/cadence_style_rc

View File

@ -551,6 +551,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> abort_operation</kbd></li><pre>
@ -588,7 +589,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
all inside selected instances will be deleted </pre>
<li><kbd> build_colors</kbd></li><pre>
Rebuild color palette using values of tcl vars dim_value and dim_bg </pre>
<li><kbd> callback winpath event mx my key button aux state</kbd></li><pre>
<li><kbd> callback win_path event mx my key button aux state</kbd></li><pre>
Invoke the callback event dispatcher with a software event </pre>
<li><kbd> case_insensitive 1|0</kbd></li><pre>
Set case insensitive symbol lookup. Use only on case insensitive filesystems </pre>
@ -713,6 +714,8 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> escape_chars source [charset]</kbd></li><pre>
escape tcl special characters with backslash
if charset is given escape characters in charset </pre>
<li><kbd> eval_expr str</kbd></li><pre>
debug function: evaluate arithmetic expression in str </pre>
<li><kbd> exit [exit_code] [closewindow] [force]</kbd></li><pre>
Exit the program, ask for confirm if current file modified.
if exit_code is given exit with its value, otherwise use 0 exit code
@ -757,6 +760,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> bbox </kbd> bounding box schematic </li>
<li><kbd> bbox_hilighted </kbd> bounding box of highlinhted objects </li>
<li><kbd> bbox_selected </kbd> bounding box of selected objects </li>
<li><kbd> build_date </kbd> time and date this file was built. </li>
<li><kbd> cadlayers </kbd> number of layers </li>
<li><kbd> case_insensitive </kbd> case_insensitive symbol matching </li>
<li><kbd> color_ps </kbd> color postscript flag </li>
@ -974,7 +978,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Example: xschem instances_to_net PANEL
--&gt; { {Vsw} {plus} {580} {-560} } { {p2} {p} {660} {-440} }
{ {Vpanel1} {minus} {600} {-440} } </pre>
<li><kbd> is_symgen symbol</kbd></li><pre>
<li><kbd> is_generator symbol</kbd></li><pre>
tell if 'symbol' is a generator (symbol(param1,param2,...) </pre>
<li><kbd> line [x1 y1 x2 y2] [pos] [propstring] [draw]</kbd></li><pre>
if 'x1 y1 x2 y2'is given place line on current
@ -1025,6 +1029,11 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
If 'f' is given output stderr messages to file 'f'
if 'f' is not given and a file log is open, close log
file and resume logging to stderr </pre>
<li><kbd> load_symbol [symbol_file]</kbd></li><pre>
Load specified symbol_file
Returns:
&gt;= 0: symbol is already loaded or has been loaded
&lt; 0: symbol was not loaded</pre>
<li><kbd> log_write text</kbd></li><pre>
write given string to log file, so tcl can write messages on the log file</pre>
<li><kbd> logic_get_net net_name</kbd></li><pre>
@ -1096,22 +1105,22 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> new_process [f]</kbd></li><pre>
Start a new xschem process for a schematic.
If 'f' is given load specified schematic. </pre>
<li><kbd> new_schematic create|destroy|destroy_all|switch winpath file [draw]</kbd></li><pre>
<li><kbd> new_schematic create|destroy|destroy_all|switch win_path file [draw]</kbd></li><pre>
Open/destroy a new tab or window
create: create new empty window or with 'file' loaded if 'file' given.
The winpath must be given (even {} is ok).
non empty winpath ({1}) will avoid warnings if opening the
The win_path must be given (even {} is ok).
non empty win_path ({1}) will avoid warnings if opening the
same file multiple times.
destroy: destroy tab/window identified by winpath. Example:
destroy: destroy tab/window identified by win_path. Example:
xschem new_schematic destroy .x1.drw
destroy_all: close all tabs/additional windows
if the 'force'argument is given do not issue a warning if modified
tabs are about to be closed.
switch: switch context to specified 'winpath' window or specified schematic name
switch: switch context to specified 'win_path' window or specified schematic name
If 'draw' is given and set to 0 do not redraw after switching tab
(only tab i/f)
Main window/tab has winpath set to .drw,
Additional windows/tabs have winpath set to .x1.drw, .x2.drw and so on...</pre>
Main window/tab has win_path set to .drw,
Additional windows/tabs have win_path set to .x1.drw, .x2.drw and so on...</pre>
<li><kbd> only_probes</kbd></li><pre>
dim schematic to better show highlights </pre>
<li><kbd> origin x y [zoom]</kbd></li><pre>
@ -1146,7 +1155,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Start a GUI placement of a text object </pre>
<li><kbd> polygon</kbd></li><pre>
Start a GUI placement of a polygon </pre>
<li><kbd> preview_window create|draw|destroy|close [winpath] [file]</kbd></li><pre>
<li><kbd> preview_window create|draw|destroy|close [win_path] [file]</kbd></li><pre>
destroy: will delete preview schematic data and destroy container window
close: same as destroy but leave the container window.
Used in fileselector to show a schematic preview.</pre>
@ -1548,7 +1557,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> switch [window_path |schematic_name]</kbd></li><pre>
Switch context to indicated window path or schematic name
returns 0 if switch was successfull or 1 in case of errors
(no tabs/windows present or no matching winpath / schematic name
(no tabs/windows present or no matching win_path / schematic name
found).</pre>
<li><kbd> symbols [n | 'derived_symbols']</kbd></li><pre>
if 'n' given list symbol with name or number 'n', else list all
@ -1723,7 +1732,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
</ul>

View File

@ -15,7 +15,7 @@ put /local/install_shares {
symgen.awk order_labels.awk sort_labels.awk spice.awk tedax.awk verilog.awk
vhdl.awk hspice_backannotate.tcl add_custom_menu.tcl create_graph.tcl
add_custom_button.tcl change_index.tcl icon.xpm resources.tcl xschemrc
ngspice_backannotate.tcl gschemtoxschem.awk mouse_bindings.tcl
ngspice_backannotate.tcl gschemtoxschem.awk mouse_bindings.tcl cadence_style_rc
place_sym_pins.tcl place_pins.tcl make_sch_from_spice.awk make_sym_from_spice.awk
}
@ -50,7 +50,7 @@ expandlabel.c expandlabel.h: expandlabel.y
bison -d -o expandlabel.c expandlabel.y
eval_expr.c: eval_expr.y
bison -o eval_expr.c eval_expr.y
bison -p kk -o eval_expr.c eval_expr.y
parselabel.o: expandlabel.h

View File

@ -45,7 +45,7 @@ unsigned int hash_file(const char *f, int skip_path_lines)
int cr = 0;
unsigned int h=5381;
char *line = NULL;
fd = fopen(f, "r"); /* windows won't return \r in the lines and we chop them out anyway in the code */
fd = my_fopen(f, "r"); /* windows won't return \r in the lines and we chop them out anyway in the code */
if(fd) {
while((line = my_fgets(fd, &n))) {
/* skip lines of type: '** sch_path: ...' or '-- sch_path: ...' or '// sym_path: ...'

10
src/cadence_style_rc Normal file
View File

@ -0,0 +1,10 @@
# run with $> xschem --script /path/to/cadence_style_rc
set draw_crosshair 1
set crosshair_size 2
set infix_interface 0
set cadence_compat 1
set orthogonal_wiring 1
set snap_cursor 1
set snap_cursor_size 4
set persistent_command 1
set use_cursor_for_selection 1

View File

@ -460,7 +460,7 @@ cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_t r
* @return Returns a pointer to a cairo_surface_t structure. It should be
* checked with cairo_surface_status() for errors.
* @note If the returned surface is invalid you can use errno to determine
* further reasons. Errno is set according to fopen(3) and malloc(3). If you
* further reasons. Errno is set according to my_fopen(3) and malloc(3). If you
* intend to check errno you shall set it to 0 before calling this function
* because it does not modify errno itself.
*/
@ -520,7 +520,7 @@ static cairo_status_t cj_read(void *closure, unsigned char *data, unsigned int l
* @return Returns a pointer to a cairo_surface_t structure. It should be
* checked with cairo_surface_status() for errors.
* @note If the returned surface is invalid you can use errno to determine
* further reasons. Errno is set according to fopen(3) and malloc(3). If you
* further reasons. Errno is set according to my_fopen(3) and malloc(3). If you
* intend to check errno you shall set it to 0 before calling this function
* because it does not modify errno itself.
*/

View File

@ -151,6 +151,8 @@ void abort_operation(void)
tcleval("set constr_mv 0" );
dbg(1, "abort_operation(): Escape: ui_state=%d, last_command=%d\n", xctx->ui_state, xctx->last_command);
xctx->constr_mv=0;
if(xctx->ui_state & STARTPOLYGON) new_polygon(END, xctx->mousex_snap, xctx->mousey_snap);
if(xctx->last_command && xctx->ui_state & (STARTWIRE | STARTLINE)) {
if(xctx->ui_state & STARTWIRE) new_wire(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
if(xctx->ui_state & STARTLINE) new_line(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
@ -220,6 +222,7 @@ static void start_line(double mx, double my)
if(xctx->constr_mv == 1) my = xctx->my_double_save;
if(xctx->constr_mv == 2) mx = xctx->mx_double_save;
} else {
xctx->manhattan_lines = 0;
xctx->mx_double_save=mx;
xctx->my_double_save=my;
}
@ -228,30 +231,31 @@ static void start_line(double mx, double my)
static void start_wire(double mx, double my)
{
dbg(1, "start_wire(): ui_state=%d, ui_state2=%d last_command=%d\n", xctx->ui_state, xctx->ui_state2, xctx->last_command);
xctx->last_command = STARTWIRE;
if(xctx->ui_state & STARTWIRE) {
if(tclgetboolvar("orthogonal_wiring") && !tclgetboolvar("constr_mv")){
xctx->constr_mv = xctx->manhattan_lines;
new_wire(CLEAR, mx, my);
redraw_w_a_l_r_p_z_rubbers(1);
}
if(xctx->constr_mv != 2) {
xctx->mx_double_save = mx;
}
if(xctx->constr_mv != 1) {
xctx->my_double_save = my;
}
if(xctx->constr_mv == 1) my = xctx->my_double_save;
if(xctx->constr_mv == 2) mx = xctx->mx_double_save;
} else {
xctx->mx_double_save=mx;
xctx->my_double_save=my;
}
new_wire(PLACE,mx, my);
if(tclgetboolvar("orthogonal_wiring") && !tclgetboolvar("constr_mv")){
xctx->constr_mv = 0;
}
dbg(1, "start_wire(): ui_state=%d, ui_state2=%d last_command=%d\n",
xctx->ui_state, xctx->ui_state2, xctx->last_command);
xctx->last_command = STARTWIRE;
if(xctx->ui_state & STARTWIRE) {
if(tclgetboolvar("orthogonal_wiring") && !tclgetboolvar("constr_mv")){
xctx->constr_mv = xctx->manhattan_lines;
new_wire(CLEAR, mx, my);
redraw_w_a_l_r_p_z_rubbers(1);
}
if(xctx->constr_mv != 2) {
xctx->mx_double_save = mx;
}
if(xctx->constr_mv != 1) {
xctx->my_double_save = my;
}
if(xctx->constr_mv == 1) my = xctx->my_double_save;
if(xctx->constr_mv == 2) mx = xctx->mx_double_save;
} else {
xctx->mx_double_save=mx;
xctx->my_double_save=my;
}
new_wire(PLACE,mx, my);
if(tclgetboolvar("orthogonal_wiring") && !tclgetboolvar("constr_mv")){
xctx->constr_mv = 0;
}
}
static double interpolate_yval(int idx, int p, double x, int sweep_idx, int point_not_last)
@ -1641,11 +1645,11 @@ static int end_place_move_copy_zoom()
}
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
return 1;
return 0;
}
else if(xctx->ui_state & STARTARC) {
new_arc(SET, 0, xctx->mousex_snap, xctx->mousey_snap);
return 1;
return 0;
}
else if(xctx->ui_state & STARTLINE) {
if(tclgetboolvar("persistent_command")) {
@ -1663,11 +1667,11 @@ static int end_place_move_copy_zoom()
}
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
return 1;
return 0;
}
else if(xctx->ui_state & STARTRECT) {
new_rect(PLACE|END,xctx->mousex_snap, xctx->mousey_snap);
return 1;
return 0;
}
else if(xctx->ui_state & STARTPOLYGON) {
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
@ -1677,7 +1681,7 @@ static int end_place_move_copy_zoom()
xctx->my_double_save=xctx->mousey_snap;
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
return 1;
return 0;
}
else if(xctx->ui_state & STARTMOVE) {
move_objects(END,0,0,0);
@ -1721,7 +1725,7 @@ void snapped_wire(double c_snap)
new_wire(PLACE|END, x, y);
xctx->constr_mv=0;
tcleval("set constr_mv 0" );
if((xctx->ui_state & MENUSTART) && !tclgetboolvar("persistent_command") ) xctx->ui_state &= ~MENUSTART;
if((xctx->ui_state & MENUSTART) && !tclgetboolvar("persistent_command") ) xctx->ui_state &= ~MENUSTART; /*CD*/
}
}
@ -2459,6 +2463,7 @@ static void handle_enter_notify(int draw_xhair, int crosshair_size)
xctx->mousey_snap = -340;
merge_file(1, ".sch");
}
return;
}
@ -2471,6 +2476,7 @@ static void handle_motion_notify(int event, KeySym key, int state, int rstate, i
}
if(draw_xhair) {
draw_crosshair(1, state); /* when moving mouse: first action is delete crosshair, will be drawn later */
if(snap_cursor && wire_draw_active) draw_snap_cursor(1);
}
if(snap_cursor && wire_draw_active) draw_snap_cursor(1);
/* pan schematic */
@ -2582,6 +2588,7 @@ static void handle_motion_notify(int event, KeySym key, int state, int rstate, i
draw_crosshair(2, state); /* what = 2(draw) */
}
if(snap_cursor && wire_draw_active) draw_snap_cursor(2);
return;
}
@ -2777,12 +2784,12 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
{
int x;
xctx->fill_pattern++;
if(xctx->fill_pattern==3) xctx->fill_pattern=0;
if(xctx->fill_pattern==2) xctx->fill_pattern=0;
if(xctx->fill_pattern==1) {
tcleval("alert_ { Stippled pattern fill} {}");
for(x=0;x<cadlayers;x++) {
if(xctx->fill_type[x]==1) XSetFillStyle(display,xctx->gcstipple[x],FillSolid);
if(xctx->fill_type[x]==2) XSetFillStyle(display,xctx->gcstipple[x],FillSolid);
else XSetFillStyle(display,xctx->gcstipple[x],FillStippled);
}
}
@ -2837,6 +2844,7 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
{
int prev_state = xctx->ui_state;
if(xctx->semaphore >= 2) return;
if(infix_interface) {
start_wire(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTWIRE) {
@ -2881,7 +2889,7 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
{
view_zoom(0.0); return;
}
if(key=='z' && EQUAL_MODMASK) /* toggle snap-cursor option */
if(key=='z' && EQUAL_MODMASK && cadence_compat) /* toggle snap-cursor option */
{
if(tclgetboolvar("snap_cursor")) {
tclsetvar("snap_cursor", "0");
@ -3435,7 +3443,6 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
int tool = 0;
int exists = 0;
char *tool_name = NULL;
char str[200];
if(xctx->semaphore >= 2) return;
tcleval("winfo exists .graphdialog");
@ -3451,7 +3458,7 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
if(exists) {
if(!tool) {
tool = tclgetintvar("sim(spicewave,default)");
my_snprintf(str, S(str), "sim(spicewave,%d,name)", tool);
my_snprintf(str, PATH_MAX + 100, "sim(spicewave,%d,name)", tool);
my_strdup(_ALLOC_ID_, &tool_name, tclgetvar(str));
dbg(1,"callback(): tool_name=%s\n", tool_name);
if(strstr(tool_name, "Gaw")) tool=GAW;
@ -3475,7 +3482,7 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
}
if(key=='g' && rstate==ControlMask) /* set snap factor 20161212 */
{
my_snprintf(str, S(str),
my_snprintf(str, S(str),
"input_line {Enter snap value (default: %.16g current: %.16g)} {xschem set cadsnap} {%g} 10",
CADSNAP, c_snap, c_snap);
tcleval(str);
@ -4087,6 +4094,7 @@ static void handle_key_press(int event, KeySym key, int state, int rstate, int m
break_wires_at_pins(1);
return;
}
return;
}
@ -4094,6 +4102,8 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
double c_snap, int draw_xhair, int crosshair_size, int enable_stretch, int aux)
{
dbg(1, "callback(): ButtonPress ui_state=%d state=%d\n",xctx->ui_state,state);
int use_cursor_for_sel = tclgetintvar("use_cursor_for_selection");
int excl = xctx->ui_state & (STARTWIRE | STARTRECT | STARTLINE | STARTPOLYGON | STARTARC);
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
return;
@ -4105,7 +4115,7 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
}
/* select instance and connected nets stopping at wire junctions */
if(button == Button3 && state == ControlMask && xctx->semaphore <2)
if(!excl && button == Button3 && state == ControlMask && xctx->semaphore <2)
{
Selected sel;
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
@ -4113,17 +4123,19 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
}
/* break wire at mouse coordinates, move break point to nearest grid point */
else if(button == Button3 && EQUAL_MODMASK && !(state & ShiftMask) && xctx->semaphore <2)
else if(!excl && button == Button3 && EQUAL_MODMASK &&
!(state & ShiftMask) && xctx->semaphore <2)
{
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 1);
}
/* break wire at mouse coordinates */
else if(button == Button3 && EQUAL_MODMASK && (state & ShiftMask) && xctx->semaphore <2)
else if(!excl && button == Button3 && EQUAL_MODMASK &&
(state & ShiftMask) && xctx->semaphore <2)
{
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 0);
}
/* select instance and connected nets NOT stopping at wire junctions */
else if(button == Button3 && state == ShiftMask && xctx->semaphore <2)
else if(!excl && button == Button3 && state == ShiftMask && xctx->semaphore <2)
{
Selected sel;
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
@ -4131,13 +4143,13 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
}
/* moved to Button3 release */
/*
* else if(button == Button3 && state == 0 && xctx->semaphore <2) {
* else if(button == Button3 && state == 0 && xctx->semaphore <2) {
* context_menu_action(xctx->mousex_snap, xctx->mousey_snap);
* }
*/
/* zoom rectangle by right clicking and drag */
else if(button == Button3 && state == 0 && xctx->semaphore < 2) {
else if(!excl && button == Button3 && state == 0 && xctx->semaphore < 2) {
zoom_rectangle(START);return;
}
@ -4187,18 +4199,18 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
if(tclgetboolvar("persistent_command") && xctx->last_command) {
if(xctx->last_command == STARTLINE) start_line(xctx->mousex_snap, xctx->mousey_snap);
if(xctx->last_command == STARTWIRE){
if(tclgetboolvar("snap_cursor")
&& (xctx->prev_snapx == xctx->mousex_snap
&& xctx->prev_snapy == xctx->mousey_snap)
&& (xctx->ui_state & STARTWIRE)
&& xctx->closest_pin_found){
new_wire(PLACE|END, xctx->mousex_snap, xctx->mousey_snap);
xctx->ui_state &= ~STARTWIRE;
}
else
start_wire(xctx->mousex_snap, xctx->mousey_snap);
}
return;
if(tclgetboolvar("snap_cursor")
&& (xctx->prev_snapx == xctx->mousex_snap
&& xctx->prev_snapy == xctx->mousey_snap)
&& (xctx->ui_state & STARTWIRE)
&& xctx->closest_pin_found){
new_wire(PLACE|END, xctx->mousex_snap, xctx->mousey_snap);
xctx->ui_state &= ~STARTWIRE;
}
else
start_wire(xctx->mousex_snap, xctx->mousey_snap);
}
return;
}
/* handle all object insertions started from Tools/Edit menu */
if(check_menu_start_commands(c_snap, mx, my)) return;
@ -4207,7 +4219,7 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
if(end_place_move_copy_zoom()) return;
/* Button1Press to select objects */
if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) {
if(!excl) {
Selected sel;
int already_selected = 0;
int prev_last_sel = xctx->lastsel;
@ -4234,7 +4246,7 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
/* find closest object. Use snap coordinates if full crosshair is enabled
* since the mouse pointer is obscured and crosshair is snapped to grid points */
if(draw_xhair) {
if(draw_xhair && (use_cursor_for_sel || crosshair_size == 0)) {
sel = find_closest_obj(xctx->mousex_snap, xctx->mousey_snap, 0);
} else {
sel = find_closest_obj(xctx->mousex, xctx->mousey, 0);
@ -4330,8 +4342,9 @@ static void handle_button_press(int event, int state, int rstate, KeySym key, in
}
}
return;
}
} /* if(!excl) */
} /* button==Button1 */
return;
}
@ -4373,12 +4386,12 @@ static void handle_button_release(int event, KeySym key, int state, int button,
xctx->semaphore = savesem;
}
/* end wire creation when dragging in intuitive interface from an inst pin ow wire endpoint */
/*else if(state == Button1Mask && xctx->intuitive_interface
* && (xctx->ui_state & STARTWIRE) && !(xctx->ui_state & MENUSTART)) {*/
/* if(end_place_move_copy_zoom()) break;*/
/*}*/
/* end wire creation when dragging in intuitive interface from an inst pin or wire endpoint */
else if(state == Button1Mask && xctx->intuitive_interface && !tclgetboolvar("persistent_command")
&& (xctx->ui_state & STARTWIRE) && !(xctx->ui_state & MENUSTART)) {
if(end_place_move_copy_zoom()) return;
}
/* end intuitive_interface copy or move */
if(xctx->ui_state & STARTCOPY && xctx->drag_elements) {
copy_objects(END);
@ -4432,6 +4445,7 @@ static void handle_button_release(int event, KeySym key, int state, int button,
}
if(draw_xhair) draw_crosshair(3, state); /* restore crosshair when selecting / unselecting */
if(snap_cursor && wire_draw_active) draw_snap_cursor(3);
return;
}
@ -4471,9 +4485,10 @@ static void handle_double_click(int event, int state, KeySym key, int button,
}
}
}
}
}
}
/* main window callback */
/* mx and my are set to the mouse coord. relative to window */
/* win_path: set to .drw or sub windows .x1.drw, .x2.drw, ... */
@ -4493,12 +4508,12 @@ int enable_stretch = tclgetboolvar("enable_stretch");
int draw_xhair = tclgetboolvar("draw_crosshair");
int crosshair_size = tclgetintvar("crosshair_size");
int infix_interface = tclgetboolvar("infix_interface");
int rstate; /* (reduced state, without ShiftMask) */
int snap_cursor = tclgetboolvar("snap_cursor");
int cadence_compat = tclgetboolvar("cadence_compat");
int wire_draw_active = (xctx->ui_state & STARTWIRE) ||
((xctx->ui_state2 & MENUSTARTWIRE) && (xctx->ui_state & MENUSTART)) ||
(tclgetboolvar("persistent_command") && (xctx->last_command & STARTWIRE));
int rstate; /* (reduced state, without ShiftMask) */
/* this fix uses an alternative method for getting mouse coordinates on KeyPress/KeyRelease
* events. Some remote connection softwares do not generate the correct coordinates
@ -4537,6 +4552,7 @@ int rstate; /* (reduced state, without ShiftMask) */
} else {
tclvareval(xctx->top_path, ".statusbar.10 configure -state normal -text { }", NULL);
}
tclvareval(xctx->top_path, ".statusbar.7 configure -text $netlist_type", NULL);
tclvareval(xctx->top_path, ".statusbar.3 delete 0 end;",
xctx->top_path, ".statusbar.3 insert 0 $cadsnap",
@ -4583,7 +4599,7 @@ int rstate; /* (reduced state, without ShiftMask) */
state &= ~Mod2Mask; /* 20170511 filter out NumLock status */
state &= ~LockMask; /* filter out Caps Lock */
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 */
rstate &= ~Button1Mask; /* ignore button-1 */
if(xctx->semaphore >= 2)
{

View File

@ -1591,9 +1591,9 @@ void drawarc(int c, int what, double x, double y, double r, double a, double b,
(int)(xx2-xx1), (int)(yy2-yy1), (int)(a*64), (int)(b*64));
}
if(xctx->fill_pattern && (xctx->fill_type[c] || arc_fill == 3) ){
if(xctx->fill_pattern && (xctx->fill_type[c] || arc_fill == 2) ){
if(arc_fill & 2) gc = xctx->gc[c];
if(arc_fill == 2) gc = xctx->gc[c];
else gc = xctx->gcstipple[c];
if(arc_fill) {
if(xctx->draw_window)
@ -1631,8 +1631,8 @@ void filledrect(int c, int what, double rectx1,double recty1,double rectx2,doubl
if(!has_x) return;
if(!xctx->fill_pattern) return;
if(fill != 3 && !xctx->fill_type[c]) return;
if(fill == 3) { /* full fill */
if(fill != 2 && !xctx->fill_type[c]) return;
if(fill == 2) { /* full fill */
gc = xctx->gc[c];
r = rf;
i = &iif;
@ -1782,7 +1782,7 @@ void arc_bbox(double x, double y, double r, double a, double b,
/* Convex Nonconvex Complex */
#define Polygontype Nonconvex
/* fill = 1: stippled fill, fill == 3: solid fill */
/* fill = 1: stippled fill, fill == 2: solid fill */
void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int fill)
{
const double bez_steps = 1.0/32.0; /* divide the t = [0,1] interval into 32 steps */
@ -1846,7 +1846,7 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int
XDrawLines(display, w, gc, p, i, CoordModeOrigin);
if(fill == 1)
XFillPolygon(display, w, xctx->gcstipple[c], p, i, Polygontype, CoordModeOrigin);
else if(fill==3)
else if(fill==2)
XFillPolygon(display, w, xctx->gc[c], p, i, Polygontype, CoordModeOrigin);
}
@ -1882,7 +1882,7 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil
for(i=0;i<points; ++i) p[i].x = (short)X_TO_SCREEN(x[i]);
for(i=0;i<points; ++i) p[i].y = (short)Y_TO_SCREEN(y[i]);
}
fill = xctx->fill_pattern && ((xctx->fill_type[c] && poly_fill == 1) || poly_fill == 3 ) &&
fill = xctx->fill_pattern && ((xctx->fill_type[c] && poly_fill == 1) || poly_fill == 2 ) &&
(x[0] == x[points-1]) && (y[0] == y[points-1]);
bezier = (flags & 1) && (points > 2);
if(dash) {
@ -1893,19 +1893,19 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil
}
if(xctx->draw_window) {
if(bezier) {
drawbezier(xctx->window, xctx->gc[c], c, x, y, points, fill | (poly_fill & 2) );
drawbezier(xctx->window, xctx->gc[c], c, x, y, points, fill ? poly_fill : 0 );
} else {
XDrawLines(display, xctx->window, xctx->gc[c], p, points, CoordModeOrigin);
}
}
if(xctx->draw_pixmap) {
if(bezier) {
drawbezier(xctx->save_pixmap, xctx->gc[c], c, x, y, points, fill | (poly_fill & 2) );
drawbezier(xctx->save_pixmap, xctx->gc[c], c, x, y, points, fill ? poly_fill : 0);
} else {
XDrawLines(display, xctx->save_pixmap, xctx->gc[c], p, points, CoordModeOrigin);
}
}
if(poly_fill & 2) gc = xctx->gc[c];
if(poly_fill == 2) gc = xctx->gc[c];
else gc = xctx->gcstipple[c];
if(fill && !bezier) {
if(xctx->draw_window)
@ -2836,9 +2836,9 @@ static void draw_graph_grid(Graph_ctx *gr, void *ct)
/* clipping everything outside container area */
/* background */
filledrect(0, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 3, -1, -1);
filledrect(0, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1);
/* graph bounding box */
drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 2, -1, -1);
drawrect(GRIDLAYER, NOW, gr->rx1, gr->ry1, gr->rx2, gr->ry2, 0, -1, -1);
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD, gr->rx1, gr->ry1, gr->rx2, gr->ry2);
@ -3133,7 +3133,7 @@ static void draw_cursor(double active_cursorx, double other_cursorx, int cursor_
else
my_snprintf(tmpstr, S(tmpstr), "%s", dtoa_eng(active_cursorx));
text_bbox(tmpstr, txtsize, txtsize, 2, flip, 0, 0, xx + xoffs, gr->ry2-1, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
filledrect(0, NOW, tx1, ty1, tx2, ty2, 2, -1, -1);
draw_string(cursor_color, NOW, tmpstr, 2, flip, 0, 0, xx + xoffs, gr->ry2-1, txtsize, txtsize);
}
}
@ -3198,7 +3198,7 @@ static void draw_hcursor(double active_cursory, int cursor_color, Graph_ctx *gr)
th = (ty2 - ty1) / 2.; /* half text height */
ty1 -= th;
ty2 -= th;
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
filledrect(0, NOW, tx1, ty1, tx2, ty2, 2, -1, -1);
draw_string(cursor_color, NOW, tmpstr, 0, 0, 0, 0, gr->rx1 + 5, yy - th, txtsize, txtsize);
}
}
@ -3230,7 +3230,7 @@ static void draw_hcursor_difference(double c1, double c2, Graph_ctx *gr)
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);
filledrect(0, NOW, tx1, ty1, tx2, ty2, 2, -1, -1);
draw_string(3, NOW, tmpstr, 0, 0, 0, 1, xx, yy, txtsize, txtsize);
if( a > b) {
dtmp = a; a = b; b = dtmp;
@ -3487,10 +3487,12 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
} else {
if(gr->hilight_wave == wcnt) {
gr->hilight_wave = -1;
my_strdup2(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
my_strdup2(_ALLOC_ID_, &r->prop_ptr,
subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
} else {
gr->hilight_wave = wcnt;
my_strdup2(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
my_strdup2(_ALLOC_ID_, &r->prop_ptr,
subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
}
}
}
@ -3512,10 +3514,12 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
} else {
if(gr->hilight_wave == wcnt) {
gr->hilight_wave = -1;
my_strdup2(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
my_strdup2(_ALLOC_ID_, &r->prop_ptr,
subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
} else {
gr->hilight_wave = wcnt;
my_strdup2(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
my_strdup2(_ALLOC_ID_, &r->prop_ptr,
subst_token(r->prop_ptr, "hilight_wave", my_itoa(gr->hilight_wave)));
}
}
}
@ -4472,7 +4476,7 @@ static cairo_surface_t *get_surface_from_file(const char *filename, const char *
}
filesize = (size_t)buf.st_size;
if(filesize > 0) {
fd = fopen(filename, fopen_read_mode);
fd = my_fopen(filename, fopen_read_mode);
if(fd) {
size_t bytes_read;
filedata = my_malloc(_ALLOC_ID_, filesize);
@ -4530,7 +4534,7 @@ static cairo_surface_t *get_surface_from_file(const char *filename, const char *
#endif
}
if(!surface || cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
if(jpg != 1) dbg(0, "draw_image(): failure creating image surface from %s\n", filename);
if(jpg != 1) dbg(0, "get_surface_from_file(): failure creating image surface from %s\n", filename);
if(surface) cairo_surface_destroy(surface);
my_free(_ALLOC_ID_, &closure.buffer);
*buffer = NULL;
@ -4732,7 +4736,7 @@ int draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2,
cairo_translate(xctx->cairo_ctx, x, y);
cairo_rotate(xctx->cairo_ctx, rot * XSCH_PI * 0.5);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_ctx, scalex, -scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_ctx, -scalex, scaley);
else cairo_scale(xctx->cairo_ctx, scalex, scaley);
cairo_set_source_surface(xctx->cairo_ctx, emb_ptr->image, 0. , 0.);
cairo_rectangle(xctx->cairo_ctx, 0, 0, w , h );
@ -4986,7 +4990,7 @@ void draw(void)
draw_symbol(ADD, cc, i,c, 0, 0, 0.0, 0.0); /* ... then draw current layer */
}
}
filledrect(cc, END, 0.0, 0.0, 0.0, 0.0, 3, -1, -1); /* last parameter must be 3! */
filledrect(cc, END, 0.0, 0.0, 0.0, 0.0, 2, -1, -1); /* fill parameter must be 2! */
drawarc(cc, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0);
drawrect(cc, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1);
drawline(cc, END, 0.0, 0.0, 0.0, 0.0, 0, NULL);
@ -5013,7 +5017,7 @@ void draw(void)
xctx->wire[i].x2,xctx->wire[i].y2, 0, NULL);
}
update_conn_cues(cc, 1, xctx->draw_window);
filledrect(cc, END, 0.0, 0.0, 0.0, 0.0, 3, -1, -1); /* fill parameter must be 3! */
filledrect(cc, END, 0.0, 0.0, 0.0, 0.0, 2, -1, -1); /* fill parameter must be 2! */
drawline(cc, END, 0.0, 0.0, 0.0, 0.0, 0, NULL);
}
if(xctx->draw_single_layer ==-1 || xctx->draw_single_layer==TEXTLAYER) {

View File

@ -586,6 +586,19 @@ char *dtoa_prec(double i)
return s;
}
FILE *my_fopen(const char *f, const char *m)
{
struct stat buf;
FILE *fd = NULL;
int st;
st = stat(f, &buf);
if(st) return NULL; /* not existing or error */
if(!S_ISREG(buf.st_mode)) return NULL; /* not a regular file/symlink to a regular file */
fd = fopen(f, m);
return fd;
}
size_t my_mstrcat(int id, char **str, const char *add, ...)
{
va_list args;
@ -1020,7 +1033,7 @@ static int edit_rect_property(int x)
}
attr = get_tok_value(xctx->rect[c][n].prop_ptr,"fill", 0);
if(!strcmp(attr, "full")) xctx->rect[c][n].fill = 3;
if(!strcmp(attr, "full")) xctx->rect[c][n].fill = 2;
else if(!strboolcmp(attr, "false")) xctx->rect[c][n].fill = 0;
else xctx->rect[c][n].fill = 1;
@ -1203,11 +1216,11 @@ static int edit_arc_property(void)
old_fill = xctx->arc[c][i].fill;
fill_ptr = get_tok_value(xctx->arc[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr,"full") )
xctx->arc[c][i].fill =3; /* bit 1: solid fill (not stippled) */
xctx->arc[c][i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr,"true") )
xctx->arc[c][i].fill =1;
xctx->arc[c][i].fill = 1;
else
xctx->arc[c][i].fill =0;
xctx->arc[c][i].fill = 0;
old_dash = xctx->arc[c][i].dash;
dash = get_tok_value(xctx->arc[c][i].prop_ptr,"dash",0);
if( strcmp(dash, "") ) {
@ -1281,11 +1294,11 @@ static int edit_polygon_property(void)
fill_ptr = get_tok_value(xctx->poly[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr,"full") )
xctx->poly[c][i].fill =3; /* bit 1: solid fill (not stippled) */
xctx->poly[c][i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr,"true") )
xctx->poly[c][i].fill =1;
xctx->poly[c][i].fill = 1;
else
xctx->poly[c][i].fill =0;
xctx->poly[c][i].fill = 0;
dash = get_tok_value(xctx->poly[c][i].prop_ptr,"dash",0);
if( strcmp(dash, "") ) {
int d = atoi(dash);

View File

@ -2,7 +2,6 @@
#include <stdio.h>
#include <math.h> /* For math functions, cos(), sin(), etc. */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include "xschem.h"
@ -16,7 +15,8 @@ static int dbglev = 1;
struct symrec
{
char *name; /* name of symbol */
double (*fnctptr)(); /* value of a FNCT */
double (*fnctptr)(double); /* value of a FNCT */
double value;
struct symrec *next; /* link field */
};
@ -32,30 +32,42 @@ static void kkerror(char *s);
static double toint(double x);
static void get_expr(double x);
static void get_char(int c);
static double rnd6(double x) {return round_to_n_digits(x, 6);}
struct fn
{
char *fname;
double (*fnct)();
double value;
};
static int lex_state = 0;
struct fn fn_array[]
= {
{"int" , toint},
{"sin" , sin},
{"cos" , cos},
{"asin", asin},
{"acos", acos},
{"atan", atan},
{"log" , log10},
{"ln" , log},
{"exp" , exp},
{"sqrt", sqrt},
{0 , 0}
{"int" , toint, 0},
{"sin" , sin, 0},
{"cos" , cos, 0},
{"exp" , exp, 0},
{"asin" , asin, 0},
{"acos" , acos, 0},
{"atan" , atan, 0},
{"log" , log10, 0},
{"ln" , log, 0},
{"exp" , exp, 0},
{"sqrt" , sqrt, 0},
{"round" , rnd6, 0},
{"pi" , NULL, 3.141592653589793},
{"e" , NULL, 2.718281828459045},
{"k" , NULL, 1.380649e-23},
{"h" , NULL, 6.62607e-34},
{"echarge" , NULL, 1.60217646e-19},
{"abszero" , NULL, 273.15},
{"c" , NULL, 2.99792458e8},
{0 , 0, 0}
};
%}
%define api.prefix {kk}
/* %define api.prefix {kk} */
%union {
int c;
double val; /* For returning numbers. */
@ -63,7 +75,7 @@ symrec *tptr; /* For returning symbol-table pointers */
}
%token STREND 0
%token <c> CHAR
%token <c> XCHAR
%token EXPR /* expr( */
%token <val> NUM /* Simple double precision number */
%token <tptr> FNCT /* Variable and Function */
@ -81,14 +93,15 @@ input:
;
line:
CHAR {get_char($1);}
XCHAR {get_char($1);}
| EXPR exp ')' {get_expr($2);lex_state = 0;}
| EXPR '\'' exp '\'' ')' {get_expr($3);lex_state = 0;}
| EXPR exp error
;
exp: NUM {$$ = $1;}
| FNCT '(' exp ')' {$$ = $1 ? (*($1->fnctptr))($3) : 0.0;}
| FNCT '(' exp ')' {$$ = $1 ? ($1->fnctptr ? (*($1->fnctptr))($3) : 0.0) : 0.0;}
| FNCT {$$ = $1 ? $1->value : 0.0;}
| exp '+' exp {$$ = $1 + $3; }
| exp '-' exp {$$ = $1 - $3;}
| exp '*' exp {$$ = $1 * $3;}
@ -188,18 +201,21 @@ void eval_expr_init_table(void) /* puts arithmetic functions in table. */
{
ptr = putsym (fn_array[i].fname);
ptr->fnctptr = fn_array[i].fnct;
ptr->value = fn_array[i].value;
}
}
void eval_expr_clear_table(void)
{
symrec *ptr;
for (ptr = sym_table; ptr; ptr = ptr->next) {
symrec *ptr = sym_table;
while(ptr) {
symrec *tmp = ptr;
ptr = ptr->next;
my_free(_ALLOC_ID_, &(tmp->name));
my_free(_ALLOC_ID_, &tmp);
}
}
static int kklex()
{
@ -216,8 +232,8 @@ static int kklex()
c = *str++;
if(c) {
kklval.c = c;
dbg(dbglev, "lex(): CHAR; %c\n", c);
return CHAR;
dbg(dbglev, "lex(): XCHAR; %c\n", c);
return XCHAR;
} else {
dbg(dbglev, "lex(): STREND\n");
return STREND;
@ -237,7 +253,7 @@ static int kklex()
str--;
sscanf(str, "%99[.0-9a-zA-Z_]%n", s, &rd);
kklval.val = atof_spice(s);
kklval.val = atof_eng(s);
str += rd;
dbg(dbglev, "lex(): NUM: %s\n", s);
return NUM;

View File

@ -696,7 +696,7 @@ static int bus_search(const char*s)
}
#ifndef __unix__
static int win_regexec(const char *options, const char *pattern, const char *name)
int win_regexec(const char *options, const char *pattern, const char *name)
{
if (options!=NULL)
tclvareval("regexp {", options,"} {", pattern, "} {", name, "}", NULL);
@ -754,7 +754,7 @@ int search(const char *tok, const char *val, int sub, int sel, int match_case)
if(regcomp(&re, val , cflags)) return TCL_ERROR;
#else
if(!match_case) {
regexp_options = "-nocase";
my_strdup(_ALLOC_ID_, &regexp_options, "-nocase");
}
#endif
dbg(1, "search():val=%s\n", val);
@ -1014,6 +1014,8 @@ int search(const char *tok, const char *val, int sub, int sel, int match_case)
}
#ifdef __unix__
regfree(&re);
#else
my_free(_ALLOC_ID_, &regexp_options);
#endif
xctx->draw_window = save_draw;
my_free(_ALLOC_ID_, &tmpname);
@ -2224,7 +2226,7 @@ void draw_hilight_net(int on_window)
((c==TEXTWIRELAYER || c==TEXTLAYER) && symptr->texts)) {
draw_symbol(ADD, col, i,c,0,0,0.0,0.0);
}
filledrect(col, END, 0.0, 0.0, 0.0, 0.0, 3, -1, -1); /* last parameter must be 3! */
filledrect(col, END, 0.0, 0.0, 0.0, 0.0, 2, -1, -1); /* last parameter must be 2! */
drawarc(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0);
drawrect(col, END, 0.0, 0.0, 0.0, 0.0, 0, -1, -1);
drawline(col, END, 0.0, 0.0, 0.0, 0.0, 0, NULL);

View File

@ -1665,8 +1665,7 @@ int sym_vs_sch_pins(int all)
/* pass through symbols, duplicated pins: do not check with schematic */
if(rects > unique_pins) continue;
get_sch_from_sym(filename, xctx->sym + i, -1, 0);
if(!stat(filename, &buf)) {
fd = fopen(filename, "r");
if(!stat(filename, &buf) && (fd = my_fopen(filename, fopen_read_mode))) {
pin_cnt = 0;
endfile = 0;
f_version[0] = '\0';

View File

@ -111,10 +111,11 @@ static void check_opt(char *opt, char *optval, int type)
} else if( (type == SHORT && *opt == 'l') || (type == LONG && !strcmp("log", opt)) ) {
if(optval) {
errfp = fopen(optval, "w");
setvbuf(errfp, NULL, _IOLBF, 0); /* line (_IOLBF) or disable (_IONBF) buffering on error log */
if(!errfp) {
errfp = stderr;
dbg(0, "Problems opening log file: %s\n", optval);
} else {
setvbuf(errfp, NULL, _IOLBF, 0); /* line (_IOLBF) or disable (_IONBF) buffering on error log */
}
}
} else if( (type == SHORT && *opt == 'o') || (type == LONG && !strcmp("netlist_path", opt)) ) {

View File

@ -120,11 +120,11 @@ static void merge_box(FILE *fd)
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3;
ptr[i].fill = 2;
else if( !strboolcmp(fill_ptr, "false") )
ptr[i].fill =0;
ptr[i].fill = 0;
else
ptr[i].fill =1;
ptr[i].fill = 1;
set_rect_flags(&xctx->rect[c][i]); /* set cached .flags bitmask from on attributes */
select_box(c,i, SELECTED, 1, 1);
xctx->rects[c]++;
@ -159,11 +159,11 @@ static void merge_arc(FILE *fd)
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3; /* bit 1: solid fill (not stippled) */
ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr, "true") )
ptr[i].fill =1;
ptr[i].fill = 1;
else
ptr[i].fill =0;
ptr[i].fill = 0;
dash = get_tok_value(ptr[i].prop_ptr,"dash",0);
if(strcmp(dash, "")) {
int d = atoi(dash);
@ -219,11 +219,11 @@ static void merge_polygon(FILE *fd)
load_ascii_string( &ptr[i].prop_ptr, fd);
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3; /* bit 1: solid fill (not stippled) */
ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr, "true") )
ptr[i].fill =1;
ptr[i].fill = 1;
else
ptr[i].fill =0;
ptr[i].fill = 0;
dash = get_tok_value(ptr[i].prop_ptr,"dash",0);
if(strcmp(dash, "")) {
int d = atoi(dash);
@ -379,7 +379,7 @@ void merge_file(int selection_load, const char ext[])
my_free(_ALLOC_ID_, &cmd);
} else fd = NULL;
} else {
fd=fopen(name, fopen_read_mode);
fd=my_fopen(name, fopen_read_mode);
}
if(fd) {
xctx->prep_hi_structs=0;

View File

@ -301,7 +301,6 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
rwi = (int)(rw * scale + 1.0);
rhi = (int)(rh * scale + 1.0);
dbg(1, "graph size: %dx%d\n", rwi, rhi);
dbg(1, "ps_embedded_graph: saving zoom\n");
save_restore_zoom(1, &zi);
set_viewport_size(rwi, rhi, xctx->lw);
@ -354,7 +353,6 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
cairo_surface_destroy(png_sfc);
xctx->draw_pixmap = 1;
tclsetboolvar("draw_grid", save_draw_grid);
dbg(1, "ps_embedded_graph: restoring zoom\n");
save_restore_zoom(0, &zi);
resetwin(1, 1, 1, 0, 0);
change_linewidth(xctx->lw);
@ -445,11 +443,27 @@ static void ps_xdrawpoint(int layer, double x1, double y1)
fprintf(fd, "%g %g %g %g L\n", x1, y1,x1,y1);
}
static void ps_xfillrectange(int layer, double x1, double y1, double x2,
/* fill_pattern:
* 0 : no fill
* 1 : stippled fill
* 2 : solid fill
*
* fill_type[i]:
* 0 : no fill
* 1 : patterned (stippled) fill
* 2 : solid fill
*
* fill:
* 0 : no fill
* 1 : stippled fill
* 2 : solid fill
*/
static void ps_xfillrectangle(int layer, double x1, double y1, double x2,
double y2, int fill)
{
fprintf(fd, "%g %g %g %g R\n", x1,y1,x2-x1,y2-y1);
if(fill && (xctx->fill_type[layer] == 1) && xctx->fill_pattern) {
if(xctx->fill_pattern && xctx->fill_type[layer] && fill) {
fprintf(fd, "%g %g %g %g RF\n", x1,y1,x2-x1,y2-y1);
/* fprintf(fd,"fill\n"); */
}
@ -547,7 +561,8 @@ static void ps_drawpolygon(int c, int what, double *x, double *y, int points, in
}
static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2, int dash, int fill)
static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2,
int dash, int fill, int e_a, int e_b)
{
double x1,y1,x2,y2, tmp;
double psdash;
@ -562,7 +577,21 @@ static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,doub
if(dash) {
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
}
ps_xfillrectange(gc, x1,y1,x2,y2, fill);
if(e_a != -1) {
double rx = (x2 - x1) / 2.0;
double ry = (y2 - y1) / 2.0;
double cx = (x2 + x1) / 2.0;
double cy = (y2 + y1) / 2.0;
if(xctx->fill_pattern && xctx->fill_type[gc] && fill) {
fprintf(fd, "%g %g MT %g %g %g %g %d %d E %g %g LT C F S\n",
cx, cy, cx, cy, rx, ry, -e_a, -e_a-e_b, cx, cy);
} else {
fprintf(fd, "%g %g %g %g %d %d E S\n", cx, cy, rx, ry, -e_a, -e_a-e_b);
}
} else {
ps_xfillrectangle(gc, x1,y1,x2,y2, fill);
}
if(dash) {
fprintf(fd, "[] 0 setdash\n");
}
@ -937,7 +966,7 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho
#endif
else if((xctx->inst[n].x2 - xctx->inst[n].x1) * xctx->mooz < 3 &&
(xctx->inst[n].y2 - xctx->inst[n].y1) * xctx->mooz < 3) {
ps_filledrect(c, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0);
ps_filledrect(c, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0, -1, -1);
xctx->inst[n].flags|=1;
return;
}
@ -946,7 +975,7 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho
}
if(hide) {
int color = (disabled==1) ? GRIDLAYER : (disabled == 2) ? PINLAYER : SYMLAYER;
ps_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0);
ps_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0, -1, -1);
}
/* pdfmarks, only if doing hierarchy print and if symbol has a subcircuit */
if(what != 7) {
@ -1033,6 +1062,7 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho
if( (!hide && xctx->enable_layer[layer]) ||
(hide && layer == PINLAYER && xctx->enable_layer[layer]) ) {
if(symptr->rects[layer]) fprintf(fd, "NP\n"); /* newpath */
for(j=0;j< symptr->rects[layer]; ++j)
{
int dash;
@ -1044,9 +1074,27 @@ static void ps_draw_symbol(int c, int n,int layer, int what, short tmp_flip, sho
if (layer == GRIDLAYER && rect->flags & 1024) /* image */
{
ps_embedded_image(rect, x0 + x1, y0 + y1, x0 + x2, y0 + y2, rot, flip);
continue;
} else {
int ellipse_a = rect->ellipse_a;
int ellipse_b = rect->ellipse_b;
if(ellipse_a != -1 && ellipse_b != 360) {
if(flip) {
ellipse_a = 180 - ellipse_a - ellipse_b;
}
if(rot) {
if(rot == 3) {
ellipse_a += 90;
} else if(rot == 2) {
ellipse_a += 180;
} else if(rot == 1) {
ellipse_a += 270;
}
ellipse_a %= 360;
}
}
ps_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill, ellipse_a, ellipse_b);
}
ps_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill);
}
} /* if( (!hide && xctx->enable_layer[layer]) || ... */
@ -1192,83 +1240,78 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
old_grid=tclgetboolvar("draw_grid");
tclsetvar("draw_grid", "0");
/* xschem window aspect ratio decides if portrait or landscape */
boundbox.x1 = xctx->areax1;
boundbox.x2 = xctx->areax2;
boundbox.y1 = xctx->areay1;
boundbox.y2 = xctx->areay2;
dx=boundbox.x2-boundbox.x1;
dy=boundbox.y2-boundbox.y1;
/* xschem drawing bbox decides if portrait or landscape */
if(fullzoom == 1) {
calc_drawing_bbox(&boundbox, 0);
dx=boundbox.x2-boundbox.x1;
dy=boundbox.y2-boundbox.y1;
}
if(dx >= dy) {
landscape = 1;
} else {
landscape = 0;
}
dbg(1, "dx=%g, dy=%g\n", dx, dy);
if(!(what & 4)) {
/* xschem window aspect ratio decides if portrait or landscape */
if(fullzoom == 1) {
/* save size and zoom factor */
save_restore_zoom(1, &zi);
/* this zoom only done to reset lw */
zoom_full(0, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
/* adjust aspect ratio to paper size */
if(landscape)
xctx->xrect[0].height = (short unsigned int) (xctx->xrect[0].width * pagey / pagex);
else
xctx->xrect[0].width = (short unsigned int) (xctx->xrect[0].height * pagey / pagex);
dbg(1, "xrect.width=%d, xrect.height=%d\n", xctx->xrect[0].width, xctx->xrect[0].height);
xctx->areax1 = -2*INT_WIDTH(xctx->lw);
xctx->areay1 = -2*INT_WIDTH(xctx->lw);
xctx->areax2 = xctx->xrect[0].width+2*INT_WIDTH(xctx->lw);
xctx->areay2 = xctx->xrect[0].height+2*INT_WIDTH(xctx->lw);
xctx->areaw = xctx->areax2-xctx->areax1;
xctx->areah = xctx->areay2 - xctx->areay1;
dbg(1, "dx=%g, dy=%g\n", dx, dy);
/* fit schematic into adjusted size */
zoom_full(0, 0, 0 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
boundbox.x1 = xctx->areax1;
boundbox.x2 = xctx->areax2;
boundbox.y1 = xctx->areay1;
boundbox.y2 = xctx->areay2;
dx=boundbox.x2-boundbox.x1;
dy=boundbox.y2-boundbox.y1;
/* xschem drawing bbox decides if portrait or landscape */
if(fullzoom == 1) {
calc_drawing_bbox(&boundbox, 0);
dx=boundbox.x2-boundbox.x1;
dy=boundbox.y2-boundbox.y1;
}
if(dx >= dy) {
landscape = 1;
}
if(!landscape) { /* decide paper orientation for best schematic fit */
double tmp;
tmp = pagex;
pagex = pagey;
pagey = tmp;
}
if(fullzoom == 2) { /* set media size to bbox */
double sc;
my_strncpy(papername, "bbox", S(papername));
pagex = xctx->xrect[0].width;
pagey = xctx->xrect[0].height;
if(pagex > pagey) {
sc = 842. / pagex;
pagex = my_round(pagex * sc);
pagey = my_round(pagey * sc);
} else {
landscape = 0;
sc = 842. / pagey;
pagex = my_round(pagex * sc);
pagey = my_round(pagey * sc);
}
dbg(1, "dx=%g, dy=%g\n", dx, dy);
if(fullzoom == 1) {
/* save size and zoom factor */
dbg(1, "create_ps: saving zoom\n");
save_restore_zoom(1, &zi);
/* this zoom only done to reset lw */
zoom_full(0, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
/* adjust aspect ratio to paper size */
if(landscape)
xctx->xrect[0].height = (short unsigned int) (xctx->xrect[0].width * pagey / pagex);
else
xctx->xrect[0].width = (short unsigned int) (xctx->xrect[0].height * pagey / pagex);
dbg(1, "xrect.width=%d, xrect.height=%d\n", xctx->xrect[0].width, xctx->xrect[0].height);
xctx->areax1 = -2*INT_WIDTH(xctx->lw);
xctx->areay1 = -2*INT_WIDTH(xctx->lw);
xctx->areax2 = xctx->xrect[0].width+2*INT_WIDTH(xctx->lw);
xctx->areay2 = xctx->xrect[0].height+2*INT_WIDTH(xctx->lw);
xctx->areaw = xctx->areax2-xctx->areax1;
xctx->areah = xctx->areay2 - xctx->areay1;
dbg(1, "dx=%g, dy=%g\n", dx, dy);
/* fit schematic into adjusted size */
zoom_full(0, 0, 0 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
boundbox.x1 = xctx->areax1;
boundbox.x2 = xctx->areax2;
boundbox.y1 = xctx->areay1;
boundbox.y2 = xctx->areay2;
dx=boundbox.x2-boundbox.x1;
dy=boundbox.y2-boundbox.y1;
}
if(!landscape) { /* decide paper orientation for best schematic fit */
double tmp;
tmp = pagex;
pagex = pagey;
pagey = tmp;
}
if(fullzoom == 2) { /* set media size to bbox */
double sc;
my_strncpy(papername, "bbox", S(papername));
pagex = xctx->xrect[0].width;
pagey = xctx->xrect[0].height;
if(pagex > pagey) {
sc = 842. / pagex;
pagex = my_round(pagex * sc);
pagey = my_round(pagey * sc);
} else {
sc = 842. / pagey;
pagex = my_round(pagex * sc);
pagey = my_round(pagey * sc);
}
margin = 0.0;
}
} /* if(!(what & 4)) */
margin = 0.0;
}
if(what & 1) {/* prolog */
dbg(1, "ps_draw(): bbox: x1=%g y1=%g x2=%g y2=%g\n", boundbox.x1, boundbox.y1, boundbox.x2, boundbox.y2);
@ -1338,9 +1381,23 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
fprintf(fd,"/C {closepath} bind def\n");
fprintf(fd,"/F {fill} bind def\n");
fprintf(fd,"/RF {rectfill} bind def\n");
fprintf(fd,"/E {\n"); /* function for drawing ellipses */
fprintf(fd,"/endangle exch def\n");
fprintf(fd,"/startangle exch def\n");
fprintf(fd,"/yrad exch def\n");
fprintf(fd,"/xrad exch def\n");
fprintf(fd,"/y exch def\n");
fprintf(fd,"/x exch def\n");
fprintf(fd,"/savematrix matrix currentmatrix def\n");
fprintf(fd,"x y translate\n");
fprintf(fd,"xrad yrad scale\n");
fprintf(fd,"0 0 1 startangle endangle arcn\n");
fprintf(fd,"savematrix setmatrix\n");
fprintf(fd,"} def %% ellipse\n");
fprintf(fd, "%%%%EndProlog\n");
}
if(what & 2) { /* page */
++numpages;
@ -1381,6 +1438,7 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
for(i=0;i<xctx->lines[c]; ++i)
ps_drawline(c, xctx->line[c][i].x1, xctx->line[c][i].y1,
xctx->line[c][i].x2, xctx->line[c][i].y2, xctx->line[c][i].dash);
if(xctx->rects[c]) fprintf(fd, "NP\n"); /* newpath */
for(i=0;i<xctx->rects[c]; ++i)
{
@ -1396,7 +1454,9 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
}
if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
ps_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,
xctx->rect[c][i].x2, xctx->rect[c][i].y2, xctx->rect[c][i].dash, xctx->rect[c][i].fill);
xctx->rect[c][i].x2, xctx->rect[c][i].y2,
xctx->rect[c][i].dash, xctx->rect[c][i].fill,
xctx->rect[c][i].ellipse_a, xctx->rect[c][i].ellipse_b);
}
}
if(xctx->arcs[c]) fprintf(fd, "NP\n"); /* newpath */
@ -1497,7 +1557,7 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
dbg(1, "ps_draw(): INT_WIDTH(lw)=%d plotfile=%s\n",INT_WIDTH(xctx->lw), xctx->plotfile);
fprintf(fd, "showpage\n\n");
} /* if(what & 2) */
}
if(what & 4) { /* trailer */
fprintf(fd, "%%%%trailer\n");
fprintf(fd, "%%%%Pages: %d\n", numpages);
@ -1515,10 +1575,10 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
/* restore original size and zoom factor */
if(!(what & 4) && fullzoom == 1) {
dbg(1, "create_ps: restoring zoom\n");
if(fullzoom == 1) {
save_restore_zoom(0, &zi);
}
}
int ps_draw(int what, int fullzoom, int eps)

View File

@ -909,7 +909,7 @@ char *base64_from_file(const char *f, size_t *length)
stat_res = stat(f, &st);
if (stat_res == 0 && ( (st.st_mode & S_IFMT) == S_IFREG) ) {
len = st.st_size;
fd = fopen(f, fopen_read_mode);
fd = my_fopen(f, fopen_read_mode);
if(fd) {
size_t bytes_read;
s = my_malloc(_ALLOC_ID_, len);
@ -1023,7 +1023,7 @@ int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, doub
raw->annot_sweep_idx = -1;
int_hash_init(&raw->table, HASHSIZE);
fd = fopen(f, fopen_read_mode);
fd = my_fopen(f, fopen_read_mode);
if(fd) {
if((res = read_dataset(fd, rawptr, type, no_warning)) == 1) {
int i;
@ -1038,6 +1038,18 @@ int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, doub
dbg(0, "Raw file data read: %s\n", f);
dbg(0, "points=%d, vars=%d, datasets=%d sim_type=%s\n",
raw->allpoints, raw->nvars, raw->datasets, raw->sim_type ? raw->sim_type : "<NULL>");
if(xctx->graph_flags & 4) { /* if cursor2 is enabled in first graph setup schematic annotation */
if(xctx->rects[GRIDLAYER] > 0) {
xRect *r;
r = &xctx->rect[GRIDLAYER][0];
if(r->flags & 1) {
setup_graph_data(0, 0, &xctx->graph_struct);
backannotate_at_cursor_b_pos(r, &xctx->graph_struct);
}
}
}
} else {
/* free_rawfile(rawptr, 0, 0); */ /* do not free: already done in read_dataset()->extra_rawfile() */
if(!no_warning) {
@ -1455,7 +1467,7 @@ int table_read(const char *f)
close(ufd);
int_hash_init(&raw->table, HASHSIZE);
fd = fopen(f, fopen_read_mode);
fd = my_fopen(f, fopen_read_mode);
if(fd) {
int nline = 0;
int field;
@ -2840,11 +2852,11 @@ static void load_polygon(FILE *fd)
load_ascii_string( &ptr[i].prop_ptr, fd);
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3; /* bit 1: solid fill (not stippled) */
ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr, "true") )
ptr[i].fill =1;
ptr[i].fill = 1;
else
ptr[i].fill =0;
ptr[i].fill = 0;
dash = get_tok_value(ptr[i].prop_ptr,"dash",0);
if(strcmp(dash, "")) {
int d = atoi(dash);
@ -2883,11 +2895,11 @@ static void load_arc(FILE *fd)
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3; /* bit 1: solid fill (not stippled) */
ptr[i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr, "true") )
ptr[i].fill =1;
ptr[i].fill = 1;
else
ptr[i].fill =0;
ptr[i].fill = 0;
dash = get_tok_value(ptr[i].prop_ptr,"dash",0);
if(strcmp(dash, "")) {
int d = atoi(dash);
@ -2927,11 +2939,11 @@ static void load_box(FILE *fd)
load_ascii_string( &ptr[i].prop_ptr, fd);
fill_ptr = get_tok_value(ptr[i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
ptr[i].fill =3;
ptr[i].fill = 2;
else if( !strboolcmp(fill_ptr, "false") )
ptr[i].fill =0;
ptr[i].fill = 0;
else
ptr[i].fill =1;
ptr[i].fill = 1;
attr = get_tok_value(ptr[i].prop_ptr,"dash",0);
if(strcmp(attr, "")) {
int d = atoi(attr);
@ -3532,7 +3544,7 @@ int load_schematic(int load_symbols, const char *fname, int reset_undo, int aler
my_free(_ALLOC_ID_, &cmd);
} else fd = NULL;
}
else fd=fopen(name,fopen_read_mode);
else fd=my_fopen(name,fopen_read_mode);
if( fd == NULL) {
size_t len;
ret = 0;
@ -3545,7 +3557,7 @@ int load_schematic(int load_symbols, const char *fname, int reset_undo, int aler
}
len = strlen(name);
if(!strcmp(name + len - 4, ".sym")) {
xctx->save_netlist_type = xctx->netlist_type;
if(xctx->netlist_type != CAD_SYMBOL_ATTRS) xctx->save_netlist_type = xctx->netlist_type;
xctx->netlist_type = CAD_SYMBOL_ATTRS;
set_tcl_netlist_type();
xctx->loaded_symbol = 1;
@ -3564,7 +3576,7 @@ int load_schematic(int load_symbols, const char *fname, int reset_undo, int aler
if(reset_undo) {
tclvareval("is_xschem_file {", xctx->sch[xctx->currsch], "}", NULL);
if(!strcmp(tclresult(), "SYMBOL") || xctx->instances == 0) {
xctx->save_netlist_type = xctx->netlist_type;
if(xctx->netlist_type != CAD_SYMBOL_ATTRS) xctx->save_netlist_type = xctx->netlist_type;
xctx->netlist_type = CAD_SYMBOL_ATTRS;
set_tcl_netlist_type();
xctx->loaded_symbol = 1;
@ -3811,7 +3823,7 @@ void pop_undo(int redo, int set_modify_status)
fd=fdopen(pd[0],"r");
#else /* uncompressed undo */
my_snprintf(diff_name, S(diff_name), "%s/undo%d", xctx->undo_dirname, xctx->cur_undo_ptr%MAX_UNDO);
fd=fopen(diff_name, "r");
fd=my_fopen(diff_name, fopen_read_mode);
if(!fd) {
fprintf(errfp, "pop_undo(): failed to open read pipe %s\n", diff_name);
xctx->no_undo=1;
@ -3882,9 +3894,9 @@ static void get_sym_type(const char *symname, char **type,
if( !found ) {
dbg(1, "get_sym_type(): open file %s, pintable %s\n",name, pintable ? "set" : "<NULL>");
/* ... if not found open file and look for 'type' into the global attributes. */
if(embed_fd) fd = embed_fd;
else fd=fopen(name,fopen_read_mode);
else fd=my_fopen(name,fopen_read_mode);
if(fd==NULL) {
dbg(1, "get_sym_type(): Symbol not found: %s\n",name);
@ -4226,15 +4238,15 @@ int load_sym_def(const char *name, FILE *embed_fd)
} else {
my_strncpy(sympath, abs_sym_path(transl_name, ""), S(sympath));
}
if((lcc[level].fd=fopen(sympath,fopen_read_mode))==NULL) {
if((lcc[level].fd=my_fopen(sympath,fopen_read_mode))==NULL) {
/* not found: try web URL */
if(is_from_web(xctx->current_dirname)) {
my_snprintf(sympath, S(sympath), "%s/%s", xschem_web_dirname, get_cell_w_ext(transl_name, 0));
if((lcc[level].fd=fopen(sympath,fopen_read_mode))==NULL) {
if((lcc[level].fd=my_fopen(sympath,fopen_read_mode))==NULL) {
/* not already cached in .../xschem_web_xxxxx/ so download */
tclvareval("try_download_url {", xctx->current_dirname, "} {", transl_name, "}", NULL);
}
lcc[level].fd=fopen(sympath,fopen_read_mode);
lcc[level].fd=my_fopen(sympath,fopen_read_mode);
}
}
dbg(1, "l_s_d(): fopen1(%s), level=%d, fd=%p\n",sympath, level, lcc[level].fd);
@ -4246,7 +4258,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
/* issue warning only on top level symbol loading */
if(recursion_counter == 1) dbg(0, "l_s_d(): Symbol not found: %s\n", transl_name);
my_snprintf(sympath, S(sympath), "%s/%s", tclgetvar("XSCHEM_SHAREDIR"), "systemlib/missing.sym");
if((lcc[level].fd=fopen(sympath, fopen_read_mode))==NULL)
if((lcc[level].fd=my_fopen(sympath, fopen_read_mode))==NULL)
{
fprintf(errfp, "l_s_d(): systemlib/missing.sym missing, I give up\n");
tcleval("exit");
@ -4441,11 +4453,11 @@ int load_sym_def(const char *name, FILE *embed_fd)
fill_ptr = get_tok_value(pp[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
pp[c][i].fill =3; /* bit 1: solid fill (not stippled) */
pp[c][i].fill = 2; /* bit 1: solid fill (not stippled) */
else if( !strboolcmp(fill_ptr, "true") )
pp[c][i].fill =1;
pp[c][i].fill = 1;
else
pp[c][i].fill =0;
pp[c][i].fill = 0;
attr = get_tok_value(pp[c][i].prop_ptr,"dash", 0);
if( strcmp(attr, "") ) {
@ -4507,11 +4519,11 @@ int load_sym_def(const char *name, FILE *embed_fd)
}
fill_ptr = get_tok_value(aa[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
aa[c][i].fill =3; /* bit 1: solid fill (not stiaaled) */
aa[c][i].fill = 2; /* bit 1: solid fill (not stiaaled) */
else if( !strboolcmp(fill_ptr, "true") )
aa[c][i].fill =1;
aa[c][i].fill = 1;
else
aa[c][i].fill =0;
aa[c][i].fill = 0;
attr = get_tok_value(aa[c][i].prop_ptr,"dash", 0);
if( strcmp(attr, "") ) {
int d = atoi(attr);
@ -4570,11 +4582,11 @@ int load_sym_def(const char *name, FILE *embed_fd)
dbg(2, "l_s_d(): loaded rect: ptr=%lx\n", (unsigned long)bb[c]);
fill_ptr = get_tok_value(bb[c][i].prop_ptr,"fill",0);
if( !strcmp(fill_ptr, "full") )
bb[c][i].fill =3;
bb[c][i].fill = 2;
else if( !strboolcmp(fill_ptr, "false") )
bb[c][i].fill =0;
bb[c][i].fill = 0;
else
bb[c][i].fill =1;
bb[c][i].fill = 1;
attr = get_tok_value(bb[c][i].prop_ptr,"dash", 0);
if( strcmp(attr, "") ) {
int d = atoi(attr);
@ -4787,6 +4799,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
dbg(1, "l_s_d(): level=%d, symname=%s symtype=%s\n", level, symname, symtype);
if( /* add here symbol types not to consider when loading schematic-as-symbol instances */
!symtype ||
!strcmp(symtype, "logo") ||
!strcmp(symtype, "netlist_commands") ||
!strcmp(symtype, "netlist_options") ||
@ -4817,7 +4830,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
dbg(1, "l_s_d(): fopen2(%s), level=%d\n",sympath, level);
/* find out if symbol is in an external file or embedded, set fd_tmp accordingly */
if ((fd_tmp = fopen(sympath, fopen_read_mode)) == NULL) {
if ((fd_tmp = my_fopen(sympath, fopen_read_mode)) == NULL) {
char c;
fprintf(errfp, "l_s_d(): unable to open file to read schematic: %s\n", sympath);
if(!generator) {
@ -5107,6 +5120,7 @@ int descend_symbol(void)
char name_embedded[PATH_MAX];
int n = 0;
struct stat buf;
int save_netlist_type = xctx->netlist_type;
if(xctx->currsch + 1 >= CADMAXHIER) {
dbg(0, "descend_symbol(): max hierarchy depth reached: %d", CADMAXHIER);
return 0;
@ -5216,6 +5230,10 @@ int descend_symbol(void)
}
my_free(_ALLOC_ID_, &sympath);
}
if(save_netlist_type != CAD_SYMBOL_ATTRS) xctx->save_netlist_type = save_netlist_type;
xctx->loaded_symbol = 1;
xctx->netlist_type = CAD_SYMBOL_ATTRS;
set_tcl_netlist_type();
zoom_full(1, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
return 1;
}

View File

@ -1344,6 +1344,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
my_snprintf(res, S(res), "%g %g %g %g", boundbox.x1, boundbox.y1, boundbox.x2, boundbox.y2);
Tcl_SetResult(interp, res, TCL_VOLATILE);
}
else if(!strcmp(argv[2], "build_date")) { /* time and date this file was built. */
char date[] = __DATE__ " : " __TIME__;
Tcl_SetResult(interp, date, TCL_STATIC);
}
break;
case 'c':
if(!strcmp(argv[2], "cadlayers")) { /* number of layers */
@ -2158,7 +2162,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(argc > 2 ) {
what = atoi(argv[2]);
}
if((xctx->semaphore == 0)) go_back(what);
if(xctx->semaphore == 0) go_back(what);
Tcl_ResetResult(interp);
}
@ -3024,6 +3028,33 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(argc==2 && errfp != stderr) { fclose(errfp); errfp=stderr; }
}
/* load_symbol [symbol_file]
* Load specified symbol_file
* Returns:
* >= 0: symbol is already loaded or has been loaded
* < 0: symbol was not loaded
*/
else if(!strcmp(argv[1], "load_symbol") )
{
int res = -2;
struct stat buf;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
int i = get_symbol(rel_sym_path(argv[2]));
if(i < 0 ) {
if(!stat(argv[2], &buf)) { /* file exists */
res = load_sym_def(rel_sym_path(argv[2]), NULL);
if(res == 0) res = -1;
} else {
res = -3;
}
} else {
res = 1;
}
}
Tcl_SetResult(interp, my_itoa(res), TCL_VOLATILE);
}
/* log_write text
* write given string to log file, so tcl can write messages on the log file
*/
@ -3356,7 +3387,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
"-message {Please Set netlisting mode (Options menu)}");
tclsetboolvar("keep_symbols", save_keep);
if( (erc == 0) ) {
if(erc == 0) {
my_strncpy(xctx->netlist_name, "", S(xctx->netlist_name));
}
}
@ -5547,7 +5578,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
set_rect_flags(r); /* set cached .flags bitmask from attributes */
if(argc > 5 && !strcmp(argv[5], "fill")) {
const char *attr = get_tok_value(r->prop_ptr,"fill", 0);
if(!strcmp(attr, "full")) xctx->rect[c][n].fill = 3;
if(!strcmp(attr, "full")) xctx->rect[c][n].fill = 2;
else if(!strboolcmp(attr, "false")) xctx->rect[c][n].fill = 0;
else xctx->rect[c][n].fill = 1;
}

View File

@ -439,7 +439,7 @@ static void del_rect_line_arc_poly()
{
++j;
if(xctx->arc[c][i].fill & 1) /* .fill: 1: stippled fill, 3: solid fill */
if(xctx->arc[c][i].fill) /* .fill: 1: stippled fill, 2: solid fill */
arc_bbox(xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, 0, 360,
&tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2);
else

View File

@ -635,6 +635,11 @@ int spice_block_netlist(FILE *fd, int i, int alert)
tclgetvar("netlist_dir"), get_cell(name, 0), getpid());
dbg(1, "spice_block_netlist(): split_files: netl_filename=%s\n", netl_filename);
fd=fopen(netl_filename, "w");
if(!fd) {
dbg(0, "spice_block_netlist(): unable to write file %s\n", netl_filename);
err = 1;
goto err;
}
my_snprintf(cellname, S(cellname), "%s.spice", get_cell(name, 0));
}
fprintf(fd, "\n* expanding symbol: %s # of pins=%d\n", name,xctx->sym[i].rects[PINLAYER] );
@ -689,6 +694,7 @@ int spice_block_netlist(FILE *fd, int i, int alert)
set_tcl_netlist_type();
if(debug_var==0) xunlink(netl_filename);
}
err:
xctx->netlist_count++;
my_free(_ALLOC_ID_, &name);
return err;

View File

@ -156,11 +156,11 @@ void store_arc(int pos, double x, double y, double r, double a, double b,
fill_ptr = get_tok_value(xctx->arc[rectc][n].prop_ptr,"fill",0);
if(!strcmp(fill_ptr, "full") )
xctx->arc[rectc][n].fill =3; /* bit 1: solid fill (not stippled) */
xctx->arc[rectc][n].fill = 2; /* bit 1: solid fill (not stippled) */
else if(!strboolcmp(fill_ptr, "true") )
xctx->arc[rectc][n].fill =1;
xctx->arc[rectc][n].fill = 1;
else
xctx->arc[rectc][n].fill =0;
xctx->arc[rectc][n].fill = 0;
dash = get_tok_value(xctx->arc[rectc][n].prop_ptr,"dash",0);
if( strcmp(dash, "") ) {
int d = atoi(dash);
@ -206,11 +206,11 @@ void store_poly(int pos, double *x, double *y, int points, unsigned int rectc,
fill_ptr = get_tok_value(xctx->poly[rectc][n].prop_ptr,"fill",0);
if(!strcmp(fill_ptr, "full") )
xctx->poly[rectc][n].fill =3; /* bit 1: solid fill (not stippled) */
xctx->poly[rectc][n].fill = 2; /* bit 1: solid fill (not stippled) */
else if(!strboolcmp(fill_ptr, "true") )
xctx->poly[rectc][n].fill =1;
xctx->poly[rectc][n].fill = 1;
else
xctx->poly[rectc][n].fill =0;
xctx->poly[rectc][n].fill = 0;
dash = get_tok_value(xctx->poly[rectc][n].prop_ptr,"dash",0);
if( strcmp(dash, "") ) {
int d = atoi(dash);
@ -307,11 +307,11 @@ int storeobject(int pos, double x1,double y1,double x2,double y2,
fill_ptr = get_tok_value(xctx->rect[rectc][n].prop_ptr, "fill", 0);
if(!strcmp(fill_ptr, "full") )
xctx->rect[rectc][n].fill =3;
xctx->rect[rectc][n].fill = 2;
else if(!strboolcmp(fill_ptr,"false") )
xctx->rect[rectc][n].fill =0;
xctx->rect[rectc][n].fill = 0;
else
xctx->rect[rectc][n].fill =1;
xctx->rect[rectc][n].fill = 1;
set_rect_flags(&xctx->rect[rectc][n]); /* set cached .flags bitmask from on attributes */
if(rectc == GRIDLAYER && (xctx->rect[rectc][n].flags & 1024)) {
xRect *r = &xctx->rect[GRIDLAYER][n];

View File

@ -62,7 +62,7 @@ static void svg_xfillrectangle(int layer, double x1, double y1, double x2, doubl
if(dash) fprintf(fd, "stroke-dasharray=\"%g,%g\" ", 1.4*dash/xctx->zoom, 1.4*dash/xctx->zoom);
if(fill == 0) {
fprintf(fd,"style=\"fill:none;\" ");
} else if(fill == 3) {
} else if(fill == 2) {
fprintf(fd, "style=\"fill-opacity:1.0;\" ");
}
fprintf(fd,"d=\"M%g %gL%g %gL%g %gL%g %gL%g %gz\"/>\n", x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
@ -135,7 +135,7 @@ static void svg_drawpolygon(int c, int what, double *x, double *y, int points, i
if(dash) fprintf(fd, "stroke-dasharray=\"%g,%g\" ", 1.4*dash/xctx->zoom, 1.4*dash/xctx->zoom);
if(fill == 0) {
fprintf(fd,"style=\"fill:none;\" ");
} else if(fill == 3) {
} else if(fill == 2) {
fprintf(fd, "style=\"fill-opacity:1.0;\" ");
}
bezier = flags && (points > 2);
@ -154,7 +154,8 @@ static void svg_drawpolygon(int c, int what, double *x, double *y, int points, i
fprintf(fd, "\"/>\n");
}
static void svg_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2, int dash, int fill)
static void svg_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2,
int dash, int fill, int e_a, int e_b)
{
double x1,y1,x2,y2;
@ -164,7 +165,41 @@ static void svg_filledrect(int gc, double rectx1,double recty1,double rectx2,dou
y2=Y_TO_SCREEN(recty2);
if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) )
{
svg_xfillrectangle(gc, x1,y1,x2,y2, dash, fill);
if(e_a != -1) {
double rx = (x2 - x1) / 2.0;
double ry = (y2 - y1) / 2.0;
double cx = (x2 + x1) / 2.0;
double cy = (y2 + y1) / 2.0;
if(e_b == 360.) {
fprintf(fd, "<ellipse class=\"l%d\" cx=\"%g\" cy=\"%g\" rx=\"%g\" ry=\"%g\" ", gc, cx, cy, rx, ry);
if(dash) fprintf(fd, "stroke-dasharray=\"%g,%g\" ", 1.4*dash/xctx->zoom, 1.4*dash/xctx->zoom);
if(fill == 0) fprintf(fd, "style=\"fill:none;\" ");
else if(fill == 2) fprintf(fd, "style=\"fill-opacity:1.0;\" ");
fprintf(fd, "/>\n");
} else {
double xx1 = rx * cos(e_a * XSCH_PI / 180.) + cx;
double yy1 = -ry * sin(e_a * XSCH_PI / 180.) + cy;
double xx2 = rx * cos((e_a + e_b) * XSCH_PI / 180.) + cx;
double yy2 = -ry * sin((e_a + e_b) * XSCH_PI / 180.) + cy;
int fa = e_b > 180 ? 1 : 0;
int fs = e_b > 0 ? 0 : 1;
fprintf(fd,"<path class=\"l%d\" ", gc);
if(dash) fprintf(fd, "stroke-dasharray=\"%g,%g\" ", 1.4*dash/xctx->zoom, 1.4*dash/xctx->zoom);
if(fill == 0) {
fprintf(fd,"style=\"fill:none;\" ");
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2);
} else if(fill == 2) {
fprintf(fd, "style=\"fill-opacity:1.0;\" ");
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2, cx, cy);
} else {
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rx, ry, fa, fs, xx2, yy2, cx, cy);
}
}
} else {
svg_xfillrectangle(gc, x1,y1,x2,y2, dash, fill);
}
}
}
@ -210,7 +245,7 @@ static void svg_drawarc(int gc, int fillarc, double x,double y,double r,double a
fprintf(fd, "<circle class=\"l%d\" cx=\"%g\" cy=\"%g\" r=\"%g\" ", gc, xx, yy, rr);
if(dash) fprintf(fd, "stroke-dasharray=\"%g,%g\" ", 1.4*dash/xctx->zoom, 1.4*dash/xctx->zoom);
if(fillarc == 0) fprintf(fd, "style=\"fill:none;\" ");
else if(fillarc == 3) fprintf(fd, "style=\"fill-opacity:1.0;\" ");
else if(fillarc == 2) fprintf(fd, "style=\"fill-opacity:1.0;\" ");
fprintf(fd, "/>\n");
} else {
@ -226,12 +261,12 @@ static void svg_drawarc(int gc, int fillarc, double x,double y,double r,double a
if(fillarc == 0) {
fprintf(fd,"style=\"fill:none;\" ");
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %g\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2);
} else if(fillarc == 3) {
} else if(fillarc == 2) {
fprintf(fd, "style=\"fill-opacity:1.0;\" ");
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy);
} else {
fprintf(fd, "d=\"M%g %g A%g %g 0 %d %d %g %gL%g %gz\"/>\n", xx1, yy1, rr, rr, fa, fs, xx2, yy2, xx, yy);
}
}
}
}
}
@ -478,6 +513,7 @@ static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, doub
double alpha = 1.0;
unsigned char *buffer = NULL;
size_t buffer_size;
double xorig, yorig; /* image anchor point, upper left corner in SVG */
x1=X_TO_SCREEN(rx1);
y1=Y_TO_SCREEN(ry1);
@ -488,7 +524,6 @@ static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, doub
if(RECT_OUTSIDE(x1, y1, x2, y2,
xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) return 0;
if(rot == 1 || rot == 3) {
w = fabs(y2 - y1);
h = fabs(x2 - x1);
@ -498,7 +533,8 @@ static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, doub
}
if(flip && (rot == 0 || rot == 2)) scalex = -1.0;
else if(flip && (rot == 1 || rot == 3)) scaley = -1.0;
else if(flip && (rot == 1 || rot == 3)) scalex = -1.0;
alpha_str = get_tok_value(r->prop_ptr, "alpha", 0);
if(alpha_str[0]) alpha = atof(alpha_str);
attr_len = my_strdup2(_ALLOC_ID_, &attr, get_tok_value(r->prop_ptr, "image_data", 0));
@ -523,8 +559,32 @@ static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, doub
my_free(_ALLOC_ID_, &attr);
return 0;
}
xorig = x1;
yorig = y1;
if(rot == 0) {
if(flip) xorig += w;
} else if(rot == 1) {
if(flip) {
xorig += h;
yorig += w;
} else xorig += h;
} else if(rot == 2) {
if(flip) {
yorig += h;
} else {
xorig += w;
yorig += h;
}
} else if(rot == 3) {
if(flip) {
} else {
yorig += w;
}
}
my_snprintf(transform, S(transform),
"transform=\"translate(%g,%g) scale(%g,%g) rotate(%d)\"", x1, y1, scalex, scaley, rot * 90);
"transform=\"translate(%g,%g) rotate(%d) scale(%g,%g)\"", xorig, yorig, rot * 90, scalex, scaley);
if(alpha == 1.0) strcpy(opacity, "");
else my_snprintf(opacity, S(opacity), "style=\"opacity:%g;\"", alpha);
/* png jpg */
@ -603,7 +663,7 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
}
else if((xctx->inst[n].x2 - xctx->inst[n].x1) * xctx->mooz < 3 &&
(xctx->inst[n].y2 - xctx->inst[n].y1) * xctx->mooz < 3) {
svg_filledrect(c, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0);
svg_filledrect(c, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 0, 0, -1, -1);
xctx->inst[n].flags|=1;
return;
}
@ -612,7 +672,7 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
}
if(hide) {
int color = (disabled==1) ? GRIDLAYER : (disabled == 2) ? PINLAYER : SYMLAYER;
svg_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0);
svg_filledrect(color, xctx->inst[n].xx1, xctx->inst[n].yy1, xctx->inst[n].xx2, xctx->inst[n].yy2, 2, 0, -1, -1);
}
}
else if(xctx->inst[n].flags&1) {
@ -692,9 +752,27 @@ static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,
double xx2 = x0 + x2;
double yy2 = y0 + y2;
svg_embedded_image(rect, xx1, yy1, xx2, yy2, rot, flip);
continue;
} else {
int ellipse_a = rect->ellipse_a;
int ellipse_b = rect->ellipse_b;
if(ellipse_a != -1 && ellipse_b != 360) {
if(flip) {
ellipse_a = 180 - ellipse_a - ellipse_b;
}
if(rot) {
if(rot == 3) {
ellipse_a += 90;
} else if(rot == 2) {
ellipse_a += 180;
} else if(rot == 1) {
ellipse_a += 270;
}
ellipse_a %= 360;
}
}
svg_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill, ellipse_a, ellipse_b);
}
svg_filledrect(c, x0+x1, y0+y1, x0+x2, y0+y2, dash, rect->fill);
}
}
@ -916,8 +994,8 @@ void svg_draw(void)
* 2 : solid fill
* fill_type[i]:
* 0 : no fill
* 1 : solid fill
* 2 : patterned (stippled) fill
* 1 : patterned (stippled) fill
* 2 : solid fill
*/
for(i=0;i<cadlayers; ++i){
if(unused_layer[i]) continue;
@ -927,7 +1005,7 @@ void svg_draw(void)
svg_colors[i].red, svg_colors[i].green, svg_colors[i].blue);
else if( xctx->fill_pattern == 2 && xctx->fill_type[i])
fprintf(fd, " fill: #%02x%02x%02x;\n", svg_colors[i].red, svg_colors[i].green, svg_colors[i].blue);
else if( xctx->fill_pattern && xctx->fill_type[i] == 1)
else if( xctx->fill_pattern && xctx->fill_type[i] == 2)
fprintf(fd, " fill: #%02x%02x%02x;\n", svg_colors[i].red, svg_colors[i].green, svg_colors[i].blue);
else
fprintf(fd, " fill: #%02x%02x%02x; fill-opacity: 0.5;\n",
@ -976,7 +1054,8 @@ void svg_draw(void)
} else {
svg_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,
xctx->rect[c][i].x2, xctx->rect[c][i].y2,
xctx->rect[c][i].dash, xctx->rect[c][i].fill);
xctx->rect[c][i].dash, xctx->rect[c][i].fill,
xctx->rect[c][i].ellipse_a, xctx->rect[c][i].ellipse_b);
}
}
for(i=0;i<xctx->arcs[c]; ++i)

View File

@ -1174,26 +1174,41 @@ static void print_vhdl_primitive(FILE *fd, int inst) /* netlist primitives, 200
if(c=='\0')
{
/* do one level of substitutions to resolve remaining @params and/or tcl expr/code */
if(result) {
dbg(1, "print_vhdl_primitive(): before translate() result=%s\n", result);
if(!strcmp(xctx->sym[xctx->inst[inst].ptr].type, "netlist_commands")) {
/* since netlist_commands often have @ characters in spice node save / plot commands, do
* not pass through translate, unless a tcleval(...) is present */
if(strstr(result, "tcleval(")== result) {
my_strdup(_ALLOC_ID_, &result, translate(inst, result));
}
} else {
my_strdup(_ALLOC_ID_, &result, translate(inst, result));
}
dbg(1, "print_vhdl_primitive(): after translate() result=%s\n", result);
}
if(result) fprintf(fd, "%s", result);
fputc('\n',fd);
fprintf(fd, "---- end primitive\n");
break ;
char *parent_prop_ptr = NULL;
if(xctx->currsch > 0) {
parent_prop_ptr = xctx->hier_attr[xctx->currsch - 1].prop_ptr;
}
/* if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions
* can be calculated. Before that do also a round of translation to remove remaining @params */
if(result) {
dbg(1, "print_vhdl_primitive(): before translate3() result=%s\n", result);
if(strchr(result, '@')) {
/* netlist_commands often have @ characters due to ngspice syntax. Do not translate */
if(strcmp(xctx->sym[xctx->inst[inst].ptr].type, "netlist_commands")) {
my_strdup2(_ALLOC_ID_, &result,
translate3(result, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, NULL, NULL));
/* can not put template in above translate3: -----------------------^^^^
* if instance has VHI=VHI, format string has VHI=@VHI, and symbol template has VHI=3
* we do not want token @VHI to resolve to 3, but stop at VHI as specified in instance */
if(strchr(result, '@')) {
my_strdup2(_ALLOC_ID_, &result,
translate3(result, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, template, NULL));
}
}
}
my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result)); /* tcl evaluation if tcleval(....) */
if(strstr(result, "expr(") ) {
result = eval_expr(result);
}
dbg(1, "print_vhdl_primitive(): after translate3() result=%s\n", result);
}
if(result) fprintf(fd, "%s", result);
fputc('\n',fd);
fprintf(fd, "---- end primitive\n");
break ;
}
}
} /* while(1) */
my_free(_ALLOC_ID_, &result);
my_free(_ALLOC_ID_, &template);
my_free(_ALLOC_ID_, &format);
@ -2398,7 +2413,14 @@ int print_spice_element(FILE *fd, int inst)
* model=nfet_01v8
*/
my_strdup2(_ALLOC_ID_, &val,
translate3(token, 2, xctx->inst[inst].prop_ptr, parent_prop_ptr, template, NULL));
translate3(token, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, NULL, NULL));
/* can not put template in above translate3: ---------------------------^^^^
* if instance has VHI=VHI, format string has VHI=@VHI, and symbol template has VHI=3
* we do not want token @VHI to resolve to 3, but stop at VHI as specified in instance */
if(strchr(val, '@')) {
my_strdup2(_ALLOC_ID_, &val,
translate3(val, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, template, NULL));
}
/* nmos instance format string: @model --> @modeln */
dbg(1, "print_spice_element(): 1st round: val: |%s|\n", val);
if(strchr(val, '@')) {
@ -2428,12 +2450,10 @@ int print_spice_element(FILE *fd, int inst)
}
dbg(1, "print_spice_element(): final: val: |%s|\n", val);
}
value = val;
/* xctx->tok_size==0 (set in translate3()) indicates that token(+1) does not exist
* in instance attributes so try to get from symbol template */
dbg(1, "print_spice_element(): val: %s\n", val);
/* still unresolved: set to empty */
if(val[0] == '@') value = "";
else value = val;
token_exists = xctx->tok_size;
value = val;
tok_val_len = strlen(value);
/* @spiceprefix needs a special tag for postprocessing */
if(!strcmp(token, "@spiceprefix") && value[0]) {
@ -3109,26 +3129,42 @@ static void print_verilog_primitive(FILE *fd, int inst) /* netlist switch level
}
if(c=='\0')
{
/* do one level of substitutions to resolve remaining @params and/or tcl expr/code */
char *parent_prop_ptr = NULL;
if(xctx->currsch > 0) {
parent_prop_ptr = xctx->hier_attr[xctx->currsch - 1].prop_ptr;
}
/* if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions
* can be calculated. Before that do also a round of translation to remove remaining @params */
if(result) {
dbg(1, "print_verilog_primitive(): before translate() result=%s\n", result);
if(!strcmp(xctx->sym[xctx->inst[inst].ptr].type, "netlist_commands")) {
/* since netlist_commands often have @ characters in spice node save / plot commands, do
* not pass through translate, unless a tcleval(...) is present */
if(strstr(result, "tcleval(")== result) {
my_strdup(_ALLOC_ID_, &result, translate(inst, result));
dbg(1, "print_verilog_primitive(): before translate3() result=%s\n", result);
if(strchr(result, '@')) {
/* netlist_commands often have @ characters due to ngspice syntax. Do not translate */
if(strcmp(xctx->sym[xctx->inst[inst].ptr].type, "netlist_commands")) {
my_strdup2(_ALLOC_ID_, &result,
translate3(result, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, NULL, NULL));
/* can not put template in above translate3: -----------------------^^^^
* if instance has VHI=VHI, format string has VHI=@VHI, and symbol template has VHI=3
* we do not want token @VHI to resolve to 3, but stop at VHI as specified in instance */
if(strchr(result, '@')) {
my_strdup2(_ALLOC_ID_, &result,
translate3(result, 0, xctx->inst[inst].prop_ptr, parent_prop_ptr, template, NULL));
}
}
} else {
my_strdup(_ALLOC_ID_, &result, translate(inst, result));
}
dbg(1, "print_verilog_primitive(): after translate() result=%s\n", result);
my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result)); /* tcl evaluation if tcleval(....) */
if(strstr(result, "expr(") ) {
result = eval_expr(result);
}
dbg(1, "print_verilog_primitive(): after translate3() result=%s\n", result);
}
if(result) fprintf(fd, "%s", result);
fputc('\n',fd);
fprintf(fd, "---- end primitive\n");
break ;
}
}
} /* while(1) */
my_free(_ALLOC_ID_, &result);
my_free(_ALLOC_ID_, &template);
my_free(_ALLOC_ID_, &format);
@ -3748,7 +3784,9 @@ const char *spice_get_node(const char *token)
/* if s==NULL return emty string */
const char *translate(int inst, const char* s)
{
#ifdef __unix__
static regex_t *get_sp_cur = NULL;
#endif
static const char *empty="";
static char *result=NULL; /* safe to keep even with multiple schematics */
size_t size=0;
@ -3773,24 +3811,28 @@ const char *translate(int inst, const char* s)
if(!s && inst == -1) {
if(result) my_free(_ALLOC_ID_, &result);
#ifdef __unix__
if(get_sp_cur) {
regfree(get_sp_cur);
get_sp_cur = NULL;
}
#endif
}
if(!s || !xctx || !xctx->inst) {
return empty;
}
#ifdef __unix__
if(!get_sp_cur) {
get_sp_cur = my_malloc(_ALLOC_ID_, sizeof(regex_t));
/* @spice_get_current_param(...) or @spice_get_modelparam_param(...) */
/* @spice_get_current_<param>(...) or @spice_get_modelparam_<param>(...) */
/* @spice_get_current(...) or @spice_get_modelparam(...) */
/* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...) */
/* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_<param>(...) */
regcomp(get_sp_cur,
"^@spice_get_(current|modelparam|modelvoltage)(_[a-zA-Z][a-zA-Z0-9_]*)*\\(", REG_NOSUB | REG_EXTENDED);
}
#endif
sp_prefix = tclgetboolvar("spiceprefix");
@ -4116,13 +4158,17 @@ const char *translate(int inst, const char* s)
}
}
}
/* @spice_get_current(...) or @spice_get_current_param(...)
* @spice_get_modelparam(...) or @spice_get_modelparam_param(...)
* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...)
/* @spice_get_current(...) or @spice_get_current_<param>(...)
* @spice_get_modelparam(...) or @spice_get_modelparam_<param>(...)
* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_<param>(...)
*
* Only @spice_get_current(...) and @spice_get_current_param(...) are processed
* Only @spice_get_current(...) and @spice_get_current_<param>(...) are processed
* the other types are ignored */
#ifdef __unix__
else if(!regexec(get_sp_cur, token, 0 , NULL, 0) )
# else
else if ((win_regexec(NULL/*options*/, "^@spice_get_(current|modelparam|modelvoltage)(_[a-zA-Z][a-zA-Z0-9_]*)*\\(", token)))
#endif
{
int start_level; /* hierarchy level where waves were loaded */
int live = tclgetboolvar("live_cursor2_backannotate");
@ -4148,7 +4194,8 @@ const char *translate(int inst, const char* s)
n = sscanf(token + 19, "%[^)]", dev);
} else {
param = my_malloc(_ALLOC_ID_, tmp);
n = sscanf(token, "@spice_get_current_%s(%[^)]", param, dev);
n = sscanf(token, "@spice_get_current_%[^(](%[^)]", param, dev);
dbg(1, "token=%s, param=%s, dev=%s\n", token, param, dev);
if(n < 2) {
my_free(_ALLOC_ID_, &param);
n = sscanf(token, "@spice_get_current[^(](%[^)]", dev);
@ -4173,6 +4220,7 @@ const char *translate(int inst, const char* s)
my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "ic");
} else if(prefix == 'd' || prefix == 'm') {
my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "id");
dbg(1, "translate(): fqdev=%s\n", fqdev);
} else if(prefix == 'i') {
my_snprintf(fqdev, len, "i(@%c.%s%s.%s[current])", prefix, path, instname, dev);
} else {
@ -4605,7 +4653,6 @@ const char *translate2(Lcc *lcc, int level, char* s)
}
else if(strcmp(token,"@path")==0) {
char *path = NULL;
here(level);
my_strdup2(_ALLOC_ID_, &path, "@path@name\\.");
if(level > 1) { /* add parent LCC instance names (X1, Xinv etc) */
int i;

View File

@ -453,6 +453,11 @@ int verilog_block_netlist(FILE *fd, int i, int alert)
tclgetvar("netlist_dir"), get_cell(name, 0), getpid());
dbg(1, "global_vhdl_netlist(): split_files: netl_filename=%s\n", netl_filename);
fd=fopen(netl_filename, "w");
if(!fd) {
dbg(0, "verilog_block_netlist(): unable to write file %s\n", netl_filename);
err = 1;
goto err;
}
my_snprintf(cellname, S(cellname), "%s.v", get_cell(name, 0));
}
@ -619,6 +624,7 @@ int verilog_block_netlist(FILE *fd, int i, int alert)
set_tcl_netlist_type();
if(debug_var==0) xunlink(netl_filename);
}
err:
xctx->netlist_count++;
my_free(_ALLOC_ID_, &name);
return err;

View File

@ -538,6 +538,11 @@ int vhdl_block_netlist(FILE *fd, int i, int alert)
tclgetvar("netlist_dir"), get_cell(xctx->sym[i].name, 0), getpid());
dbg(1, "vhdl_block_netlist(): split_files: netl_filename=%s\n", netl_filename);
fd=fopen(netl_filename, "w");
if(!fd) {
dbg(0, "vhdl_block_netlist(): unable to write file %s\n", netl_filename);
err = 1;
goto err;
}
my_snprintf(cellname, S(cellname), "%s.vhdl", get_cell(xctx->sym[i].name, 0) );
}
@ -721,6 +726,7 @@ int vhdl_block_netlist(FILE *fd, int i, int alert)
set_tcl_netlist_type();
if(debug_var==0) xunlink(netl_filename);
}
err:
xctx->netlist_count++;
return err;
}

View File

@ -361,10 +361,10 @@ void init_pixdata()/* populate xctx->fill_type array that is used in create_gc()
if(pixdata[i][j]!=0xff) full=0;
if(pixdata[i][j]!=0x00) empty=0;
}
if(full) xctx->fill_type[i] = 1;
if(full) xctx->fill_type[i] = 2;
else if(empty) xctx->fill_type[i] = 0;
else xctx->fill_type[i]=2;
if(rainbow_colors && i>5) xctx->fill_type[i]=1; /* 20171212 solid fill style */
else xctx->fill_type[i]=1;
if(rainbow_colors && i>5) xctx->fill_type[i]=2; /* 20171212 solid fill style */
/*fprintf(errfp, "fill_type[%d]= %d\n", i, xctx->fill_type[i]); */
}
}
@ -434,7 +434,7 @@ void create_gc(void)
xctx->gc[i] = XCreateGC(display,xctx->window,0L,NULL);
xctx->gcstipple[i] = XCreateGC(display,xctx->window,0L,NULL);
XSetStipple(display,xctx->gcstipple[i],pixmap[i]);
if(xctx->fill_type[i]==1) XSetFillStyle(display,xctx->gcstipple[i],FillSolid);
if(xctx->fill_type[i]==2) XSetFillStyle(display,xctx->gcstipple[i],FillSolid);
else XSetFillStyle(display,xctx->gcstipple[i],FillStippled);
}
}
@ -1177,12 +1177,20 @@ static int source_tcl_file(char *s)
if(Tcl_EvalFile(interp, s)==TCL_ERROR) {
fprintf(errfp, "Tcl_AppInit() error: can not execute %s, please fix:\n", s);
fprintf(errfp, "Line No: %d\n", Tcl_GetErrorLine(interp));
fprintf(errfp, "%s", tclresult());
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6
fprintf(errfp, "Line No: %d\n", Tcl_GetErrorLine(interp));
#endif
fprintf(errfp, "\n");
#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >=6
my_snprintf(tmp, S(tmp), "tk_messageBox -icon error -type ok -message \
{Tcl_AppInit() err 1: can not execute %s, please fix:\n%s\nLine No: %d\n}",
s, tclresult(), Tcl_GetErrorLine(interp));
#else
my_snprintf(tmp, S(tmp), "tk_messageBox -icon error -type ok -message \
{Tcl_AppInit() err 1: can not execute %s, please fix:\n%s\n}",
s, tclresult());
#endif
if(has_x) {
tcleval( "wm withdraw .");
tcleval( tmp);

View File

@ -491,7 +491,7 @@ typedef struct
unsigned short sel;
char *prop_ptr;
void *extraptr; /* generic data pointer (images) */
short fill;
short fill; /* 0: no fill, 1: stippled fill, 2: solid fill */
short dash;
int ellipse_a, ellipse_b;
/* bit0=1 for graph function, bit1=1 for unlocked x axis
@ -1648,6 +1648,7 @@ extern char *my_free(int id, void *ptr);
extern size_t my_strcat(int id, char **, const char *);
extern size_t my_strcat2(int id, char **, const char *);
extern size_t my_mstrcat(int id, char **str, const char *append_str, ...);
extern FILE * my_fopen(const char *f, const char *m);
extern void *my_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
extern char *my_itoa(int i);
extern double atof_spice(const char *s);
@ -1764,4 +1765,5 @@ extern const char *create_tmpdir(char *prefix);
extern FILE *open_tmpfile(char *prefix, char *suffix, char **filename);
extern void create_ps(char** psfile, int what, int fullzoom, int eps);
extern void MyXCopyArea(Display* display, Drawable src, Drawable dest, GC gc, int src_x, int src_y, unsigned int width, unsigned int height, int dest_x, int dest_y);
extern int win_regexec(const char *options, const char *pattern, const char *name);
#endif /*CADGLOBALS */

View File

@ -693,6 +693,72 @@ proc spaces {n {indent 4}} {
return [string repeat { } $n]
}
# complex number operators
# a + b
proc cadd {a b} {
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra + $rb}] [expr {$ia + $ib}]]
return $c
}
# a - b
proc csub {a b} {
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra - $rb}] [expr {$ia - $ib}]]
return $c
}
# a * b
proc cmul {a b} {
lassign $a ra ia
lassign $b rb ib
set c [list [expr {$ra * $rb - $ia * $ib}] [expr {$ra * $ib + $rb * $ia}]]
return $c
}
# a / b
proc cdiv {a b} {
lassign $a ra ia
lassign $b rb ib
set ra [expr {double($ra)}]
set ia [expr {double($ia)}]
set rb [expr {double($rb)}]
set ib [expr {double($ib)}]
set m [expr {$rb * $rb + $ib * $ib}]
set c [list [expr {($ra * $rb + $ia * $ib) / $m}] [expr {($rb * $ia - $ra * $ib) / $m}]]
return $c
}
# 1/b
proc cinv {b} {
lassign $b rb ib
set rb [expr {double($rb)}]
set ib [expr {double($ib)}]
set m [expr {$rb * $rb + $ib * $ib}]
set c [list [expr {$rb / $m}] [expr {-$ib / $m}]]
return $c
}
# return real component
proc creal {a} {
lassign $a ra ia
return $ra
}
# return imaginary component
proc cimag {a} {
lassign $a ra ia
return $ia
}
# return resulting impedance of parallel connected impedances a and b
proc cparallel {a b} {
return [cdiv [cmul $a $b] [cadd $a $b]]
}
# wraps provided table formatted text into a nice looking bordered table
# sep is the list of characters used as separators, default are { }, {,}, {\t}
# if you want to tabulate data with spaces use only {,} as separator or any other character.
@ -6021,6 +6087,50 @@ proc edit_prop {txtlabel} {
return $tctx::rcode
}
# reads metadata tokens from header component of the symbol inside `v {data}` element
# and returns dictionary in name of the token as key and value of the token as value in dictionary
# Courtesy @georgtree
proc symbolParse {file} {
try {
set file [open $file r]
} on error {errmsg erropts} {
puts stderr "Error while reading symbol file '$file': $errmsg"
return
}
set data [read $file]
close $file
# pattern to find v {} and extract content inside brackets
set pattern {(?:^|\n)v\s+\{((?:[^{}]|\\[{}])*)\}}
if {![regexp $pattern $data -> content]} {
return
}
# outer braces {...} are not part of content, so remove escaping of inner {, } and \ .
set content [string map { \\\{ \{ \\\} \} \\\\ \\ } $content]
# pattern to find: name="value" or name=value or name = "value" or name = value
set pattern {(\w+)\s*=\s*(?:"((?:[^"]|\\["])*)"|(\S+))}
set start 0
# 'match' variable holds the complete matched pattern, used for searching next one
while {[regexp -start $start $pattern $content -> name quotedValue unquotedValue]} {
# Determine the value (quoted or unquoted)
if {[string length $quotedValue] > 0} {
set value $quotedValue
# outer quotes are removed from value,
# remove escaping of internal backslashes and doublequotes
dict append tokens $name [string map {\\\\ \\ \\\" \" } $value]
} else {
set value $unquotedValue
dict append tokens $name $value
}
# Update the start index to continue searching after this match
set start [expr {[string first $value $content $start] + [string length $value]}]
# Safety check to prevent infinite loops
if {$start <= 0} {
break
}
}
return $tokens
}
proc read_data_nonewline {f} {
set fid [open $f r]
set data [read -nonewline $fid]
@ -6631,8 +6741,12 @@ proc try_download_url {dirname sch_or_sym} {
# Example: rel_sym_path /home/schippes/share/xschem/xschem_library/devices/iopin.sym
# devices/iopin.sym
proc rel_sym_path {symbol} {
global OS pathlist
global OS pathlist env
regsub {^~/} $symbol ${env(HOME)}/ symbol
if {![regexp {^/} $symbol]} {
set symbol [pwd]/$symbol
}
set curr_dirname [pwd]
set name {}
foreach path_elem $pathlist {
@ -7768,7 +7882,8 @@ set tctx::global_list {
toolbar_visible top_is_subckt transparent_svg undo_type use_lab_wire unselect_partial_sel_wires
use_label_prefix use_tclreadline
user_wants_copy_cell verilog_2001 verilog_bitblast viewdata_fileid viewdata_filename viewdata_w
tctx::vsize xschem_libs xschem_listen_port zoom_full_center
tctx::vsize xschem_libs xschem_listen_port zoom_full_center orthogonal_wiring snap_cursor
snap_cursor_size cadence_compat use_cursor_for_selection
}
## list of global arrays to save/restore on context switching
@ -8056,7 +8171,7 @@ proc pack_widgets { { topwin {} } } {
pack $topwin.statusbar.6 -side left
pack $topwin.statusbar.7 -side left
pack $topwin.statusbar.10 -side left
pack $topwin.statusbar.11 -side left
pack $topwin.statusbar.11 -side left
pack $topwin.statusbar.9 -side left
pack $topwin.statusbar.8 -side left
pack $topwin.statusbar.1 -side left -fill x
@ -9228,6 +9343,7 @@ set_ne big_grid_points 0
set_ne draw_grid_axes 1
set_ne persistent_command 0
set_ne intuitive_interface 1
set_ne use_cursor_for_selection 0
set_ne autotrim_wires 0
set_ne cadence_compat 0
set_ne infix_interface 1

View File

@ -294,6 +294,19 @@
#### set cadence_compat; Default: 0 (Cadence-style keybinds are not used by default)
# set cadence_compat 1
#### enable drawing a diamond-shaped cursor at the closest circuit endpoint. Default: disabled (0)
# set snap_cursor 1
#### set snap_cursor_size; Default: 6 (Diamond-shaped cursor that snaps to nearest circuit endpoint)
# set snap_cursor_size 6
#### set cadence_compat; Default: 0 (Cadence-style keybinds are not used by default)
# set cadence_compat 1
#### if set, then, when cursor (regardless of style) is on an object, and user clicks (though mouse pointer is not on the object),
#### the object is selected. Default: 0
# set use_cursor_for_selection 1
#### enable to scale grid point size as done with lines at close zoom, default: 0
# set big_grid_points 0
@ -647,3 +660,6 @@
#### Default: not enabled (0)
# set fix_mouse_coord 0
#### redefine some variables to emulate Cadence UI / bindkeys
# source /home/schippes/share/xschem/cadence_style_rc

View File

@ -1,4 +1,4 @@
v {xschem version=3.4.5 file_version=1.2
v {xschem version=3.4.6 file_version=1.2
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
@ -47,7 +47,7 @@ T {@#0:pinnumber} -10 -27.5 0 1 0.2 0.2 {layer=13}
T {@#1:pinnumber} -10 17.5 0 1 0.2 0.2 {layer=13}
T {@#0:net_name} 5 -42.5 0 0 0.15 0.15 {layer=15 hide=instance}
T {@#1:net_name} 5 32.5 0 0 0.15 0.15 {layer=15 hide=instance}
T {@name} 15 -18.75 0 0 0.2 0.2 {}
T {@value} 15 -3.75 0 0 0.2 0.2 {}
T {m=@m} 15 11.25 0 0 0.2 0.2 {}
T {@spice_get_current} -12.5 5 0 1 0.2 0.2 {layer=17}
T {@name} 15 -18.75 0 0 0.2 0.2 {}
T {@value} 15 -6.25 0 0 0.2 0.2 {}
T {m=@m} 15 6.25 0 0 0.2 0.2 {}

View File

@ -21,21 +21,21 @@ v {xschem version=3.4.6 file_version=1.2
}
G {}
K {type=opamp_va
format="@name @@OUT @@IN1 @@IN2 @model"
format="@name @@OUT @@IN1 @@IN2 @model gain=@gain amplitude=@amplitude offset=@offset"
template="name=X1 model=diff_amp_cell"
template="name=X1 model=diff_amp_cell gain=40 amplitude=3 offset=1.5"
device_model="tcleval(
.subckt diff_amp_cell OUT IN1 IN2
N1 out in1 in2 diff_amp_model
.ends diff_amp_cell
.model diff_amp_model diff_amp
.control
* following line specifies the location for the .osdi file so ngspice can use it.
pre_osdi $USER_CONF_DIR/xschem_library/diff_amp.osdi
.endc
.model diff_amp_model diff_amp $ gain=40 amplitude=3 offset=1.5
.subckt diff_amp_cell OUT IN1 IN2 gain=40 amplitude=3 offset=1.5
N1 out in1 in2 diff_amp_model gain=gain amplitude=amplitude offset=offset
.ends diff_amp_cell
)"
}
V {}

View File

@ -25,8 +25,8 @@ V {}
S {}
E {}
B 2 840 -580 1640 -170 {flags=graph
y1=0
y2=6
y1=6.3e-14
y2=5
ypos1=0
ypos2=2
divy=5
@ -49,7 +49,7 @@ logy=0
}
B 2 840 -990 1640 -580 {flags=graph
y1=0
y2=40
y2=100
ypos1=0
ypos2=2
divy=5
@ -68,10 +68,9 @@ unitx=1
logx=0
logy=0
}
P 4 5 140 -600 140 -880 710 -880 710 -600 140 -600 {}
P 4 5 30 -600 30 -880 740 -880 740 -600 30 -600 {}
P 4 7 410 -600 410 -560 420 -560 410 -540 400 -560 410 -560 410 -600 {}
T {// importing libs
`include "discipline.h"
module diff_amp(
@ -79,17 +78,17 @@ module diff_amp(
input electrical in1,
input electrical in2);
parameter real gain = 40; // setting gain to 40 of the differential amplifier
parameter real vcc = 3; // swing from -vcc/2 to +vcc/2
parameter real offset = 3;// added offset
(* desc="gain", units="", type="instance" *) parameter real gain = 40 from [-inf: inf];
(* desc="amplitude", units="", type="instance" *) parameter real amplitude = 3 from [-inf: inf];
(* desc="offset", units="", type="instance" *) parameter real offset = 1.5 from [-inf: inf];
analog begin
V(out) <+ offset / 2 + vcc / 2 * tanh( gain / vcc * 2 * V(in1, in2));
V(out) <+ offset + amplitude / 2 * tanh( gain / amplitude * 2 * V(in1, in2));
end
endmodule
} 150 -870 0 0 0.2 0.2 {font=monospace}
} 40 -870 0 0 0.2 0.2 {font=monospace}
T {create a diff_amp.va file with following code
and compile it into a .osdi file with openvaf.} 190 -940 0 0 0.4 0.4 {}
N 180 -450 320 -450 {lab=B}
@ -100,7 +99,6 @@ N 180 -330 180 -290 {lab=0}
N 80 -330 80 -290 {lab=0}
N 80 -530 80 -390 {lab=A}
N 180 -450 180 -390 {lab=B}
C {diff_amp.sym} 420 -490 0 0 {name=X1}
C {lab_pin.sym} 640 -490 0 1 {name=p1 sig_type=std_logic lab=Z}
C {lab_pin.sym} 80 -530 0 0 {name=p2 sig_type=std_logic lab=A}
C {lab_pin.sym} 180 -450 0 0 {name=p3 sig_type=std_logic lab=B}
@ -118,7 +116,7 @@ C {code_shown.sym} 240 -320 0 0 {name=COMMANDS only_toplevel=false value="
set appendwrite
remzerovec
write tb_diff_amp.raw
quit 0
* quit 0
.endc
"}
C {launcher.sym} 670 -120 0 0 {name=h5
@ -130,3 +128,4 @@ C {launcher.sym} 670 -170 0 0 {name=h1
descr="OP annotate"
tclcommand="xschem annotate_op"
}
C {diff_amp.sym} 420 -490 0 0 {name=X1 model=diff_amp_cell gain=100 amplitude=5 offset=2.5}