diff --git a/src/actions.c b/src/actions.c index 60ee1174..b80f9f9a 100644 --- a/src/actions.c +++ b/src/actions.c @@ -3879,7 +3879,7 @@ void fix_restore_rect(double x1, double y1, double x2, double y2) /* 20150927 select=1: select objects, select=0: unselect objects */ -void select_rect(int what, int select) +void select_rect(int stretch, int what, int select) { int incremental_select = tclgetboolvar("incremental_select"); int sel_touch = tclgetboolvar("select_touch"); @@ -3901,7 +3901,7 @@ void select_rect(int what, int select) draw_selection(xctx->gc[SELLAYER], 0); if(!xctx->nl_sel || (incremental_select && xctx->nl_dir == 0)) - select_inside(xctx->nl_xx1, xctx->nl_yy1, xctx->nl_xx2, xctx->nl_yy2, xctx->nl_sel); + select_inside(stretch, xctx->nl_xx1, xctx->nl_yy1, xctx->nl_xx2, xctx->nl_yy2, xctx->nl_sel); else if(incremental_select && xctx->nl_dir == 1 && sel_touch) select_touch(xctx->nl_xx1, xctx->nl_yy1, xctx->nl_xx2, xctx->nl_yy2, xctx->nl_sel); xctx->nl_xx1=xctx->nl_xr;xctx->nl_xx2=xctx->nl_xr2;xctx->nl_yy1=xctx->nl_yr;xctx->nl_yy2=xctx->nl_yr2; @@ -3935,7 +3935,7 @@ void select_rect(int what, int select) drawtemprect(xctx->gctiled, NOW, xctx->nl_xr,xctx->nl_yr,xctx->nl_xr2,xctx->nl_yr2); if(!sel_touch || xctx->nl_dir == 0) - select_inside(xctx->nl_xr,xctx->nl_yr,xctx->nl_xr2,xctx->nl_yr2, xctx->nl_sel); + select_inside(stretch, xctx->nl_xr,xctx->nl_yr,xctx->nl_xr2,xctx->nl_yr2, xctx->nl_sel); else select_touch(xctx->nl_xr,xctx->nl_yr,xctx->nl_xr2,xctx->nl_yr2, xctx->nl_sel); diff --git a/src/callback.c b/src/callback.c index 2601ab0b..1f9d4d4a 100644 --- a/src/callback.c +++ b/src/callback.c @@ -74,7 +74,7 @@ static int waves_selected(int event, KeySym key, int state, int button) if(! (xctx->ui_state & GRAPHPAN) ) { xctx->graph_master = i; } - if(draw_xhair) draw_crosshair(1); + if(draw_xhair) draw_crosshair(1); /* remove crosshair, re-enable mouse cursor */ tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL); break; } @@ -1372,28 +1372,28 @@ void draw_crosshair(int what) if(fix_broken_tiled_fill || !_unix) { if(xhair_size) { MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - 4 * INT_WIDTH(xctx->lw) + 4 * xhair_size, - 4 * INT_WIDTH(xctx->lw) + 4 * xhair_size, - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw) - xhair_size); + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + 2 * INT_WIDTH(xctx->lw) + 2 * xhair_size, + 2 * INT_WIDTH(xctx->lw) + 2 * xhair_size, + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw) - xhair_size); MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - 4 * INT_WIDTH(xctx->lw) + 4 * xhair_size, - 4 * INT_WIDTH(xctx->lw) + 4 * xhair_size, - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw) - xhair_size, - (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw) - xhair_size); + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + 2 * INT_WIDTH(xctx->lw) + 2 * xhair_size, + 2 * INT_WIDTH(xctx->lw) + 2 * xhair_size, + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw) - xhair_size, + (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw) - xhair_size); } else { /* full screen span xhair */ MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], - 0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw), - xctx->xrect[0].width, 4 * INT_WIDTH(xctx->lw), - 0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw)); + 0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw), + xctx->xrect[0].width, 2 * INT_WIDTH(xctx->lw), + 0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 1 * INT_WIDTH(xctx->lw)); MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw), 0, - 4 * INT_WIDTH(xctx->lw), xctx->xrect[0].height, - (int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw), 0); + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw), 0, + 2 * INT_WIDTH(xctx->lw), xctx->xrect[0].height, + (int)X_TO_SCREEN(xctx->prev_crossx) - 1 * INT_WIDTH(xctx->lw), 0); } } else { @@ -1758,8 +1758,7 @@ static int check_menu_start_commands(double c_snap) return 0; } - -static int add_wire_from_inst_pin(Selected *sel, double mx, double my) +static int add_wire_from_inst(Selected *sel, double mx, double my) { int res = 0; int prev_state = xctx->ui_state; @@ -1785,7 +1784,16 @@ static int add_wire_from_inst_pin(Selected *sel, double mx, double my) } res = 1; } - } else if(type == WIRE) { + } + return res; +} + +static int add_wire_from_wire(Selected *sel, double mx, double my) +{ + int res = 0; + int prev_state = xctx->ui_state; + int type = sel->type; + if(type == WIRE) { int n = sel->n; double x1 = xctx->wire[n].x1; double y1 = xctx->wire[n].y1; @@ -1804,7 +1812,6 @@ static int add_wire_from_inst_pin(Selected *sel, double mx, double my) return res; } - /* sets xctx->shape_point_selected */ static int edit_line_point(int state) { @@ -1842,7 +1849,7 @@ static int edit_line_point(int state) static int edit_wire_point(int state) { int wire_n = -1; - dbg(1, "1 Wire selected\n"); + dbg(1, "edit_wire_point\n"); wire_n = xctx->sel_array[0].n; /* wire point: Check is user is clicking a control point of a wire */ if(wire_n >= 0) { @@ -2366,7 +2373,9 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key, #else XKeyboardState kbdstate; #endif +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 snap_cursor = tclgetboolvar("snap_cursor"); int wire_draw_active = (xctx->ui_state & STARTWIRE) || @@ -2498,7 +2507,7 @@ int rstate; /* (reduced state, without ShiftMask) */ dbg(2, "callback(): Enter event, ui_state=%d\n", xctx->ui_state); xctx->mouse_inside = 1; if(draw_xhair) { - if(tclgetintvar("crosshair_size") == 0) { + if(crosshair_size == 0) { tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL); } } else @@ -2558,18 +2567,22 @@ int rstate; /* (reduced state, without ShiftMask) */ break; } if(draw_xhair) { - draw_crosshair(1); + draw_crosshair(1); /* when moving mouse: first action is delete crosshair, will be drawn later */ } + /* pan schematic */ if(snap_cursor && wire_draw_active) draw_snap_cursor(1); if(xctx->ui_state & STARTPAN) pan(RUBBER, mx, my); + if(xctx->semaphore >= 2) { if(draw_xhair) { - draw_crosshair(2); + draw_crosshair(2); /* locked UI: draw new crosshair and break out */ } if(snap_cursor && wire_draw_active) draw_snap_cursor(2); break; } dbg(1, "ui_state=%d deltax=%g\n", xctx->ui_state, xctx->deltax); + + /* update status bar messages */ if(xctx->ui_state) { if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) { my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d w=%.6g h=%.6g", @@ -2580,6 +2593,8 @@ int rstate; /* (reduced state, without ShiftMask) */ statusmsg(str,1); } } + + /* update zoom rectangle drag */ if(xctx->ui_state & STARTZOOM) zoom_rectangle(RUBBER); /* determine direction of a rectangle selection (or unselection with ALT key) */ @@ -2588,26 +2603,32 @@ int rstate; /* (reduced state, without ShiftMask) */ if( (state & Button1Mask) && SET_MODMASK) { if(mx >= xctx->mx_save) xctx->nl_dir = 0; else xctx->nl_dir = 1; - select_rect(RUBBER,0); + select_rect(enable_stretch, RUBBER,0); /* select by area : determine direction */ } else if(state & Button1Mask) { if(mx >= xctx->mx_save) xctx->nl_dir = 0; else xctx->nl_dir = 1; - select_rect(RUBBER,1); + select_rect(enable_stretch, RUBBER,1); } } + /* draw objects being moved */ if(xctx->ui_state & STARTMOVE) { if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; move_objects(RUBBER,0,0,0); } + + /* draw objects being copied */ if(xctx->ui_state & STARTCOPY) { if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; copy_objects(RUBBER); } + + /* draw moving objects being inserted, wires, arcs, lines, rectangles, polygons */ redraw_w_a_l_r_p_rubbers(); + /* start of a mouse area select. Button1 pressed. No shift pressed * Do not start an area select if user is dragging a polygon/bezier point */ if(!(xctx->ui_state & STARTPOLYGON) && (state&Button1Mask) && !(xctx->ui_state & STARTWIRE) && @@ -2618,7 +2639,7 @@ int rstate; /* (reduced state, without ShiftMask) */ xctx->mouse_moved = 1; if(!xctx->drag_elements) { if( !(xctx->ui_state & STARTSELECT)) { - select_rect(START,1); + select_rect(enable_stretch, START,1); xctx->onetime=1; } if(abs(mx-xctx->mx_save) > 8 || @@ -2637,7 +2658,7 @@ int rstate; /* (reduced state, without ShiftMask) */ !(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) { /* unselect area */ if( !(xctx->ui_state & STARTSELECT)) { - select_rect(START,0); + select_rect(enable_stretch, START,0); } } /* Select by area. Shift pressed */ @@ -2646,7 +2667,7 @@ int rstate; /* (reduced state, without ShiftMask) */ !xctx->drag_elements && !(xctx->ui_state & STARTPAN) ) { if(mx != xctx->mx_save || my != xctx->my_save) { if( !(xctx->ui_state & STARTSELECT)) { - select_rect(START,1); + select_rect(enable_stretch, START,1); } if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ @@ -3287,16 +3308,8 @@ int rstate; /* (reduced state, without ShiftMask) */ } if(key=='y' && rstate == 0) /* toggle stretching */ { - int en_s; - en_s = tclgetboolvar("enable_stretch"); - en_s = !en_s; - - if(en_s) { - tclsetvar("enable_stretch","1"); - } - else { - tclsetvar("enable_stretch","0"); - } + enable_stretch = !enable_stretch; + tclsetboolvar("enable_stretch", enable_stretch); break; } if(key=='x' && EQUAL_MODMASK) /* toggle draw crosshair at mouse pos */ @@ -3820,8 +3833,7 @@ int rstate; /* (reduced state, without ShiftMask) */ waves_callback(event, mx, my, key, button, aux, state); break; } - if(tclgetboolvar("enable_stretch")) - select_attached_nets(); /* stretch nets that land on selected instance pins */ + if(enable_stretch) select_attached_nets(); /* stretch nets that land on selected instance pins */ if(infix_interface) { xctx->mx_double_save=xctx->mousex_snap; xctx->my_double_save=xctx->mousey_snap; @@ -3856,8 +3868,7 @@ int rstate; /* (reduced state, without ShiftMask) */ waves_callback(event, mx, my, key, button, aux, state); break; } - if(!tclgetboolvar("enable_stretch")) - select_attached_nets(); /* stretch nets that land on selected instance pins */ + if(!enable_stretch) select_attached_nets(); /* stretch nets that land on selected instance pins */ if(infix_interface) { xctx->mx_double_save=xctx->mousex_snap; xctx->my_double_save=xctx->mousey_snap; @@ -3873,8 +3884,7 @@ int rstate; /* (reduced state, without ShiftMask) */ if(key=='M' && state == (ControlMask | ShiftMask) && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) { - if(!tclgetboolvar("enable_stretch")) - select_attached_nets(); /* stretch nets that land on selected instance pins */ + if(!enable_stretch) select_attached_nets(); /* stretch nets that land on selected instance pins */ xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */ if(infix_interface) { xctx->mx_double_save=xctx->mousex_snap; @@ -4179,31 +4189,37 @@ int rstate; /* (reduced state, without ShiftMask) */ } break; - case ButtonPress: /* end operation */ + case ButtonPress: dbg(1, "callback(): ButtonPress ui_state=%d state=%d\n",xctx->ui_state,state); if(waves_selected(event, key, state, button)) { waves_callback(event, mx, my, key, button, aux, state); break; } + /* terminate a schematic pan action */ if(xctx->ui_state & STARTPAN) { xctx->ui_state &=~STARTPAN; break; } + /* select instance and connected nets stopping at wire junctions */ if(button == Button3 && state == ControlMask && xctx->semaphore <2) { Selected sel; sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); if(sel.type) select_connected_nets(1); } + + /* break wire at mouse coordinates, move break point to nearest grid point */ else if(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) { 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) { Selected sel; @@ -4216,6 +4232,8 @@ int rstate; /* (reduced state, without ShiftMask) */ * 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) { zoom_rectangle(START);break; } @@ -4236,10 +4254,13 @@ int rstate; /* (reduced state, without ShiftMask) */ select_object(xctx->mousex, xctx->mousey, 0, 0, NULL); rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ } + + /* Middle button press (Button2) will pan the schematic. */ else if(button==Button2 && (state == 0)) { pan(START, mx, my); xctx->ui_state |= STARTPAN; } + /* button1 click to select another instance while edit prop dialog open */ else if(button==Button1 && xctx->semaphore >= 2) { if(tcleval("winfo exists .dialog.textinput")[0] == '1') { /* proc text_line */ @@ -4256,11 +4277,15 @@ int rstate; /* (reduced state, without ShiftMask) */ rebuild_selected_array(); } } + + /* Handle the remaining Button1Press events */ else if(button==Button1) /* MOD button is not pressed here. Processed above */ { xctx->onetime = 0; xctx->mouse_moved = 0; xctx->drag_elements = 0; + + /* start another wire or line in persistent mode */ 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){ @@ -4279,7 +4304,8 @@ int rstate; /* (reduced state, without ShiftMask) */ } /* handle all object insertions started from Tools/Edit menu */ if(check_menu_start_commands(c_snap)) break; - /* complete the STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */ + + /* complete the pending STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */ if(end_place_move_copy_zoom()) break; /* Button1Press to select objects */ @@ -4294,16 +4320,31 @@ int rstate; /* (reduced state, without ShiftMask) */ xctx->mx_double_save=xctx->mousex; xctx->my_double_save=xctx->mousey; - /* Clicking on an instance pin -> drag a new wire - * if an instance is already selected */ + #if 0 /* disabled */ + /* Clicking and dragging from a **selected** instance pin will start a new wire + * if no other elements are selected */ if(xctx->lastsel == 1 && xctx->sel_array[0].type==ELEMENT) { - if(add_wire_from_inst_pin(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) break; + if(add_wire_from_wire(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) break; + if(add_wire_from_inst(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) break; } + #endif + /* In *NON* intuitive interface a button1 press with no modifiers will + * first unselect everything... + * For intuitive interface unselection see below... */ if(!xctx->intuitive_interface && no_shift_no_ctrl ) unselect_all(1); if(draw_xhair) sel = find_closest_obj(xctx->mousex_snap, xctx->mousey_snap, 0); else sel = find_closest_obj(xctx->mousex, xctx->mousey, 0); + /* 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 && crosshair_size == 0) { + sel = find_closest_obj(xctx->mousex_snap, xctx->mousey_snap, 0); + } else { + sel = find_closest_obj(xctx->mousex, xctx->mousey, 0); + } + dbg(1, "sel.type=%d\n", sel.type); + /* determine if closest object was already selected when button1 was pressed */ switch(sel.type) { case WIRE: if(xctx->wire[sel.n].sel) already_selected = 1; break; case xTEXT: if(xctx->text[sel.n].sel) already_selected = 1; break; @@ -4315,42 +4356,65 @@ int rstate; /* (reduced state, without ShiftMask) */ default: break; } /*end switch */ - /* Clicking on an instance pin -> drag a new wire */ + /* Clicking and drag on an instance pin -> drag a new wire */ if(xctx->intuitive_interface && !already_selected) { - if(add_wire_from_inst_pin(&sel, xctx->mousex_snap, xctx->mousey_snap)) break; + if(add_wire_from_inst(&sel, xctx->mousex_snap, xctx->mousey_snap)) break; + } + + /* Clicking and drag on a wire end -> drag a new wire */ + if(xctx->intuitive_interface && !already_selected) { + if(add_wire_from_wire(&sel, xctx->mousex_snap, xctx->mousey_snap)) break; } + /* In intuitive interface a button1 press with no modifiers will + * unselect everything... we do it here */ if(xctx->intuitive_interface && !already_selected && no_shift_no_ctrl ) unselect_all(1); + /* select the object under the mouse and rebuild the selected array */ if(!already_selected) select_object(xctx->mousex, xctx->mousey, SELECTED, 0, &sel); rebuild_selected_array(); + dbg(1, "Button1Press to select objects, lastsel = %d\n", xctx->lastsel); - if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) - if(edit_polygon_point(state)) break; /* sets xctx->shape_point_selected */ + /* if clicking on some object endpoints or vertices set shape_point_selected + * this information will be used in Motion events to draw the stretched vertices */ + if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) { + if(edit_polygon_point(state)) break; /* sets xctx->shape_point_selected */ + } + if(xctx->lastsel == 1 && xctx->intuitive_interface) { + int cond = already_selected; - if(xctx->lastsel == 1 && xctx->sel_array[0].type==xRECT) - if(edit_rect_point(state)) break; /* sets xctx->shape_point_selected */ + if(cond && xctx->sel_array[0].type==xRECT) { + if(edit_rect_point(state)) break; /* sets xctx->shape_point_selected */ + } - if(xctx->lastsel == 1 && xctx->sel_array[0].type==LINE) - if(edit_line_point(state)) break; /* sets xctx->shape_point_selected */ + if(cond && xctx->sel_array[0].type==LINE) { + if(edit_line_point(state)) break; /* sets xctx->shape_point_selected */ + } - if(xctx->lastsel == 1 && xctx->sel_array[0].type==WIRE) + if(cond && xctx->sel_array[0].type==WIRE) { if(edit_wire_point(state)) break; /* sets xctx->shape_point_selected */ + } + } + dbg(1, "shape_point_selected=%d, lastsel=%d\n", xctx->shape_point_selected, xctx->lastsel); /* intuitive interface: directly drag elements */ if(sel.type && xctx->intuitive_interface && xctx->lastsel >= 1 && !xctx->shape_point_selected) { - /* xctx->push_undo(); */ + int stretch = (state & ControlMask ? 1 : 0) ^ enable_stretch; xctx->drag_elements = 1; - - if( (state & ControlMask) && !(state & ShiftMask) && !tclgetboolvar("enable_stretch")) { + /* select attached nets depending on ControlMask and enable_stretch */ + if(stretch && !(state & ShiftMask)) { select_attached_nets(); /* stretch nets that land on selected instance pins */ } + + /* if dragging instances with Ctrl and Shift down add wires to pins attached to something */ if(state == (ShiftMask | ControlMask) ) { xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */ move_objects(START,0,0,0); } + /* dragging away an object with Shift pressed is a copy (duplicate object) */ else if(state == ShiftMask) copy_objects(START); + /* else it is a move */ else move_objects(START,0,0,0); } @@ -4375,7 +4439,8 @@ int rstate; /* (reduced state, without ShiftMask) */ waves_callback(event, mx, my, key, button, aux, state); break; } - + dbg(1, "release: shape_point_selected=%d\n", xctx->shape_point_selected); + /* bring up context menu if no pending operation */ if(state == Button3Mask && xctx->semaphore <2) { if(!end_place_move_copy_zoom()) { context_menu_action(xctx->mousex_snap, xctx->mousey_snap); @@ -4442,14 +4507,11 @@ int rstate; /* (reduced state, without ShiftMask) */ if(xctx->semaphore >= 2) break; if(xctx->ui_state & STARTSELECT) { if(state & ControlMask) { - int es = tclgetboolvar("enable_stretch"); - tclsetboolvar("enable_stretch", !es); - select_rect(END,-1); - tclsetboolvar("enable_stretch", es); + select_rect(!enable_stretch, END,-1); } else { /* Button1 release: end of rectangle select */ if(!(state & (Button4Mask|Button5Mask) ) ) { - select_rect(END,-1); + select_rect(enable_stretch, END,-1); } } rebuild_selected_array(); diff --git a/src/findnet.c b/src/findnet.c index cc9801e1..26e52402 100644 --- a/src/findnet.c +++ b/src/findnet.c @@ -375,13 +375,17 @@ static void find_closest_box(double mx ,double my, int override_lock) { double tmp; double ds = xctx->cadhalfdotsize; - int i, c, r=-1, col = 0; + + /* correction for very small boxes */ for(c=0;cenable_layer[c]) continue; for(i=0;irects[c]; ++i) { + double min = MINOR(xctx->rect[c][i].x2 - xctx->rect[c][i].x1, + xctx->rect[c][i].y2 - xctx->rect[c][i].y1); + ds = (xctx->cadhalfdotsize * 8 <= min ) ? xctx->cadhalfdotsize : min / 8; if( POINTINSIDE(mx, my, xctx->rect[c][i].x1 - ds, xctx->rect[c][i].y1 - ds, xctx->rect[c][i].x2 + ds, xctx->rect[c][i].y2 + ds) ) { @@ -402,25 +406,25 @@ static void find_closest_box(double mx ,double my, int override_lock) static void find_closest_element(double mx, double my, int override_lock) { - double tmp; - int i, r=-1; - for(i=0;iinstances; ++i) - { - dbg(2, "find_closest_element(): %s: %g %g %g %g\n", - xctx->inst[i].instname, xctx->inst[i].x1, xctx->inst[i].y1, xctx->inst[i].x2, xctx->inst[i].y2); - if( POINTINSIDE(mx, my, xctx->inst[i].x1, xctx->inst[i].y1, xctx->inst[i].x2, xctx->inst[i].y2) ) + double tmp; + int i, r=-1; + for(i = 0;i < xctx->instances; ++i) { - tmp=pow(mx-(xctx->inst[i].xx1 + xctx->inst[i].xx2)/2, 2)+pow(my-(xctx->inst[i].yy1 + xctx->inst[i].yy2)/2, 2); - if(tmp*0.1 < distance) - { - r = i; distance = tmp*0.1; - } - dbg(2, "find_closest_element(): finding closest element, instances=%d, dist=%.16g\n", i, tmp); + dbg(1, "find_closest_element(): %s: %g %g %g %g\n", + xctx->inst[i].instname, xctx->inst[i].x1, xctx->inst[i].y1, xctx->inst[i].x2, xctx->inst[i].y2); + if( POINTINSIDE(mx, my, xctx->inst[i].x1, xctx->inst[i].y1, xctx->inst[i].x2, xctx->inst[i].y2) ) + { + tmp=dist_from_rect(mx, my, xctx->inst[i].xx1, xctx->inst[i].yy1, xctx->inst[i].xx2, xctx->inst[i].yy2); + if(tmp < distance) + { + r = i; distance = tmp; + } + dbg(2, "find_closest_element(): finding closest element, instances=%d, dist=%.16g\n", i, tmp); + } + } /* end for i */ + if( r != -1 && (override_lock || strboolcmp(get_tok_value(xctx->inst[r].prop_ptr, "lock", 0), "true")) ) { + sel.n = r; sel.type = ELEMENT; } - } /* end for i */ - if( r!=-1 && (override_lock || strboolcmp(get_tok_value(xctx->inst[r].prop_ptr, "lock", 0), "true")) ) { - sel.n = r; sel.type = ELEMENT; - } } static void find_closest_text(double mx, double my) diff --git a/src/font.c b/src/font.c index 372f8b5a..299bbda2 100644 --- a/src/font.c +++ b/src/font.c @@ -35,7 +35,7 @@ void compile_font(void) for(code=0;code<127;code++) { unselect_all(1); - select_inside(code*FONTOFFSET-1,-FONTHEIGHT-1, + select_inside(0, code*FONTOFFSET-1,-FONTHEIGHT-1, code*FONTOFFSET+FONTWIDTH+1,FONTWHITESPACE + FONTDESCENT+1, 1); rebuild_selected_array(); character[code] = my_calloc(_ALLOC_ID_, xctx->lastsel*4+1, sizeof(double)); diff --git a/src/scheduler.c b/src/scheduler.c index f4534fa7..22322d33 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -5018,7 +5018,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg y1 = atof(argv[3]); x2 = atof(argv[4]); y2 = atof(argv[5]); - select_inside(x1, y1, x2, y2, sel); + select_inside(tclgetboolvar("enable_stretch"), x1, y1, x2, y2, sel); Tcl_ResetResult(interp); } diff --git a/src/select.c b/src/select.c index 485c9ee3..ca5105d2 100644 --- a/src/select.c +++ b/src/select.c @@ -1298,20 +1298,18 @@ void select_attached_nets(void) rebuild_selected_array(); } -void select_inside(double x1,double y1, double x2, double y2, int sel) /*added unselect (sel param) */ +void select_inside(int stretch, double x1,double y1, double x2, double y2, int sel) { int c,i, tmpint; double x, y, r, a, b, xa, ya, xb, yb; /* arc */ double xx1,yy1,xx2,yy2, dtmp; xRect tmp; - int en_s; int select_rot = 0, select_flip = 0; #if HAS_CAIRO==1 int customfont; #endif char *estr = NULL; - en_s = tclgetboolvar("enable_stretch"); for(i=0;iwires; ++i) { if(sel) { @@ -1320,12 +1318,12 @@ void select_inside(double x1,double y1, double x2, double y2, int sel) /*added u xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ select_wire(i, SELECTED, 1); } - else if(en_s && POINTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1, x1,y1,x2,y2) ) + else if(stretch && POINTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_wire(i, SELECTED1, 1); } - else if(en_s && POINTINSIDE(xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2) ) + else if(stretch && POINTINSIDE(xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_wire(i, SELECTED2, 1); @@ -1412,7 +1410,7 @@ void select_inside(double x1,double y1, double x2, double y2, int sel) /*added u select_polygon(c, i, SELECTED, 1); } else if(selected_points) { /* for polygon, SELECTED1 means partial sel */ - if(sel && en_s) select_polygon(c, i, SELECTED1,1); + if(sel && stretch) select_polygon(c, i, SELECTED1,1); } } @@ -1425,12 +1423,12 @@ void select_inside(double x1,double y1, double x2, double y2, int sel) /*added u xctx->ui_state |= SELECTION; select_line(c,i,SELECTED,1); } - else if(en_s && POINTINSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1, x1,y1,x2,y2) ) + else if(stretch && POINTINSIDE(xctx->line[c][i].x1,xctx->line[c][i].y1, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ select_line(c, i,SELECTED1,1); } - else if(en_s && POINTINSIDE(xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2) ) + else if(stretch && POINTINSIDE(xctx->line[c][i].x2,xctx->line[c][i].y2, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_line(c, i,SELECTED2,1); @@ -1458,17 +1456,17 @@ void select_inside(double x1,double y1, double x2, double y2, int sel) /*added u xctx->ui_state |= SELECTION; /* set xctx->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 && en_s && POINTINSIDE(x, y, x1, y1, x2, y2) ) + else if( sel && stretch && POINTINSIDE(x, y, x1, y1, x2, y2) ) { xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED1,1); } - else if( sel && en_s && POINTINSIDE(xb, yb, x1, y1, x2, y2) ) + else if( sel && stretch && POINTINSIDE(xb, yb, x1, y1, x2, y2) ) { xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED3,1); } - else if( sel && en_s && POINTINSIDE(xa, ya, x1, y1, x2, y2) ) + else if( sel && stretch && POINTINSIDE(xa, ya, x1, y1, x2, y2) ) { xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ select_arc(c, i,SELECTED2,1); @@ -1490,22 +1488,22 @@ void select_inside(double x1,double y1, double x2, double y2, int sel) /*added u } } else if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 2048)){ /* no stretch on unscaled images */ - if( sel && en_s && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y1, x1,y1,x2,y2) ) + if( sel && stretch && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y1, x1,y1,x2,y2) ) { /*20070302 added stretch select */ xctx->ui_state |= SELECTION; select_box(c, i,SELECTED1,1, 0); } - if( sel && en_s && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y1, x1,y1,x2,y2) ) + if( sel && stretch && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y1, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_box(c, i,SELECTED2,1, 0); } - if( sel && en_s && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y2, x1,y1,x2,y2) ) + if( sel && stretch && POINTINSIDE(xctx->rect[c][i].x1,xctx->rect[c][i].y2, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_box(c, i,SELECTED3,1, 0); } - if( sel && en_s && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y2, x1,y1,x2,y2) ) + if( sel && stretch && POINTINSIDE(xctx->rect[c][i].x2,xctx->rect[c][i].y2, x1,y1,x2,y2) ) { xctx->ui_state |= SELECTION; select_box(c, i,SELECTED4,1, 0); diff --git a/src/xinit.c b/src/xinit.c index 2fcb25f7..4cc8bf24 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -1172,12 +1172,14 @@ static int source_tcl_file(char *s) { char tmp[1024]; 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()); fprintf(errfp, "\n"); my_snprintf(tmp, S(tmp), "tk_messageBox -icon error -type ok -message \ - {Tcl_AppInit() err 1: can not execute %s, please fix:\n %s}", - s, tclresult()); + {Tcl_AppInit() err 1: can not execute %s, please fix:\n%s\nLine No: %d\n}", + s, tclresult(), Tcl_GetErrorLine(interp)); if(has_x) { tcleval( "wm withdraw ."); tcleval( tmp); diff --git a/src/xschem.h b/src/xschem.h index 50a7ff42..a10139bf 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1385,7 +1385,7 @@ extern Selected select_object(double mx,double my, unsigned short sel_mode, extern int set_first_sel(unsigned short type, int n, unsigned int col); extern void unselect_all(int dr); extern void select_attached_nets(void); -extern void select_inside(double x1,double y1, double x2, double y2, int sel); +extern void select_inside(int stretch, double x1,double y1, double x2, double y2, int sel); extern void select_touch(double x1,double y1, double x2, double y2, int sel); /* Select all nets that are dangling, ie not attached to any non pin/port/probe components */ extern int select_dangling_nets(void); @@ -1548,7 +1548,7 @@ extern void pan(int what, int mx, int my); extern void zoom_rectangle(int what); extern void zoom_box(double x1, double y1, double x2, double y2, double factor); extern void save_restore_zoom(int save, Zoom_info *zi); -extern void select_rect(int what, int select); +extern void select_rect(int stretch, int what, int select); extern void new_rect(int what, double mousex_snap, double mousey_snap); extern void new_polygon(int what, double mousex_snap, double mousey_snap); extern void compile_font(void);