/* File: move.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 double rx1, rx2, ry1, ry2; static int rot = 0; static int flip = 0; static double x1=0.0, y_1=0.0, x2=0.0, y_2=0.0, deltax = 0.0, deltay = 0.0; /* static int i,c,n,k; */ static int lastsel; static int rotatelocal=0; /* 20171208 */ void rebuild_selected_array() /* can be used only if new selected set is lower */ /* that is, selectedgroup[] size can not increase */ { int i,c; dbg(1, "rebuild selected array\n"); if(!need_rebuild_selected_array) return; lastselected=0; for(i=0;irects[PINLAYER]; for(p = 0; p < rects; p++) { if(node && inst_ptr[i].node[p] && !strcmp(inst_ptr[i].node[p], node )) { symbol_bbox(i, &inst_ptr[i].x1, &inst_ptr[i].y1, &inst_ptr[i].x2, &inst_ptr[i].y2 ); bbox(ADD, inst_ptr[i].x1, inst_ptr[i].y1, inst_ptr[i].x2, inst_ptr[i].y2 ); } } } } void copy_objects(int what) { int c, i, n, k; Box tmp; double angle; int newpropcnt; double tmpx, tmpy; int textlayer; const char *str; /* 20171112 */ #ifdef HAS_CAIRO char *textfont; int customfont; /* 20181009 */ #endif if(what & BEGIN) { rotatelocal=0; /*20171208 */ dbg(1, "copy_objects(): BEGIN copy\n"); rebuild_selected_array(); save_selection(1); deltax = deltay = 0.0; lastsel = lastselected; x1=mousex_snap;y_1=mousey_snap; flip = 0;rot = 0; ui_state|=STARTCOPY; } if(what & ABORT) /* draw objects while moving */ { char *str = NULL; /* 20161122 overflow safe */ draw_selection(gctiled,0); rot=flip=deltax=deltay=0; ui_state&=~STARTCOPY; my_strdup(225, &str, user_conf_dir); my_strcat(226, &str, "/.selection.sch"); xunlink(str); update_symbol_bboxes(); my_free(818, &str); } if(what & RUBBER) /* draw objects while moving */ { x2=mousex_snap;y_2=mousey_snap; draw_selection(gctiled,0); deltax = x2-x1; deltay = y_2 - y_1; draw_selection(gc[SELLAYER],1); } if(what & ROTATELOCAL ) { /*20171208 */ rotatelocal=1; } if(what & ROTATE) { draw_selection(gctiled,0); rot= (rot+1) & 0x3; update_symbol_bboxes(); } if(what & FLIP) { draw_selection(gctiled,0); flip = !flip; update_symbol_bboxes(); } if(what & END) /* copy selected objects */ { int save_draw; /* 20181009 */ save_draw = draw_window; draw_window=1; /* temporarily re-enable draw to window together with pixmap */ draw_selection(gctiled,0); bbox(BEGIN, 0.0 , 0.0 , 0.0 , 0.0); /* 20181009 */ newpropcnt=0; set_modify(1); push_undo(); /* 20150327 push_undo */ prepared_hash_instances=0; /* 20171224 */ prepared_hash_wires=0; if(show_pin_net_names) find_inst_hash_clear(); /* calculate copied symbols bboxes before actually doing the move */ for(i=0;i cadhalfdotsize ? bus_width : CADHALFDOTSIZE; if(wire[n].y1 < wire[n].y2) { y1 = wire[n].y1-ov; y2 = wire[n].y2+ov; } else { y1 = wire[n].y1+ov; y2 = wire[n].y2-ov; } bbox(ADD, wire[n].x1-ov, y1 , wire[n].x2+ov , y2 ); } else { int ov, y1, y2; ov = cadhalfdotsize; if(wire[n].y1 < wire[n].y2) { y1 = wire[n].y1-ov; y2 = wire[n].y2+ov; } else { y1 = wire[n].y1+ov; y2 = wire[n].y2-ov; } bbox(ADD, wire[n].x1-ov, y1 , wire[n].x2+ov , y2 ); } if(rotatelocal) { ROTATION(wire[n].x1, wire[n].y1, wire[n].x1, wire[n].y1, rx1,ry1); ROTATION(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, rx2,ry2); } else { ROTATION(x1, y_1, wire[n].x1, wire[n].y1, rx1,ry1); ROTATION(x1, y_1, wire[n].x2, wire[n].y2, rx2,ry2); } if( wire[n].sel & (SELECTED|SELECTED1) ) { rx1+=deltax; ry1+=deltay; } if( wire[n].sel & (SELECTED|SELECTED2) ) { rx2+=deltax; ry2+=deltay; } tmpx=rx1; /* used as temporary storage */ tmpy=ry1; ORDER(rx1,ry1,rx2,ry2); if( tmpx == rx2 && tmpy == ry2) { if(wire[n].sel == SELECTED1) wire[n].sel = SELECTED2; else if(wire[n].sel == SELECTED2) wire[n].sel = SELECTED1; } selectedgroup[i].n=lastwire; storeobject(-1, rx1,ry1,rx2,ry2,WIRE,0,wire[n].sel,wire[n].prop_ptr); wire[n].sel=0; if(wire[n].bus) /* 20171201 */ drawline(WIRELAYER, THICK, rx1,ry1,rx2,ry2, 0); else drawline(WIRELAYER, ADD, rx1,ry1,rx2,ry2, 0); } drawline(WIRELAYER, END, 0.0, 0.0, 0.0, 0.0, 0); } for(k=0;k bx2) bx2 = polygon[c][n].x[j]; if(j==0 || polygon[c][n].y[j] > by2) by2 = polygon[c][n].y[j]; if( polygon[c][n].sel==SELECTED || polygon[c][n].selected_point[j]) { if(rotatelocal) { ROTATION(polygon[c][n].x[0], polygon[c][n].y[0], polygon[c][n].x[j], polygon[c][n].y[j], rx1,ry1); } else { ROTATION(x1, y_1, polygon[c][n].x[j], polygon[c][n].y[j], rx1,ry1); } x[j] = rx1+deltax; y[j] = ry1+deltay; } else { x[j] = polygon[c][n].x[j]; y[j] = polygon[c][n].y[j]; } bbox(ADD, bx1, by1, bx2, by2); /* 20181009 */ } drawpolygon(k, NOW, x, y, polygon[c][n].points, polygon[c][n].fill, polygon[c][n].dash); /* 20180914 added fill */ selectedgroup[i].n=lastpolygon[c]; store_polygon(-1, x, y, polygon[c][n].points, c, polygon[c][n].sel, polygon[c][n].prop_ptr); polygon[c][n].sel=0; my_free(819, &x); my_free(820, &y); } break; case ARC: if(c!=k) break; arc_bbox(arc[c][n].x, arc[c][n].y, arc[c][n].r, arc[c][n].a, arc[c][n].b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2); bbox(ADD, tmp.x1, tmp.y1, tmp.x2, tmp.y2); if(rotatelocal) { /* rotate center wrt itself: do nothing */ rx1 = arc[c][n].x; ry1 = arc[c][n].y; } else { ROTATION(x1, y_1, arc[c][n].x, arc[c][n].y, rx1,ry1); } angle = arc[c][n].a; if(flip) { angle = 270.*rot+180.-arc[c][n].b-arc[c][n].a; } else { angle = arc[c][n].a+rot*270.; } angle = fmod(angle, 360.); if(angle<0.) angle+=360.; arc[c][n].sel=0; drawarc(k, ADD, rx1+deltax, ry1+deltay, arc[c][n].r, angle, arc[c][n].b, arc[c][n].fill, arc[c][n].dash); selectedgroup[i].n=lastarc[c]; store_arc(-1, rx1+deltax, ry1+deltay, arc[c][n].r, angle, arc[c][n].b, c, SELECTED, arc[c][n].prop_ptr); break; case xRECT: if(c!=k) break; bbox(ADD, rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2); /* 20181009 */ if(rotatelocal) { ROTATION(rect[c][n].x1, rect[c][n].y1, rect[c][n].x1, rect[c][n].y1, rx1,ry1); ROTATION(rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2, rx2,ry2); } else { ROTATION(x1, y_1, rect[c][n].x1, rect[c][n].y1, rx1,ry1); ROTATION(x1, y_1, rect[c][n].x2, rect[c][n].y2, rx2,ry2); } RECTORDER(rx1,ry1,rx2,ry2); rect[c][n].sel=0; drawrect(k, ADD, rx1+deltax, ry1+deltay, rx2+deltax, ry2+deltay, rect[c][n].dash); filledrect(k, ADD, rx1+deltax, ry1+deltay, rx2+deltax, ry2+deltay); selectedgroup[i].n=lastrect[c]; storeobject(-1, rx1+deltax, ry1+deltay, rx2+deltax, ry2+deltay,xRECT, c, SELECTED, rect[c][n].prop_ptr); break; case xTEXT: if(k!=TEXTLAYER) break; check_text_storage(); /* 20181009 */ #ifdef HAS_CAIRO customfont = set_text_custom_font(&textelement[n]); #endif text_bbox(textelement[n].txt_ptr, textelement[n].xscale, textelement[n].yscale, textelement[n].rot,textelement[n].flip, textelement[n].hcenter, textelement[n].vcenter, textelement[n].x0, textelement[n].y0, &rx1,&ry1, &rx2,&ry2); #ifdef HAS_CAIRO if(customfont) cairo_restore(ctx); #endif bbox(ADD, rx1, ry1, rx2, ry2 ); if(rotatelocal) { ROTATION(textelement[n].x0, textelement[n].y0, textelement[n].x0, textelement[n].y0, rx1,ry1); } else { ROTATION(x1, y_1, textelement[n].x0, textelement[n].y0, rx1,ry1); } textelement[lasttext].txt_ptr=NULL; my_strdup(229, &textelement[lasttext].txt_ptr,textelement[n].txt_ptr); textelement[n].sel=0; dbg(2, "copy_objects(): current str=%s\n", textelement[lasttext].txt_ptr); textelement[lasttext].x0=rx1+deltax; textelement[lasttext].y0=ry1+deltay; textelement[lasttext].rot=(textelement[n].rot + ( (flip && (textelement[n].rot & 1) ) ? rot+2 : rot) ) & 0x3; textelement[lasttext].flip=flip^textelement[n].flip; textelement[lasttext].sel=SELECTED; textelement[lasttext].prop_ptr=NULL; textelement[lasttext].font=NULL; my_strdup(230, &textelement[lasttext].prop_ptr, textelement[n].prop_ptr); my_strdup(231, &textelement[lasttext].font, get_tok_value(textelement[lasttext].prop_ptr, "font", 0));/*20171206 */ str = get_tok_value(textelement[lasttext].prop_ptr, "hcenter", 0); textelement[lasttext].hcenter = strcmp(str, "true") ? 0 : 1; str = get_tok_value(textelement[lasttext].prop_ptr, "vcenter", 0); textelement[lasttext].vcenter = strcmp(str, "true") ? 0 : 1; str = get_tok_value(textelement[lasttext].prop_ptr, "layer", 0); /*20171206 */ if(str[0]) textelement[lasttext].layer = atoi(str); else textelement[lasttext].layer = -1; textelement[lasttext].flags = 0; str = get_tok_value(textelement[lasttext].prop_ptr, "slant", 0); textelement[lasttext].flags |= strcmp(str, "oblique") ? 0 : TEXT_OBLIQUE; textelement[lasttext].flags |= strcmp(str, "italic") ? 0 : TEXT_ITALIC; str = get_tok_value(textelement[lasttext].prop_ptr, "weight", 0); textelement[lasttext].flags |= strcmp(str, "bold") ? 0 : TEXT_BOLD; textelement[lasttext].xscale=textelement[n].xscale; textelement[lasttext].yscale=textelement[n].yscale; textlayer = textelement[lasttext].layer; /* 20171206 */ if(textlayer < 0 || textlayer >= cadlayers) textlayer = TEXTLAYER; #ifdef HAS_CAIRO textfont = textelement[lasttext].font; /* 20171206 */ if((textfont && textfont[0]) || textelement[lasttext].flags) { cairo_font_slant_t slant; cairo_font_weight_t weight; textfont = (textelement[lasttext].font && textelement[lasttext].font[0]) ? textelement[lasttext].font : cairo_font_name; weight = ( textelement[lasttext].flags & TEXT_BOLD) ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL; slant = CAIRO_FONT_SLANT_NORMAL; if(textelement[lasttext].flags & TEXT_ITALIC) slant = CAIRO_FONT_SLANT_ITALIC; if(textelement[lasttext].flags & TEXT_OBLIQUE) slant = CAIRO_FONT_SLANT_OBLIQUE; cairo_save(ctx); cairo_save(save_ctx); cairo_select_font_face (ctx, textfont, slant, weight); cairo_select_font_face (save_ctx, textfont, slant, weight); } #endif draw_string(textlayer, ADD, textelement[lasttext].txt_ptr, /* draw moved txt */ textelement[lasttext].rot, textelement[lasttext].flip, textelement[lasttext].hcenter, textelement[lasttext].vcenter, rx1+deltax,ry1+deltay, textelement[lasttext].xscale, textelement[lasttext].yscale); #ifndef HAS_CAIRO drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); #endif #ifdef HAS_CAIRO if( (textfont && textfont[0]) || textelement[lasttext].flags) { cairo_restore(ctx); cairo_restore(save_ctx); } #endif selectedgroup[i].n=lasttext; lasttext++; dbg(2, "copy_objects(): done copy string\n"); break; case ELEMENT: if(k==0) { check_inst_storage(); if(rotatelocal) { ROTATION(inst_ptr[n].x0, inst_ptr[n].y0, inst_ptr[n].x0, inst_ptr[n].y0, rx1,ry1); } else { ROTATION(x1, y_1, inst_ptr[n].x0, inst_ptr[n].y0, rx1,ry1); } inst_ptr[lastinst] = inst_ptr[n]; inst_ptr[lastinst].prop_ptr=NULL; inst_ptr[lastinst].instname=NULL; /* 20150409 */ inst_ptr[lastinst].node=NULL; inst_ptr[lastinst].name=NULL; my_strdup(232, &inst_ptr[lastinst].name, inst_ptr[n].name); my_strdup(233, &inst_ptr[lastinst].prop_ptr, inst_ptr[n].prop_ptr); my_strdup2(234, &inst_ptr[lastinst].instname, get_tok_value(inst_ptr[n].prop_ptr, "name",0)); /* 20150409 */ inst_ptr[n].sel=0; inst_ptr[lastinst].flags = inst_ptr[n].flags; inst_ptr[lastinst].flags &= ~4; /* do not propagate hilight */ inst_ptr[lastinst].x0 = rx1+deltax; inst_ptr[lastinst].y0 = ry1+deltay; inst_ptr[lastinst].sel = SELECTED; inst_ptr[lastinst].rot = (inst_ptr[lastinst].rot + ( (flip && (inst_ptr[lastinst].rot & 1) ) ? rot+2 : rot) ) & 0x3; inst_ptr[lastinst].flip = (flip? !inst_ptr[n].flip:inst_ptr[n].flip); /* the newpropcnt argument is zero for the 1st call and used in */ /* new_prop_string() for cleaning some internal caches. */ if(!newpropcnt) hash_all_names(lastinst); new_prop_string(lastinst, inst_ptr[n].prop_ptr,newpropcnt++, disable_unique_names); my_strdup2(235, &inst_ptr[lastinst].instname, get_tok_value(inst_ptr[lastinst].prop_ptr, "name", 0)); /* 20150409 */ n=selectedgroup[i].n=lastinst; lastinst++; /* must be updated before calling symbol_bbox which triggers prepare_netlist_structs(0) */ } break; } /* end switch(selectedgroup[i].type) */ } /* end for(i=0;itranslate * to translate @#n:net_name texts */ need_rebuild_selected_array=1; rebuild_selected_array(); prepared_hash_wires=0; 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(k == 0) { if(selectedgroup[i].type == ELEMENT) { int p; symbol_bbox(n, &inst_ptr[n].x1, &inst_ptr[n].y1, &inst_ptr[n].x2, &inst_ptr[n].y2 ); /* 20171201 */ bbox(ADD, inst_ptr[n].x1, inst_ptr[n].y1, inst_ptr[n].x2, inst_ptr[n].y2 ); if(show_pin_net_names) for(p = 0; p < (inst_ptr[n].ptr + instdef)->rects[PINLAYER]; p++) { if( inst_ptr[n].node && inst_ptr[n].node[p]) { find_inst_to_be_redrawn(inst_ptr[n].node[p]); } } } if(show_pin_net_names && selectedgroup[i].type == WIRE) { find_inst_to_be_redrawn(wire[n].node); } } /* draw_symbol(ADD,k, n,k, 0, 0, 0.0, 0.0); */ } filledrect(k, END, 0.0, 0.0, 0.0, 0.0); drawarc(k, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(k, END, 0.0, 0.0, 0.0, 0.0, 0); drawline(k, END, 0.0, 0.0, 0.0, 0.0, 0); } /* end for(k=0;krects[PINLAYER]; p++) { if( inst_ptr[n].node && inst_ptr[n].node[p]) { find_inst_to_be_redrawn(inst_ptr[n].node[p]); } } } if(show_pin_net_names && selectedgroup[i].type == WIRE) { find_inst_to_be_redrawn(wire[n].node); } } for(k=0;k cadhalfdotsize ? bus_width : CADHALFDOTSIZE; if(wire[n].y1 < wire[n].y2) { y1 = wire[n].y1-ov; y2 = wire[n].y2+ov; } else { y1 = wire[n].y1+ov; y2 = wire[n].y2-ov; } bbox(ADD, wire[n].x1-ov, y1 , wire[n].x2+ov , y2 ); } else { int ov, y1, y2; ov = cadhalfdotsize; if(wire[n].y1 < wire[n].y2) { y1 = wire[n].y1-ov; y2 = wire[n].y2+ov; } else { y1 = wire[n].y1+ov; y2 = wire[n].y2-ov; } bbox(ADD, wire[n].x1-ov, y1 , wire[n].x2+ov , y2 ); } if(rotatelocal) { ROTATION(wire[n].x1, wire[n].y1, wire[n].x1, wire[n].y1, rx1,ry1); ROTATION(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, rx2,ry2); } else { ROTATION(x1, y_1, wire[n].x1, wire[n].y1, rx1,ry1); ROTATION(x1, y_1, wire[n].x2, wire[n].y2, rx2,ry2); } if( wire[n].sel & (SELECTED|SELECTED1) ) { rx1+=deltax; ry1+=deltay; } if( wire[n].sel & (SELECTED|SELECTED2) ) { rx2+=deltax; ry2+=deltay; } wire[n].x1=rx1; wire[n].y1=ry1; ORDER(rx1,ry1,rx2,ry2); if( wire[n].x1 == rx2 && wire[n].y1 == ry2) { if(wire[n].sel == SELECTED1) wire[n].sel = SELECTED2; else if(wire[n].sel == SELECTED2) wire[n].sel = SELECTED1; } wire[n].x1=rx1; wire[n].y1=ry1; wire[n].x2=rx2; wire[n].y2=ry2; } else if(k == WIRELAYER) { if(wire[n].bus) drawline(WIRELAYER, THICK, wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, 0); else drawline(WIRELAYER, ADD, wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, 0); } break; case LINE: if(c!=k) break; bbox(ADD, line[c][n].x1, line[c][n].y1, line[c][n].x2, line[c][n].y2); if(rotatelocal) { ROTATION(line[c][n].x1, line[c][n].y1, line[c][n].x1, line[c][n].y1, rx1,ry1); ROTATION(line[c][n].x1, line[c][n].y1, line[c][n].x2, line[c][n].y2, rx2,ry2); } else { ROTATION(x1, y_1, line[c][n].x1, line[c][n].y1, rx1,ry1); ROTATION(x1, y_1, line[c][n].x2, line[c][n].y2, rx2,ry2); } if( line[c][n].sel & (SELECTED|SELECTED1) ) { rx1+=deltax; ry1+=deltay; } if( line[c][n].sel & (SELECTED|SELECTED2) ) { rx2+=deltax; ry2+=deltay; } line[c][n].x1=rx1; line[c][n].y1=ry1; ORDER(rx1,ry1,rx2,ry2); if( line[c][n].x1 == rx2 && line[c][n].y1 == ry2) { if(line[c][n].sel == SELECTED1) line[c][n].sel = SELECTED2; else if(line[c][n].sel == SELECTED2) line[c][n].sel = SELECTED1; } line[c][n].x1=rx1; line[c][n].y1=ry1; line[c][n].x2=rx2; line[c][n].y2=ry2; if(line[c][n].bus) drawline(k, THICK, line[c][n].x1, line[c][n].y1, line[c][n].x2, line[c][n].y2, line[c][n].dash); else drawline(k, ADD, line[c][n].x1, line[c][n].y1, line[c][n].x2, line[c][n].y2, line[c][n].dash); break; case POLYGON: /* 20171115 */ if(c!=k) break; { double bx1=0., by1=0., bx2=0., by2=0.; int j; double savex0, savey0; savex0 = polygon[c][n].x[0]; savey0 = polygon[c][n].y[0]; for(j=0; j bx2) bx2 = polygon[c][n].x[j]; if(j==0 || polygon[c][n].y[j] > by2) by2 = polygon[c][n].y[j]; if( polygon[c][n].sel==SELECTED || polygon[c][n].selected_point[j]) { if(rotatelocal) { ROTATION(savex0, savey0, polygon[c][n].x[j], polygon[c][n].y[j], rx1,ry1); } else { ROTATION(x1, y_1, polygon[c][n].x[j], polygon[c][n].y[j], rx1,ry1); } polygon[c][n].x[j] = rx1+deltax; polygon[c][n].y[j] = ry1+deltay; } } bbox(ADD, bx1, by1, bx2, by2); } /* 20180914 added fill */ drawpolygon(k, NOW, polygon[c][n].x, polygon[c][n].y, polygon[c][n].points, polygon[c][n].fill, polygon[c][n].dash); break; case ARC: if(c!=k) break; if(arc[c][n].fill) arc_bbox(arc[c][n].x, arc[c][n].y, arc[c][n].r, 0, 360, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2); else arc_bbox(arc[c][n].x, arc[c][n].y, arc[c][n].r, arc[c][n].a, arc[c][n].b, &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2); dbg(1, "move_objects(): arc_bbox: %g %g %g %g\n", tmp.x1, tmp.y1, tmp.x2, tmp.y2); bbox(ADD, tmp.x1, tmp.y1, tmp.x2, tmp.y2); if(rotatelocal) { /* rotate center wrt itself: do nothing */ rx1 = arc[c][n].x; ry1 = arc[c][n].y; } else { ROTATION(x1, y_1, arc[c][n].x, arc[c][n].y, rx1,ry1); } angle = arc[c][n].a; if(flip) { angle = 270.*rot+180.-arc[c][n].b-arc[c][n].a; } else { angle = arc[c][n].a+rot*270.; } angle = fmod(angle, 360.); if(angle<0.) angle+=360.; if(arc[c][n].sel == SELECTED) { arc[c][n].x = rx1+deltax; arc[c][n].y = ry1+deltay; arc[c][n].a = angle; } else if(arc[c][n].sel == SELECTED1) { arc[c][n].x = rx1; arc[c][n].y = ry1; if(arc[c][n].r+deltax) arc[c][n].r = fabs(arc[c][n].r+deltax); arc[c][n].a = angle; } else if(arc[c][n].sel == SELECTED2) { angle = ROUND(fmod(atan2(-deltay, deltax)*180./XSCH_PI+angle, 360.)); if(angle<0.) angle +=360.; arc[c][n].x = rx1; arc[c][n].y = ry1; arc[c][n].a = angle; } else if(arc[c][n].sel==SELECTED3) { angle = ROUND(fmod(atan2(-deltay, deltax)*180./XSCH_PI+arc[c][n].b, 360.)); if(angle<0.) angle +=360.; if(angle==0) angle=360.; arc[c][n].x = rx1; arc[c][n].y = ry1; arc[c][n].b = angle; } drawarc(k, ADD, arc[c][n].x, arc[c][n].y, arc[c][n].r, arc[c][n].a, arc[c][n].b, arc[c][n].fill, arc[c][n].dash); break; case xRECT: if(c!=k) break; bbox(ADD, rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2); if(rotatelocal) { ROTATION(rect[c][n].x1, rect[c][n].y1, rect[c][n].x1, rect[c][n].y1, rx1,ry1); ROTATION(rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2, rx2,ry2); } else { ROTATION(x1, y_1, rect[c][n].x1, rect[c][n].y1, rx1,ry1); ROTATION(x1, y_1, rect[c][n].x2, rect[c][n].y2, rx2,ry2); } if( rect[c][n].sel == SELECTED) { rx1+=deltax; ry1+=deltay; rx2+=deltax; ry2+=deltay; } else if( rect[c][n].sel == SELECTED1) { /* 20070302 stretching on rectangles */ rx1+=deltax; ry1+=deltay; } else if( rect[c][n].sel == SELECTED2) { rx2+=deltax; ry1+=deltay; } else if( rect[c][n].sel == SELECTED3) { rx1+=deltax; ry2+=deltay; } else if( rect[c][n].sel == SELECTED4) { rx2+=deltax; ry2+=deltay; } else if(rect[c][n].sel==(SELECTED1|SELECTED2)) { ry1+=deltay; } else if(rect[c][n].sel==(SELECTED3|SELECTED4)) { ry2+=deltay; } else if(rect[c][n].sel==(SELECTED1|SELECTED3)) { rx1+=deltax; } else if(rect[c][n].sel==(SELECTED2|SELECTED4)) { rx2+=deltax; } tx1 = rx1; ty1 = ry1; RECTORDER(rx1,ry1,rx2,ry2); if( rx2 == tx1) { /*20070302 */ if(rect[c][n].sel==SELECTED1) rect[c][n].sel = SELECTED2; else if(rect[c][n].sel==SELECTED2) rect[c][n].sel = SELECTED1; else if(rect[c][n].sel==SELECTED3) rect[c][n].sel = SELECTED4; else if(rect[c][n].sel==SELECTED4) rect[c][n].sel = SELECTED3; } if( ry2 == ty1) { if(rect[c][n].sel==SELECTED1) rect[c][n].sel = SELECTED3; else if(rect[c][n].sel==SELECTED3) rect[c][n].sel = SELECTED1; else if(rect[c][n].sel==SELECTED2) rect[c][n].sel = SELECTED4; else if(rect[c][n].sel==SELECTED4) rect[c][n].sel = SELECTED2; } rect[c][n].x1 = rx1; rect[c][n].y1 = ry1; rect[c][n].x2 = rx2; rect[c][n].y2 = ry2; drawrect(k, ADD, rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2, rect[c][n].dash); filledrect(c, ADD, rect[c][n].x1, rect[c][n].y1, rect[c][n].x2, rect[c][n].y2); break; case xTEXT: if(k!=TEXTLAYER) break; #ifdef HAS_CAIRO customfont = set_text_custom_font(&textelement[n]); #endif text_bbox(textelement[n].txt_ptr, textelement[n].xscale, textelement[n].yscale, textelement[n].rot,textelement[n].flip, textelement[n].hcenter, textelement[n].vcenter, textelement[n].x0, textelement[n].y0, &rx1,&ry1, &rx2,&ry2); #ifdef HAS_CAIRO if(customfont) cairo_restore(ctx); #endif bbox(ADD, rx1, ry1, rx2, ry2 ); if(rotatelocal) { ROTATION(textelement[n].x0, textelement[n].y0, textelement[n].x0, textelement[n].y0, rx1,ry1); } else { ROTATION(x1, y_1, textelement[n].x0, textelement[n].y0, rx1,ry1); } textelement[n].x0=rx1+deltax; textelement[n].y0=ry1+deltay; textelement[n].rot=(textelement[n].rot + ( (flip && (textelement[n].rot & 1) ) ? rot+2 : rot) ) & 0x3; textelement[n].flip=flip^textelement[n].flip; textlayer = textelement[n].layer; /* 20171206 */ if(textlayer < 0 || textlayer >= cadlayers) textlayer = TEXTLAYER; #ifdef HAS_CAIRO textfont = textelement[n].font; /* 20171206 */ if((textfont && textfont[0]) || textelement[n].flags) { cairo_font_slant_t slant; cairo_font_weight_t weight; textfont = (textelement[n].font && textelement[n].font[0]) ? textelement[n].font : cairo_font_name; weight = ( textelement[n].flags & TEXT_BOLD) ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL; slant = CAIRO_FONT_SLANT_NORMAL; if(textelement[n].flags & TEXT_ITALIC) slant = CAIRO_FONT_SLANT_ITALIC; if(textelement[n].flags & TEXT_OBLIQUE) slant = CAIRO_FONT_SLANT_OBLIQUE; cairo_save(ctx); cairo_save(save_ctx); cairo_select_font_face (ctx, textfont, slant, weight); cairo_select_font_face (save_ctx, textfont, slant, weight); } #endif draw_string(textlayer, ADD, textelement[n].txt_ptr, /* draw moved txt */ textelement[n].rot, textelement[n].flip, textelement[n].hcenter, textelement[n].vcenter, textelement[n].x0, textelement[n].y0, textelement[n].xscale, textelement[n].yscale); #ifndef HAS_CAIRO drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); #endif #ifdef HAS_CAIRO if( (textfont && textfont[0]) || textelement[n].flags) { cairo_restore(ctx); cairo_restore(save_ctx); } #endif break; case ELEMENT: if(k==0) { if(rotatelocal) { ROTATION(inst_ptr[n].x0, inst_ptr[n].y0, inst_ptr[n].x0, inst_ptr[n].y0, rx1,ry1); } else { ROTATION(x1, y_1, inst_ptr[n].x0, inst_ptr[n].y0, rx1,ry1); } inst_ptr[n].x0 = rx1+deltax; inst_ptr[n].y0 = ry1+deltay; inst_ptr[n].rot = (inst_ptr[n].rot + ( (flip && (inst_ptr[n].rot & 1) ) ? rot+2 : rot) ) & 0x3; inst_ptr[n].flip = flip ^ inst_ptr[n].flip; } break; } /* end switch(selectedgroup[i].type) */ } /* end for(i=0;itranslate * to translate @#n:net_name texts */ prepared_netlist_structs=0; prepared_hilight_structs=0; prepared_hash_wires=0; if(show_pin_net_names) { prepare_netlist_structs(0); } } for(i = 0; i < lastselected; i++) { n = selectedgroup[i].n; if(k == 0) { if(selectedgroup[i].type == ELEMENT) { int p; symbol_bbox(n, &inst_ptr[n].x1, &inst_ptr[n].y1, &inst_ptr[n].x2, &inst_ptr[n].y2 ); /* 20171201 */ bbox(ADD, inst_ptr[n].x1, inst_ptr[n].y1, inst_ptr[n].x2, inst_ptr[n].y2 ); if(show_pin_net_names) for(p = 0; p < (inst_ptr[n].ptr + instdef)->rects[PINLAYER]; p++) { if( inst_ptr[n].node && inst_ptr[n].node[p]) { find_inst_to_be_redrawn(inst_ptr[n].node[p]); } } } if(show_pin_net_names && selectedgroup[i].type == WIRE) { find_inst_to_be_redrawn(wire[n].node); } } /* draw_symbol(ADD,k, n,k, 0, 0, 0.0, 0.0); */ } filledrect(k, END, 0.0, 0.0, 0.0, 0.0); drawarc(k, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(k, END, 0.0, 0.0, 0.0, 0.0, 0); drawline(k, END, 0.0, 0.0, 0.0, 0.0, 0); } /*end for(k=0;k