/* File: select.c * * This file is part of XSCHEM, * a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit * simulation. * Copyright (C) 1998-2020 Stefan Frederik Schippers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xschem.h" static int rot = 0; static int flip = 0; static double xx1,yy1,xx2,yy2; void symbol_bbox(int i, double *x1,double *y1, double *x2, double *y2) { int j; xText text; const char *tmp_txt; int rot,flip; double x0, y0 ; double text_x0, text_y0; int sym_rot, sym_flip; double xx1,yy1,xx2,yy2; #ifdef HAS_CAIRO int customfont; #endif /* symbol bbox */ flip = xctx->inst[i].flip; rot = xctx->inst[i].rot; x0=xctx->inst[i].x0; y0=xctx->inst[i].y0; ROTATION(0.0,0.0,(xctx->inst[i].ptr+ xctx->sym)->minx, (xctx->inst[i].ptr+ xctx->sym)->miny,*x1,*y1); ROTATION(0.0,0.0,(xctx->inst[i].ptr+ xctx->sym)->maxx, (xctx->inst[i].ptr+ xctx->sym)->maxy,*x2,*y2); RECTORDER(*x1,*y1,*x2,*y2); *x1+=x0;*y1+=y0; *x2+=x0;*y2+=y0; xctx->inst[i].xx1 = *x1; /* 20070314 added bbox without text */ xctx->inst[i].yy1 = *y1; /* for easier select */ xctx->inst[i].xx2 = *x2; xctx->inst[i].yy2 = *y2; dbg(2, "symbol_bbox(): instance=%d %.16g %.16g %.16g %.16g\n",i,*x1, *y1, *x2, *y2); /* strings bbox */ for(j=0;j< (xctx->inst[i].ptr+ xctx->sym)->texts;j++) { sym_flip = flip; sym_rot = rot; text = (xctx->inst[i].ptr+ xctx->sym)->text[j]; dbg(2, "symbol_bbox(): instance %d text n: %d text str=%s\n", i,j, text.txt_ptr? text.txt_ptr:"NULL"); tmp_txt = translate(i, text.txt_ptr); dbg(2, "symbol_bbox(): translated text: %s\n", tmp_txt); ROTATION(0.0,0.0,text.x0, text.y0,text_x0,text_y0); #ifdef HAS_CAIRO customfont=set_text_custom_font(&text); #endif text_bbox(tmp_txt, text.xscale, text.yscale, (text.rot + ( (sym_flip && (text.rot & 1) ) ? sym_rot+2 : sym_rot)) &0x3, sym_flip ^ text.flip, text.hcenter, text.vcenter, x0+text_x0,y0+text_y0, &xx1,&yy1,&xx2,&yy2); #ifdef HAS_CAIRO if(customfont) cairo_restore(cairo_ctx); #endif if(xx1<*x1) *x1=xx1; if(yy1<*y1) *y1=yy1; if(xx2>*x2) *x2=xx2; if(yy2>*y2) *y2=yy2; dbg(2, "symbol_bbox(): instance=%d text=%d %.16g %.16g %.16g %.16g\n",i,j, *x1, *y1, *x2, *y2); } } static void del_rect_line_arc_poly(void) { xRect tmp; int c, j, i; for(c=0;crects[c];i++) { if(xctx->rect[c][i].sel == SELECTED) { j++; bbox(ADD, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2); my_free(928, &xctx->rect[c][i].prop_ptr); set_modify(1); continue; } if(j) { xctx->rect[c][i-j] = xctx->rect[c][i]; } } xctx->rects[c] -= j; j = 0; for(i=0;ilines[c];i++) { if(xctx->line[c][i].sel == SELECTED) { j++; if(xctx->line[c][i].bus){ int ov, y1, y2; ov = INT_BUS_WIDTH(xctx->lw); if(xctx->line[c][i].y1 < xctx->line[c][i].y2) { y1 = xctx->line[c][i].y1-ov; y2 = xctx->line[c][i].y2+ov; } else { y1 = xctx->line[c][i].y1+ov; y2 = xctx->line[c][i].y2-ov; } bbox(ADD, xctx->line[c][i].x1-ov, y1 , xctx->line[c][i].x2+ov , y2 ); } else { bbox(ADD, xctx->line[c][i].x1, xctx->line[c][i].y1 , xctx->line[c][i].x2 , xctx->line[c][i].y2 ); } set_modify(1); my_free(929, &xctx->line[c][i].prop_ptr); continue; } if(j) { xctx->line[c][i-j] = xctx->line[c][i]; } } xctx->lines[c] -= j; j = 0; for(i=0;iarcs[c];i++) { if(xctx->arc[c][i].sel == SELECTED) { j++; if(xctx->arc[c][i].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 arc_bbox(xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2); bbox(ADD, tmp.x1, tmp.y1, tmp.x2, tmp.y2); my_free(930, &xctx->arc[c][i].prop_ptr); set_modify(1); continue; } if(j) { xctx->arc[c][i-j] = xctx->arc[c][i]; } } xctx->arcs[c] -= j; j = 0; for(i=0;ipolygons[c];i++) { if(xctx->poly[c][i].sel == SELECTED) { int k; double x1=0., y1=0., x2=0., y2=0.; for(k=0; kpoly[c][i].points; k++) { if(k==0 || xctx->poly[c][i].x[k] < x1) x1 = xctx->poly[c][i].x[k]; if(k==0 || xctx->poly[c][i].y[k] < y1) y1 = xctx->poly[c][i].y[k]; if(k==0 || xctx->poly[c][i].x[k] > x2) x2 = xctx->poly[c][i].x[k]; if(k==0 || xctx->poly[c][i].y[k] > y2) y2 = xctx->poly[c][i].y[k]; } j++; bbox(ADD, x1, y1, x2, y2); my_free(931, &xctx->poly[c][i].prop_ptr); my_free(932, &xctx->poly[c][i].x); my_free(933, &xctx->poly[c][i].y); my_free(934, &xctx->poly[c][i].selected_point); /*fprintf(errfp, "bbox: %.16g %.16g %.16g %.16g\n", x1, y1, x2, y2); */ set_modify(1); continue; } if(j) { xctx->poly[c][i-j] = xctx->poly[c][i]; } } xctx->polygons[c] -= j; } } void delete(void) { int i, j, n; #ifdef HAS_CAIRO int customfont; #endif dbg(3, "delete(): start\n"); j = 0; bbox(BEGIN, 0.0 , 0.0 , 0.0 , 0.0); rebuild_selected_array(); if(lastselected) push_undo(); /* first calculate bbox, because symbol_bbox() needs translate (@#0:net_name) which needs prepare_netlist_structs * which needs a consistent xctx->inst[] data structure */ /* does not seem to be needed prepared_netlist_structs=0; prepared_hilight_structs=0; */ if(show_pin_net_names) { prepare_netlist_structs(0); } for(i = 0; i < lastselected; i++) { n = selectedgroup[i].n; if(selectedgroup[i].type == ELEMENT) { int p; char *type = (xctx->inst[n].ptr + xctx->sym)->type; symbol_bbox(n, &xctx->inst[n].x1, &xctx->inst[n].y1, &xctx->inst[n].x2, &xctx->inst[n].y2 ); bbox(ADD, xctx->inst[n].x1, xctx->inst[n].y1, xctx->inst[n].x2, xctx->inst[n].y2 ); if(show_pin_net_names && type && IS_LABEL_OR_PIN(type) ) { for(p = 0; p < (xctx->inst[n].ptr + xctx->sym)->rects[PINLAYER]; p++) { if( xctx->inst[n].node && xctx->inst[n].node[p]) { find_inst_to_be_redrawn(xctx->inst[n].node[p]); } } } } if(show_pin_net_names && selectedgroup[i].type == WIRE && xctx->wire[n].node) { find_inst_to_be_redrawn(xctx->wire[n].node); } } if(show_pin_net_names) { find_inst_hash_clear(); } /* already done above for(i=0;iinstances;i++) { if(xctx->inst[i].sel == SELECTED) { symbol_bbox(i, &xctx->inst[i].x1, &xctx->inst[i].y1, &xctx->inst[i].x2, &xctx->inst[i].y2); bbox(ADD, xctx->inst[i].x1, xctx->inst[i].y1, xctx->inst[i].x2, xctx->inst[i].y2); } } */ for(i=0;itexts;i++) { if(xctx->text[i].sel == SELECTED) { rot = xctx->text[i].rot; flip = xctx->text[i].flip; #ifdef HAS_CAIRO customfont = set_text_custom_font(&xctx->text[i]); #endif text_bbox(xctx->text[i].txt_ptr, xctx->text[i].xscale, xctx->text[i].yscale, rot, flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0, xctx->text[i].y0, &xx1,&yy1, &xx2,&yy2); #ifdef HAS_CAIRO if(customfont) cairo_restore(cairo_ctx); #endif bbox(ADD, xx1, yy1, xx2, yy2 ); my_free(935, &xctx->text[i].prop_ptr); my_free(936, &xctx->text[i].font); my_free(937, &xctx->text[i].txt_ptr); set_modify(1); j++; continue; } if(j) { dbg(1, "select(); deleting string %d\n",i-j); xctx->text[i-j] = xctx->text[i]; dbg(1, "select(); new string %d = %s\n",i-j,xctx->text[i-j].txt_ptr); } } xctx->texts -= j; j = 0; for(i=0;iinstances;i++) { if(xctx->inst[i].sel == SELECTED) { set_modify(1); if(xctx->inst[i].prop_ptr != NULL) { my_free(938, &xctx->inst[i].prop_ptr); } delete_inst_node(i); my_free(939, &xctx->inst[i].name); my_free(940, &xctx->inst[i].instname); j++; continue; } if(j) { xctx->inst[i-j] = xctx->inst[i]; } } xctx->instances-=j; if(j) { prepared_hash_instances=0; prepared_netlist_structs=0; prepared_hilight_structs=0; } j = 0; for(i=0;iwires;i++) { if(xctx->wire[i].sel == SELECTED) { j++; if(xctx->wire[i].bus){ int ov, y1, y2; ov = INT_BUS_WIDTH(xctx->lw)> cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE; if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; } else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; } bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 ); } else { int ov, y1, y2; ov = cadhalfdotsize; if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; } else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; } bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 ); } my_free(941, &xctx->wire[i].prop_ptr); my_free(942, &xctx->wire[i].node); set_modify(1); continue; } if(j) { xctx->wire[i-j] = xctx->wire[i]; } } xctx->wires -= j; if(j) { prepared_hash_wires=0; prepared_netlist_structs=0; prepared_hilight_structs=0; } del_rect_line_arc_poly(); update_conn_cues(0, 0); lastselected = 0; bbox(SET , 0.0 , 0.0 , 0.0 , 0.0); draw(); bbox(END , 0.0 , 0.0 , 0.0 , 0.0); ui_state &= ~SELECTION; if(event_reporting) { printf("xschem delete\n"); fflush(stdout); } } void delete_only_rect_line_arc_poly(void) { bbox(BEGIN, 0.0 , 0.0 , 0.0 , 0.0); del_rect_line_arc_poly(); lastselected = 0; bbox(SET , 0.0 , 0.0 , 0.0 , 0.0); draw(); bbox(END , 0.0 , 0.0 , 0.0 , 0.0); ui_state &= ~SELECTION; } void bbox(int what,double x1,double y1, double x2, double y2) { int i; static int bbx1, bbx2, bby1, bby2; static int savew, saveh, savex1, savex2, savey1, savey2; static int sem=0; /* fprintf(errfp, "bbox: what=%d\n", what); */ switch(what) { case BEGIN: if(sem==1) { fprintf(errfp, "ERROR: rentrant bbox() call\n"); tcleval("alert_ {ERROR: reentrant bbox() call} {}"); } bbx1 = 300000000; bbx2 = 0; bby1 = 300000000; bby2 = 0; savex1 = areax1; savex2 = areax2; savey1 = areay1; savey2 = areay2; savew = areaw; saveh = areah; sem=1; break; case ADD: if(sem==0) { fprintf(errfp, "ERROR: bbox(ADD) call before bbox(BEGIN)\n"); tcleval("alert_ {ERROR: bbox(ADD) call before bbox(BEGIN)} {}"); } x1=X_TO_SCREEN(x1); y1=Y_TO_SCREEN(y1); x2=X_TO_SCREEN(x2); y2=Y_TO_SCREEN(y2); x1=CLIP(x1,savex1,savex2); x2=CLIP(x2,savex1,savex2); y1=CLIP(y1,savey1,savey2); y2=CLIP(y2,savey1,savey2); if(x1 < bbx1) bbx1 = (int) x1; if(x2 > bbx2) bbx2 = (int) x2; if(y1 < bby1) bby1 = (int) y1; if(y2 > bby2) bby2 = (int) y2; if(y2 < bby1) bby1 = (int) y2; if(y1 > bby2) bby2 = (int) y1; break; case END: areax1 = savex1; areax2 = savex2; areay1 = savey1; areay2 = savey2; areaw = savew; areah = saveh; xrect[0].x = 0; xrect[0].y = 0; xrect[0].width = areaw-4*INT_WIDTH(xctx->lw); xrect[0].height = areah-4*INT_WIDTH(xctx->lw); XSetClipMask(display, gctiled, None); /* 20171110 optimization, clipping already done in software */ for(i=0;ilw); areax2 = bbx2+2*INT_WIDTH(xctx->lw); areay1 = bby1-2*INT_WIDTH(xctx->lw); areay2 = bby2+2*INT_WIDTH(xctx->lw); areaw = (areax2-areax1); areah = (areay2-areay1); xrect[0].x = bbx1-INT_WIDTH(xctx->lw); xrect[0].y = bby1-INT_WIDTH(xctx->lw); xrect[0].width = bbx2-bbx1+2*INT_WIDTH(xctx->lw); xrect[0].height = bby2-bby1+2*INT_WIDTH(xctx->lw); for(i=0;iwires;i++) { if(xctx->wire[i].sel) { xctx->wire[i].sel = 0; { if(xctx->wire[i].bus) drawtempline(gctiled, THICK, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); else drawtempline(gctiled, ADD, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); } } } for(i=0;iinstances;i++) { if(xctx->inst[i].sel == SELECTED) { xctx->inst[i].sel = 0; for(c=0;cinst[i].instname, PATH_MAX)); fflush(stdout); } } } for(i=0;itexts;i++) { if(xctx->text[i].sel == SELECTED) { xctx->text[i].sel = 0; #ifdef HAS_CAIRO customfont = set_text_custom_font(& xctx->text[i]); /* needed for bbox calculation */ #endif draw_temp_string(gctiled,ADD, xctx->text[i].txt_ptr, xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0, xctx->text[i].y0, xctx->text[i].xscale, xctx->text[i].yscale); #ifdef HAS_CAIRO if(customfont) cairo_restore(cairo_ctx); #endif } } for(c=0;carcs[c];i++) { if(xctx->arc[c][i].sel) { xctx->arc[c][i].sel = 0; drawtemparc(gctiled, ADD, xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b); } } for(i=0;irects[c];i++) { if(xctx->rect[c][i].sel) { xctx->rect[c][i].sel = 0; drawtemprect(gctiled, ADD, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2); } } for(i=0;ilines[c];i++) { if(xctx->line[c][i].sel) { xctx->line[c][i].sel = 0; if(xctx->line[c][i].bus) drawtempline(gctiled, THICK, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); else drawtempline(gctiled, ADD, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); } } for(i=0;ipolygons[c];i++) { if(xctx->poly[c][i].sel) { int k; for(k=0;kpoly[c][i].points; k++) xctx->poly[c][i].selected_point[k] = 0; xctx->poly[c][i].sel = 0; drawtemppolygon(gctiled, NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points); } } } drawtemparc(gctiled, END, 0.0, 0.0, 0.0, 0.0, 0.0); drawtemprect(gctiled, END, 0.0, 0.0, 0.0, 0.0); drawtempline(gctiled,END, 0.0, 0.0, 0.0, 0.0); ui_state &= ~SELECTION; /*\statusmsg("",2); */ my_snprintf(str, S(str), "%s/%s", user_conf_dir, ".selection.sch"); /* 20161115 PWD->HOME */ xunlink(str); if(event_reporting) { printf("xschem unselect_all\n"); fflush(stdout); } } void select_wire(int i,unsigned short select_mode, int fast) { char str[1024]; /* overflow safe */ /*my_strncpy(s,xctx->wire[i].prop_ptr!=NULL?xctx->wire[i].prop_ptr:"",256); */ if( !fast ) { my_snprintf(str, S(str), "selected wire: n=%d end1=%d end2=%d\nnode=%s",i, xctx->wire[i].end1, xctx->wire[i].end2, xctx->wire[i].prop_ptr? xctx->wire[i].prop_ptr: "(null)"); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g w = %.16g h = %.16g",i, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2-xctx->wire[i].x1, xctx->wire[i].y2-xctx->wire[i].y1 ); statusmsg(str,1); } if( ((xctx->wire[i].sel|select_mode) == (SELECTED1|SELECTED2)) || ((xctx->wire[i].sel == SELECTED) && select_mode) ) xctx->wire[i].sel = SELECTED; else xctx->wire[i].sel = select_mode; if(select_mode) { dbg(1, "select(): wire[%d].end1=%d, ,end2=%d\n", i, xctx->wire[i].end1, xctx->wire[i].end2); if(xctx->wire[i].bus) drawtempline(gc[SELLAYER], THICK, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); else drawtempline(gc[SELLAYER], ADD, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); } else { if(xctx->wire[i].bus) drawtempline(gctiled, THICK, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); else drawtempline(gctiled, NOW, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2); } need_rebuild_selected_array=1; } void select_element(int i,unsigned short select_mode, int fast, int override_lock) { int c, j; char str[1024]; /* overflow safe */ char s[256]; /* overflow safe */ if(!strcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true") && select_mode == SELECTED && !override_lock) return; my_strncpy(s,xctx->inst[i].prop_ptr!=NULL?xctx->inst[i].prop_ptr:"",S(s)); if(event_reporting) { char n[PATH_MAX]; printf("xschem search exact %d name %s\n", select_mode? 1:-1, escape_chars(n, xctx->inst[i].instname, PATH_MAX)); fflush(stdout); } if( !fast ) { my_snprintf(str, S(str), "selected element %d: %s properties: %s", i, xctx->inst[i].name,s); statusmsg(str,2); my_snprintf(str, S(str), "symbol name=%s", xctx->inst[i].name==NULL?"(null)":xctx->inst[i].name); statusmsg(str,2); /* 20190526 */ /*Why this? 20191125 only on small schematics. slow down on big schematics */ if(xctx->instances < 150) { prepare_netlist_structs(0); for(j=0;j< (xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER] ;j++) { if(xctx->inst[i].node && (xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr) { my_snprintf(str, S(str), "pin:%s -> %s", get_tok_value( (xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr,"name",0) , xctx->inst[i].node[j] ? xctx->inst[i].node[j] : "__UNCONNECTED_PIN__"); statusmsg(str,2); } } } my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g w = %.16g h = %.16g",i, xctx->inst[i].xx1, xctx->inst[i].yy1, xctx->inst[i].xx2-xctx->inst[i].xx1, xctx->inst[i].yy2-xctx->inst[i].yy1 ); statusmsg(str,1); } xctx->inst[i].sel = select_mode; if(select_mode) { for(c=0;ctext[i].prop_ptr!=NULL?xctx->text[i].prop_ptr:"",S(s)); my_snprintf(str, S(str), "selected text %d: properties: %s", i,s); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g", i, xctx->text[i].x0, xctx->text[i].y0); statusmsg(str,1); } xctx->text[i].sel = select_mode; #ifdef HAS_CAIRO customfont = set_text_custom_font(&xctx->text[i]); #endif if(select_mode) draw_temp_string(gc[SELLAYER],ADD, xctx->text[i].txt_ptr, xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0, xctx->text[i].y0, xctx->text[i].xscale, xctx->text[i].yscale); else draw_temp_string(gctiled,NOW, xctx->text[i].txt_ptr, xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0, xctx->text[i].y0, xctx->text[i].xscale, xctx->text[i].yscale); #ifdef HAS_CAIRO if(customfont) cairo_restore(cairo_ctx); #endif need_rebuild_selected_array=1; } void select_box(int c, int i, unsigned short select_mode, int fast) { char str[1024]; /* overflow safe */ char s[256]; /* overflow safe */ if(!fast) { my_strncpy(s,xctx->rect[c][i].prop_ptr!=NULL?xctx->rect[c][i].prop_ptr:"",S(s)); my_snprintf(str, S(str), "selected box : layer=%d, n=%d properties: %s",c-4,i,s); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g w = %.16g h = %.16g", i, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2-xctx->rect[c][i].x1, xctx->rect[c][i].y2-xctx->rect[c][i].y1 ); statusmsg(str,1); } if(select_mode) { if(select_mode==SELECTED) { xctx->rect[c][i].sel = select_mode; } else { xctx->rect[c][i].sel |= select_mode; } drawtemprect(gc[SELLAYER], ADD, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2); } else { xctx->rect[c][i].sel = 0; drawtemprect(gctiled, NOW, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2); } if( xctx->rect[c][i].sel == (SELECTED1|SELECTED2|SELECTED3|SELECTED4)) xctx->rect[c][i].sel = SELECTED; need_rebuild_selected_array=1; } void select_arc(int c, int i, unsigned short select_mode, int fast) { char str[1024]; /* overflow safe */ char s[256]; /* overflow safe */ if(!fast) { my_strncpy(s,xctx->rect[c][i].prop_ptr!=NULL?xctx->rect[c][i].prop_ptr:"",S(s)); my_snprintf(str, S(str), "selected arc : layer=%d, n=%d properties: %s",c-4,i,s); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g r = %.16g a = %.16g b = %.16g", i, xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b); statusmsg(str,1); } if(select_mode) { xctx->arc[c][i].sel = select_mode; drawtemparc(gc[SELLAYER], ADD, xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b); } else { xctx->arc[c][i].sel = 0; drawtemparc(gctiled, NOW, xctx->arc[c][i].x, xctx->arc[c][i].y, xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b); } /*if( xctx->arc[c][i].sel == (SELECTED1|SELECTED2|SELECTED3|SELECTED4)) xctx->arc[c][i].sel = SELECTED; */ need_rebuild_selected_array=1; } void select_connected_nets(void) { int i, n; char *str = NULL; prepare_netlist_structs(0); rebuild_selected_array(); for(i=0;iwire[n].sel==SELECTED) { my_strdup(62, &str ,get_tok_value(xctx->wire[n].prop_ptr, "lab",0)); if(str && str[0]) { search("lab", str,1, 1, NOW); } } break; case ELEMENT: if(xctx->inst[n].sel==SELECTED) { my_strdup(63, &str, get_tok_value(xctx->inst[n].prop_ptr, "lab",0)); if(str && str[0]) { search("lab", str,1, 1, NOW); } } break; default: break; } } my_free(943, &str); } void select_polygon(int c, int i, unsigned short select_mode, int fast ) { char str[1024]; /* overflow safe */ char s[256]; /* overflow safe */ if(!fast) { my_strncpy(s,xctx->poly[c][i].prop_ptr!=NULL?xctx->poly[c][i].prop_ptr:"",S(s)); my_snprintf(str, S(str), "selected polygon: layer=%d, n=%d properties: %s",c-4,i,s); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x0 = %.16g y0 = %.16g ...", i, xctx->poly[c][i].x[0], xctx->poly[c][i].y[0]); statusmsg(str,1); } xctx->poly[c][i].sel = select_mode; if(select_mode) { drawtemppolygon(gc[SELLAYER], NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points); } else drawtemppolygon(gctiled, NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points); need_rebuild_selected_array=1; } void select_line(int c, int i, unsigned short select_mode, int fast ) { char str[1024]; /* overflow safe */ char s[256]; /* overflow safe */ if(!fast) { my_strncpy(s,xctx->line[c][i].prop_ptr!=NULL?xctx->line[c][i].prop_ptr:"",S(s)); my_snprintf(str, S(str), "selected line: layer=%d, n=%d properties: %s",c-4,i,s); statusmsg(str,2); my_snprintf(str, S(str), "n=%4d x = %.16g y = %.16g w = %.16g h = %.16g", i, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2-xctx->line[c][i].x1, xctx->line[c][i].y2-xctx->line[c][i].y1 ); statusmsg(str,1); } if( ((xctx->line[c][i].sel|select_mode) == (SELECTED1|SELECTED2)) || ((xctx->line[c][i].sel == SELECTED) && select_mode) ) xctx->line[c][i].sel = SELECTED; else xctx->line[c][i].sel = select_mode; if(select_mode) { if(xctx->line[c][i].bus) drawtempline(gc[SELLAYER], THICK, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); else drawtempline(gc[SELLAYER], ADD, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); } else if(xctx->line[c][i].bus) drawtempline(gctiled, THICK, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); else drawtempline(gctiled, NOW, xctx->line[c][i].x1, xctx->line[c][i].y1, xctx->line[c][i].x2, xctx->line[c][i].y2); need_rebuild_selected_array=1; } /* 20160503 return type field */ unsigned short select_object(double mousex,double mousey, unsigned short select_mode, int override_lock) { Selected sel; sel = find_closest_obj(mousex,mousey); dbg(1, "select_object(): sel.n=%d, sel.col=%d, sel.type=%d\n", sel.n, sel.col, sel.type); switch(sel.type) { case WIRE: select_wire(sel.n, select_mode, 0); break; case xTEXT: select_text(sel.n, select_mode, 0); break; case LINE: select_line(sel.col, sel.n, select_mode,0); break; case POLYGON: select_polygon(sel.col, sel.n, select_mode,0); break; case xRECT: select_box(sel.col,sel.n, select_mode,0); break; case ARC: select_arc(sel.col,sel.n, select_mode,0); break; case ELEMENT: select_element(sel.n,select_mode,0, override_lock); break; default: break; } /*end switch */ drawtemparc(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0); drawtemprect(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); drawtempline(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); if(sel.type) ui_state |= SELECTION; return sel.type; } void select_inside(double x1,double y1, double x2, double y2, int sel) /* 20150927 added unselect (sel param) */ { int c,i; double x, y, r, a, b, xa, ya, xb, yb; /* arc */ xRect tmp; #ifdef HAS_CAIRO int customfont; #endif for(i=0;iwires;i++) { if(RECTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1,xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2)) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ sel ? select_wire(i,SELECTED, 1): select_wire(i,0, 1); } else if( sel && enable_stretch && POINTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_wire(i,SELECTED1, 1); } else if( sel && enable_stretch && POINTINSIDE(xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_wire(i,SELECTED2, 1); } } for(i=0;itexts;i++) { rot = xctx->text[i].rot; flip = xctx->text[i].flip; #ifdef HAS_CAIRO customfont = set_text_custom_font(&xctx->text[i]); #endif text_bbox(xctx->text[i].txt_ptr, xctx->text[i].xscale, xctx->text[i].yscale, rot, flip, xctx->text[i].hcenter, xctx->text[i].vcenter, xctx->text[i].x0, xctx->text[i].y0, &xx1,&yy1, &xx2,&yy2); #ifdef HAS_CAIRO if(customfont) cairo_restore(cairo_ctx); #endif if(RECTINSIDE(xx1,yy1, xx2, yy2,x1,y1,x2,y2)) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ sel ? select_text(i, SELECTED, 1): select_text(i, 0, 1); } } for(i=0;iinstances;i++) { if(RECTINSIDE(xctx->inst[i].xx1, xctx->inst[i].yy1, xctx->inst[i].xx2, xctx->inst[i].yy2, x1,y1,x2,y2)) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ sel ? select_element(i,SELECTED,1, 0): select_element(i,0,1, 0); } } for(c=0;cpolygons[c]; i++) { int k, selected_points, flag; polygon_bbox(xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points, &xa, &ya, &xb, &yb); if(OUTSIDE(xa, ya, xb, yb, x1, y1, x2, y2)) continue; selected_points = 0; flag=0; for(k=0; kpoly[c][i].points; k++) { if(xctx->poly[c][i].sel==SELECTED) xctx->poly[c][i].selected_point[k] = 1; if( POINTINSIDE(xctx->poly[c][i].x[k],xctx->poly[c][i].y[k], x1,y1,x2,y2)) { flag=1; xctx->poly[c][i].selected_point[k] = sel; } if(xctx->poly[c][i].selected_point[k]) selected_points++; } if(flag) { if(selected_points==0) { select_polygon(c, i, 0, 1); } if(selected_points==xctx->poly[c][i].points) { ui_state |= SELECTION; select_polygon(c, i, SELECTED, 1); } else if(selected_points) { if(sel && enable_stretch) select_polygon(c, i, SELECTED1,1); /* for polygon, SELECTED1 means partial sel */ } } } for(i=0;ilines[c];i++) { if(RECTINSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1,xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2)) { ui_state |= SELECTION; sel? select_line(c,i,SELECTED,1): select_line(c,i,0,1); } else if( sel && enable_stretch && POINTINSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1, x1,y1,x2,y2) ) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ select_line(c, i,SELECTED1,1); } else if( sel && enable_stretch && POINTINSIDE(xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_line(c, i,SELECTED2,1); } } for(i=0;iarcs[c];i++) { x = xctx->arc[c][i].x; y = xctx->arc[c][i].y; a = xctx->arc[c][i].a; b = xctx->arc[c][i].b; r = xctx->arc[c][i].r; xa = x + r * cos(a * XSCH_PI/180.); ya = y - r * sin(a * XSCH_PI/180.); xb = x + r * cos((a+b) * XSCH_PI/180.); yb = y - r * sin((a+b) * XSCH_PI/180.); arc_bbox(x, y, r, a, b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2); if(RECTINSIDE(tmp.x1, tmp.y1, tmp.x2, tmp.y2, x1,y1,x2,y2)) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ sel? select_arc(c, i, SELECTED,1): select_arc(c, i, 0,1); } else if( sel && enable_stretch && POINTINSIDE(x, y, x1, y1, x2, y2) ) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED1,1); } else if( sel && enable_stretch && POINTINSIDE(xb, yb, x1, y1, x2, y2) ) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED3,1); } else if( sel && enable_stretch && POINTINSIDE(xa, ya, x1, y1, x2, y2) ) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED2,1); } } for(i=0;irects[c];i++) { if(RECTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y1,xctx->rect[c][i].x2,xctx->rect[c][i].y2, x1,y1,x2,y2)) { ui_state |= SELECTION; /* set ui_state to SELECTION also if unselecting by area ???? */ sel? select_box(c,i, SELECTED, 1): select_box(c,i, 0, 1); } else { if( sel && enable_stretch && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y1, x1,y1,x2,y2) ) { /*20070302 added stretch select */ ui_state |= SELECTION; select_box(c, i,SELECTED1,1); } if( sel && enable_stretch && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y1, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_box(c, i,SELECTED2,1); } if( sel && enable_stretch && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y2, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_box(c, i,SELECTED3,1); } if( sel && enable_stretch && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y2, x1,y1,x2,y2) ) { ui_state |= SELECTION; select_box(c, i,SELECTED4,1); } } } /* end for i */ } /* end for c */ drawtemparc(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0); drawtemprect(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); drawtempline(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); } void select_all(void) { int c,i; ui_state |= SELECTION; for(i=0;iwires;i++) { select_wire(i,SELECTED, 1); } for(i=0;itexts;i++) { select_text(i, SELECTED, 1); } for(i=0;iinstances;i++) { select_element(i,SELECTED,1, 0); } for(c=0;cpolygons[c];i++) { select_polygon(c,i,SELECTED,1); } for(i=0;ilines[c];i++) { select_line(c,i,SELECTED,1); } for(i=0;iarcs[c];i++) { select_arc(c,i, SELECTED, 1); } for(i=0;irects[c];i++) { select_box(c,i, SELECTED, 1); } } /* end for c */ drawtemparc(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0, 0.0); drawtemprect(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); drawtempline(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0); rebuild_selected_array(); }