diff --git a/.gitignore b/.gitignore index 0fe49d81..9d85221b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ # bison output src/expandlabel.c src/expandlabel.h +src/eval_expr.c # flex output src/parselabel.c src/parselabel.h @@ -39,4 +40,4 @@ scconfig/config.cache doc/manpages/xschem.1 Makefile.conf config.h -*.Identifier \ No newline at end of file +*.Identifier diff --git a/src/callback.c b/src/callback.c index 45e95cec..c1deffe4 100644 --- a/src/callback.c +++ b/src/callback.c @@ -2429,6 +2429,2051 @@ static int grabscreen(const char *win_path, int event, int mx, int my, KeySym ke } #endif +static void handle_enter_notify(int draw_xhair, int crosshair_size) +{ + struct stat buf; + dbg(2, "callback(): Enter event, ui_state=%d\n", xctx->ui_state); + xctx->mouse_inside = 1; + if(draw_xhair) { + if(crosshair_size == 0) { + tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL); + } + } else + tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL); + /* xschem window *sending* selected objects + when the pointer comes back in abort copy operation since it has been done + in another xschem xctx->window; STARTCOPY set and selection file does not exist any more */ + if(stat(sel_file, &buf) && (xctx->ui_state & STARTCOPY) ) + { + copy_objects(ABORT); + unselect_all(1); + } + /* xschem window *receiving* selected objects selection cleared --> abort */ + else if(xctx->paste_from == 1 && stat(sel_file, &buf) && (xctx->ui_state & STARTMERGE)) { + abort_operation(); + } + /*xschem window *receiving* selected objects + * no selected objects and selection file exists --> start merge */ + else if(xctx->lastsel == 0 && !stat(sel_file, &buf)) { + xctx->mousex_snap = 490; + xctx->mousey_snap = -340; + merge_file(1, ".sch"); + } + return; +} + +static void handle_motion_notify(int event, KeySym key, int state, int rstate, int button, + int mx, int my, int aux, int draw_xhair, int enable_stretch, int snap_cursor, int wire_draw_active, char *str) +{ + if( waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + 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); + /* pan schematic */ + if(xctx->ui_state & STARTPAN) pan(RUBBER, mx, my); + + if(xctx->semaphore >= 2) { + if(draw_xhair) { + draw_crosshair(2, state); /* locked UI: draw new crosshair and break out */ + } + if(snap_cursor && wire_draw_active) draw_snap_cursor(2); + return; + } + + /* 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", + xctx->mousex_snap, xctx->mousey_snap, + xctx->lastsel , + xctx->mousex_snap-xctx->mx_double_save, xctx->mousey_snap-xctx->my_double_save + ); + statusmsg(str,1); + } + } + + /* determine direction of a rectangle selection (or unselection with ALT key) */ + if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & (PLACE_SYMBOL | STARTPAN | PLACE_TEXT)) ) { + /* Unselect by area : determine direction */ + if( ((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) { + if(mx >= xctx->mx_save) xctx->nl_dir = 0; + else xctx->nl_dir = 1; + 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(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 or zoom box */ + redraw_w_a_l_r_p_z_rubbers(0); + + /* 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) && + !(xctx->ui_state & STARTPAN) && !(SET_MODMASK) && !xctx->shape_point_selected && + !(state & ShiftMask) && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) + { + if(mx != xctx->mx_save || my != xctx->my_save) { + xctx->mouse_moved = 1; + if(!xctx->drag_elements) { + if( !(xctx->ui_state & STARTSELECT)) { + select_rect(enable_stretch, START,1); + xctx->onetime=1; + } + if(abs(mx-xctx->mx_save) > 8 || + abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ + if(xctx->onetime) { + unselect_all(1); /* 20171026 avoid multiple calls of unselect_all() */ + xctx->onetime=0; + } + xctx->ui_state|=STARTSELECT; /* set it again cause unselect_all(1) clears it... */ + } + } + } + } + /* Unselect by area */ + if( (((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) && + !(state & ShiftMask) && + !(xctx->ui_state & STARTPAN) && + !xctx->shape_point_selected && + !(xctx->ui_state & STARTSELECT) && + !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) { /* unselect area */ + select_rect(enable_stretch, START,0); + } + /* Select by area. Shift pressed */ + else if((state&Button1Mask) && (state & ShiftMask) && !(xctx->ui_state & STARTWIRE) && + !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !xctx->shape_point_selected && + !xctx->drag_elements && !(xctx->ui_state & STARTPAN) ) { + if(mx != xctx->mx_save || my != xctx->my_save) { + if( !(xctx->ui_state & STARTSELECT)) { + select_rect(enable_stretch, START,1); + } + if(abs(mx-xctx->mx_save) > 8 || + abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ + if(!xctx->already_selected) { + select_object(X_TO_XSCHEM(xctx->mx_save), + Y_TO_XSCHEM(xctx->my_save), 0, 0, NULL); /* remove near obj if dragging */ + } + rebuild_selected_array(); + } + } + } + if(draw_xhair) { + draw_crosshair(2, state); /* what = 2(draw) */ + } + if(snap_cursor && wire_draw_active) draw_snap_cursor(2); + return; +} + +static void handle_key_press(int event, KeySym key, int state, int rstate, int mx, int my, + int button, int aux, int infix_interface, int enable_stretch, const char *win_path, double c_snap, + int cadence_compat, int wire_draw_active, int snap_cursor, char *str) +{ + if(key==' ') { + if(xctx->ui_state & STARTWIRE) { /* & instead of == 20190409 */ + new_wire(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap); + xctx->manhattan_lines++; + xctx->manhattan_lines %=3; + new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + + } else if(xctx->ui_state & STARTLINE) { + new_line(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap); + xctx->manhattan_lines++; + xctx->manhattan_lines %=3; + new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + } else { + if(xctx->semaphore<2) { + rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ + } + pan(START, mx, my); + xctx->ui_state |= STARTPAN; + } + return; + } + if(key == '_' ) /* toggle change line width */ + { + if(!tclgetboolvar("change_lw")) { + tcleval("alert_ { enabling change line width} {}"); + tclsetvar("change_lw","1"); + } + else { + tcleval("alert_ { disabling change line width} {}"); + tclsetvar("change_lw","0"); + } + return; + } + if(key == 'b' && rstate==ControlMask) /* toggle show text in symbol */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->sym_txt =!xctx->sym_txt; + if(xctx->sym_txt) { + /* tcleval("alert_ { enabling text in symbol} {}"); */ + tclsetvar("sym_txt","1"); + draw(); + } + else { + /* tcleval("alert_ { disabling text in symbol} {}"); */ + tclsetvar("sym_txt","0"); + draw(); + } + return; + } + if(key == '%' ) /* toggle draw grid */ + { + int dr_gr; + dr_gr = tclgetboolvar("draw_grid"); + dr_gr =!dr_gr; + if(dr_gr) { + /* tcleval("alert_ { enabling draw grid} {}"); */ + tclsetvar("draw_grid","1"); + draw(); + } + else { + /* tcleval("alert_ { disabling draw grid} {}"); */ + tclsetvar("draw_grid","0"); + draw(); + } + return; + } + if(key == 'j' && rstate==0 ) /* print list of highlight nets */ + { + if(xctx->semaphore >= 2) return; + print_hilight_net(1); + return; + } + if(key == 'j' && rstate==ControlMask) /* create ipins from highlight nets */ + { + if(xctx->semaphore >= 2) return; + print_hilight_net(0); + return; + } + if(key == 'j' && EQUAL_MODMASK) /* create labels without i prefix from hilight nets */ + { + if(xctx->semaphore >= 2) return; + print_hilight_net(4); + return; + } + if(key == 'J' && SET_MODMASK ) /* create labels with i prefix from hilight nets */ + { + if(xctx->semaphore >= 2) return; + print_hilight_net(2); + return; + } + if(key == 'h' && rstate==ControlMask ) /* go to http link */ + { + int savesem = xctx->semaphore; + xctx->semaphore = 0; + launcher(); + xctx->semaphore = savesem; + return; + } + if(key == 'h' && EQUAL_MODMASK) /* create symbol pins from schematic pins 20171208 */ + { + tcleval("schpins_to_sympins"); + return; + } + if(key == 'h' && rstate == 0) { + /* horizontally constrained drag 20171023 */ + if ( xctx->constr_mv == 1 ) { + tcleval("set constr_mv 0" ); + xctx->constr_mv = 0; + } else { + tcleval("set constr_mv 1" ); + xctx->constr_mv = 1; + } + if(xctx->ui_state & STARTWIRE) { + if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; + if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; + new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + } + if(xctx->ui_state & STARTLINE) { + if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; + if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; + new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + } + return; + } + if(key=='H' && rstate == 0) { /* attach labels to selected instances */ + attach_labels_to_inst(1); + return; + } + if (key == 'H' && rstate == ControlMask) { /* create schematic and symbol from selected components */ + make_schematic_symbol_from_sel(); + return; + } + if(key == 'v' && rstate==0) { + /* vertically constrained drag 20171023 */ + if ( xctx->constr_mv == 2 ) { + tcleval("set constr_mv 0" ); + xctx->constr_mv = 0; + } else { + tcleval("set constr_mv 2" ); + xctx->constr_mv = 2; + } + if(xctx->ui_state & STARTWIRE) { + if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; + if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; + new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + } + if(xctx->ui_state & STARTLINE) { + if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; + if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; + new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); + } + return; + } + if(key == 'j' && SET_MODMASK && (state & ControlMask) ) /* print list of highlight net with label expansion */ + { + print_hilight_net(3); + return; + } + if(key == 'J' && rstate == 0) { + create_plot_cmd(); + return; + } + if(key == '$' && rstate == 0 ) /* toggle pixmap saving */ + { + xctx->draw_pixmap =!xctx->draw_pixmap; + if(xctx->draw_pixmap) tcleval("alert_ { enabling draw pixmap} {}"); + else tcleval("alert_ { disabling draw pixmap} {}"); + return; + } + if(key == '$' && (state &ControlMask) ) /* toggle window drawing */ + { + xctx->draw_window =!xctx->draw_window; + if(xctx->draw_window) { + tcleval("alert_ { enabling draw window} {}"); + tclsetvar("draw_window","1"); + } else { + tcleval("alert_ { disabling draw window} {}"); + tclsetvar("draw_window","0"); + } + return; + } + if(key == '=' && (state &ControlMask)) /* toggle fill rectangles */ + { + int x; + xctx->fill_pattern++; + if(xctx->fill_pattern==3) xctx->fill_pattern=0; + + if(xctx->fill_pattern==1) { + tcleval("alert_ { Stippled pattern fill} {}"); + for(x=0;xfill_type[x]==1) XSetFillStyle(display,xctx->gcstipple[x],FillSolid); + else XSetFillStyle(display,xctx->gcstipple[x],FillStippled); + } + } + else if(xctx->fill_pattern==2) { + tcleval("alert_ { solid pattern fill} {}"); + for(x=0;xgcstipple[x],FillSolid); + } + else { + tcleval("alert_ { No pattern fill} {}"); + for(x=0;xgcstipple[x],FillStippled); + } + + draw(); + return; + } + if(key == '+' && state & ControlMask) /* change line width */ + { + xctx->lw = round_to_n_digits(xctx->lw + 0.5, 2); + change_linewidth(xctx->lw); + tclsetboolvar("change_lw", 0); + draw(); + return; + } + + if(key == '-' && state & ControlMask) /* change line width */ + { + xctx->lw = round_to_n_digits(xctx->lw - 0.5, 2); + if(xctx->lw < 0.0) xctx->lw = 0.0; + change_linewidth(xctx->lw); + tclsetboolvar("change_lw", 0); + draw(); + return; + } + if(key == 'X' && rstate == 0) /* highlight discrepanciens between selected instance pin and net names */ + { + hilight_net_pin_mismatches(); + return; + } + if(key== 'W' /* && !xctx->ui_state */ && rstate == 0 && !cadence_compat) { /* create wire snapping to closest instance pin (original keybind) */ + if(xctx->semaphore >= 2) return; + snapped_wire(c_snap); + return; + } + if(key== 's' /* && !xctx->ui_state */ && rstate == 0 && cadence_compat) { /* create wire snapping to closest instance pin (cadence keybind) */ + if(xctx->semaphore >= 2) return; + snapped_wire(c_snap); + return; + } + if(key == 'w' /* && !xctx->ui_state */ && rstate==0) /* place wire. */ + { + 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) { + tcleval("set constr_mv 0" ); + xctx->constr_mv=0; + } + } else { + xctx->last_command = 0; + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTWIRE; + if(prev_state & STARTWIRE) start_wire(xctx->mousex_snap, xctx->mousey_snap); + } + return; + } + if(key == XK_Return && (state == 0 ) && xctx->ui_state & STARTPOLYGON) { /* close polygon */ + new_polygon(ADD|END, xctx->mousex_snap, xctx->mousey_snap); + return; + } + if(key == XK_Escape) /* abort & redraw */ + { + if(xctx->semaphore < 2) { + abort_operation(); + } + /* stuff that can be done reentrantly ... */ + tclsetvar("tclstop", "1"); /* stop simulation if any running */ + if(xctx->ui_state2 & MENUSTARTWIRE) { + xctx->ui_state2 &= ~MENUSTARTWIRE; + } + if(tclgetboolvar("persistent_command") && (xctx->last_command & STARTWIRE) && cadence_compat) { + xctx->last_command &= ~STARTWIRE; + if(snap_cursor) draw_snap_cursor(1); + } + return; + } + if(key=='z' && rstate == 0 && + !(xctx->ui_state & (STARTRECT | STARTLINE | STARTWIRE | STARTPOLYGON | STARTARC))) /* zoom box */ + { + dbg(1, "callback(): zoom_rectangle call\n"); + zoom_rectangle(START);return; + } + if(key=='Z' && rstate == 0) /* zoom in */ + { + view_zoom(0.0); return; + } + if(key=='z' && EQUAL_MODMASK) /* toggle snap-cursor option */ + { + if(tclgetboolvar("snap_cursor")) { + tclsetvar("snap_cursor", "0"); + draw_snap_cursor(1); + xctx->closest_pin_found = 0; + xctx->prev_snapx = 0.0; + xctx->prev_snapy = 0.0; + } else { + tclsetvar("snap_cursor", "1"); + if(wire_draw_active) draw_snap_cursor(3); + } + } + if(key=='p' && EQUAL_MODMASK) /* add symbol pin */ + { + xctx->push_undo(); + unselect_all(1); + storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5, + xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout"); + xctx->need_reb_sel_arr=1; + rebuild_selected_array(); + move_objects(START,0,0,0); + xctx->ui_state |= START_SYMPIN; + return; + } + if(key=='p' && !(xctx->ui_state & STARTPOLYGON) && rstate==0) /* start polygon */ + { + if(xctx->semaphore >= 2) return; + dbg(1, "callback(): start polygon\n"); + if(infix_interface) { + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + xctx->last_command = 0; + new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTPOLYGON; + } + return; + } + if(key=='P' && rstate == 0) /* pan, other way to. */ + { + xctx->xorigin=-xctx->mousex_snap+xctx->areaw*xctx->zoom/2.0; + xctx->yorigin=-xctx->mousey_snap+xctx->areah*xctx->zoom/2.0; + draw(); + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key=='5' && rstate == 0) { /* 20110112 display only probes */ + xctx->only_probes = !xctx->only_probes; + tclsetboolvar("only_probes", xctx->only_probes); + toggle_only_probes(); + return; + } /* /20110112 */ + if(key<='9' && key >='0' && state==ControlMask) /* choose layer */ + { + char n[30]; + xctx->rectcolor = (int)key - '0'+4; + my_snprintf(n, S(n), "%d", xctx->rectcolor); + tclvareval("xschem set rectcolor ", n, NULL); + + if(has_x) { + if(!strcmp(win_path, ".drw")) { + tclvareval("reconfigure_layers_button {}", NULL); + } else { + tclvareval("reconfigure_layers_button [winfo parent ", win_path, "]", NULL); + } + } + dbg(1, "callback(): new color: %d\n",xctx->color_index[xctx->rectcolor]); + return; + } + if(key==XK_Delete && (xctx->ui_state & SELECTION) ) /* delete selection */ + { + if(xctx->semaphore >= 2) return; + delete(1/* to_push_undo */);return; + } + if(key==XK_Right && state == ControlMask) { + int save = xctx->semaphore; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + if(xctx->semaphore >= 2) return; + xctx->semaphore = 0; + tcleval("next_tab"); + xctx->semaphore = save; + return; + } + if(key==XK_Left && state == ControlMask) { + int save = xctx->semaphore; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + if(xctx->semaphore >= 2) return; + xctx->semaphore = 0; + tcleval("prev_tab"); + xctx->semaphore = save; + return; + } + if(key==XK_Right && !(state & ControlMask)) /* left */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->xorigin+=-CADMOVESTEP*xctx->zoom; + draw(); + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key==XK_Left && !(state & ControlMask)) /* right */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->xorigin-=-CADMOVESTEP*xctx->zoom; + draw(); + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key==XK_Down) /* down */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->yorigin+=-CADMOVESTEP*xctx->zoom; + draw(); + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key==XK_Up) /* up */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->yorigin-=-CADMOVESTEP*xctx->zoom; + draw(); + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key=='w' && rstate == ControlMask) /* close current schematic */ + { + int save_sem; + if(xctx->semaphore >= 2) return; + save_sem = xctx->semaphore; + tcleval("xschem exit"); + xctx->semaphore = save_sem; + return; + } + /* toggle spice_ignore, verilog_ignore, ... flag on selected instances. */ + if(key == 'T' && rstate == 0) { + toggle_ignore(); + } + if(key=='t' && rstate == 0) /* place text */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + if(xctx->semaphore >= 2) return; + xctx->last_command = 0; + xctx->mx_double_save = xctx->mousex_snap; + xctx->my_double_save = xctx->mousey_snap; + if(place_text(0, xctx->mousex_snap, xctx->mousey_snap)) { /* 1 = draw text 24122002 */ + xctx->mousey_snap = xctx->my_double_save; + xctx->mousex_snap = xctx->mx_double_save; + move_objects(START,0,0,0); + xctx->ui_state |= PLACE_TEXT; + } + return; + } + if(key=='t' && (rstate & ControlMask)) + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + return; + } + if(key=='r' /* && !xctx->ui_state */ && rstate==0) /* start rect */ + { + dbg(1, "callback(): start rect\n"); + if(xctx->semaphore >= 2) return; + if(infix_interface) { + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + xctx->last_command = 0; + new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTRECT; + } + return; + } + if(key=='V' && rstate == ControlMask) /* toggle spice/vhdl netlist */ + { + xctx->netlist_type++; if(xctx->netlist_type==6) xctx->netlist_type=1; + set_tcl_netlist_type(); + draw(); /* needed to ungrey or grey out components due to *_ignore attribute */ + return; + } + if((key=='s' && rstate == 0) && !cadence_compat) /* simulate (original keybind) */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " + "-message {Run circuit simulation?}"); + if(strcmp(tclresult(),"ok")==0) { + tcleval("[xschem get top_path].menubar invoke Simulate"); + } + return; + } + if((key=='r' && rstate == ControlMask) && cadence_compat) /* simulate (for cadence users) */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " + "-message {Run circuit simulation?}"); + if(strcmp(tclresult(),"ok")==0) { + tcleval("[xschem get top_path].menubar invoke Simulate"); + } + return; + } + if(key=='s' && rstate == ControlMask ) /* save 20121201 */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + /* check if unnamed schematic, use saveas in this case */ + if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) { + saveas(NULL, SCHEMATIC); + } else { + save(1, 0); + } + return; + } + if(key=='s' && SET_MODMASK && (state & ControlMask) ) /* save as symbol */ + { + if(xctx->semaphore >= 2) return; + saveas(NULL, SYMBOL); + return; + } + if(key=='S' && rstate == ControlMask) /* save as schematic */ + { + if(xctx->semaphore >= 2) return; + saveas(NULL, SCHEMATIC); + return; + } + if(key=='e' && rstate == 0) /* descend to schematic */ + { + if(xctx->semaphore >= 2) return; + descend_schematic(0, 1, 1, 1);return; + } + if(key=='e' && EQUAL_MODMASK) /* edit schematic in new window */ + { + int save = xctx->semaphore; + xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ + /* schematic_in_new_window(0, 1, 0); */ + tcleval("open_sub_schematic"); + xctx->semaphore = save; + return; + } + + if(key=='E' && EQUAL_MODMASK) /* edit schematic in new window - new xschem process */ + { + int save = xctx->semaphore; + xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ + schematic_in_new_window(1, 1, 0); + xctx->semaphore = save; + return; + } + + if(key=='i' && EQUAL_MODMASK) /* edit symbol in new window */ + { + int save = xctx->semaphore; + xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ + symbol_in_new_window(0); + xctx->semaphore = save; + return; + } + + if(key=='I' && EQUAL_MODMASK) /* edit symbol in new window - new xschem process */ + { + int save = xctx->semaphore; + xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ + symbol_in_new_window(1); + xctx->semaphore = save; + return; + } + + + if( (key=='e' && rstate == ControlMask) || (key==XK_BackSpace)) /* back */ + { + if(xctx->semaphore >= 2) return; + go_back(1);return; + } + + if(key=='a' && rstate == 0) /* make symbol */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " + "-message {do you want to make symbol view ?}"); + if(strcmp(tclresult(),"ok")==0) + { + save_schematic(xctx->sch[xctx->currsch], 0); + make_symbol(); + } + return; + } + if(key=='a' && rstate == ControlMask) /* select all */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + select_all(); + return; + } + if(key=='y' && rstate == 0) /* toggle stretching */ + { + enable_stretch = !enable_stretch; + tclsetboolvar("enable_stretch", enable_stretch); + return; + } + if(key=='x' && EQUAL_MODMASK) /* toggle draw crosshair at mouse pos */ + { + if(tclgetboolvar("draw_crosshair")) { + tclsetvar("draw_crosshair", "0"); + } else { + tclsetvar("draw_crosshair", "1"); + } + draw(); + } + if(key=='x' && rstate == ControlMask) /* cut selection into clipboard */ + { + if(xctx->semaphore >= 2) return; + rebuild_selected_array(); + if(xctx->lastsel) { /* 20071203 check if something selected */ + save_selection(2); + delete(1/* to_push_undo */); + } + return; + } + if(key=='c' && rstate == ControlMask) /* copy selection into clipboard */ + { + if(xctx->semaphore >= 2) return; + rebuild_selected_array(); + if(xctx->lastsel) { /* 20071203 check if something selected */ + save_selection(2); + } + return; + } + if(key=='C' /* && !xctx->ui_state */ && rstate == 0) /* place arc */ + { + if(xctx->semaphore >= 2) return; + if(infix_interface) { + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + xctx->last_command = 0; + new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTARC; + } + return; + } + if(key=='C' /* && !xctx->ui_state */ && rstate == ControlMask) /* place circle */ + { + if(xctx->semaphore >= 2) return; + if(infix_interface) { + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + xctx->last_command = 0; + new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTCIRCLE; + } + return; + } + if(key=='O' && rstate == ControlMask ) /* load most recent tile */ + { + tclvareval("xschem load -gui [lindex $recentfile 0]", NULL); + return; + } + if(key=='O' && rstate == 0) /* toggle light/dark colorscheme 20171113 */ + { + int d_c; + d_c = tclgetboolvar("dark_colorscheme"); + d_c = !d_c; + tclsetboolvar("dark_colorscheme", d_c); + tclsetdoublevar("dim_value", 0.0); + tclsetdoublevar("dim_bg", 0.0); + build_colors(0.0, 0.0); + draw(); + return; + } + if(key=='v' && rstate == ControlMask) /* paste from clipboard */ + { + if(xctx->semaphore >= 2) return; + merge_file(2,".sch"); + return; + } + if(key=='Q' && rstate == ControlMask ) /* view attributes */ + { + edit_property(2);return; + } + if(key=='q' && rstate==ControlMask) /* quit xschem */ + { + if(xctx->semaphore >= 2) return; + /* must be set to zero, otherwise switch_tab/switch_win does not proceed + * and these are necessary when closing tabs/windows */ + xctx->semaphore = 0; + tcleval("quit_xschem"); + return; + } + if(key=='q' && rstate==0) /* edit attributes */ + { + if(xctx->semaphore >= 2) return; + edit_property(0); + return; + } + if(key=='q' && EQUAL_MODMASK) /* edit .sch file (DANGER!!) */ + { + if(xctx->semaphore >= 2) return; + rebuild_selected_array(); + if(xctx->lastsel==0 ) { + my_snprintf(str, S(str), "edit_file {%s}", abs_sym_path(xctx->sch[xctx->currsch], "")); + tcleval(str); + } + else if(xctx->sel_array[0].type==ELEMENT) { + my_snprintf(str, S(str), "edit_file {%s}", + abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), "")); + tcleval(str); + + } + return; + } + #if defined(__unix__) && HAS_CAIRO==1 + if(key == XK_Print) { + xctx->ui_state |= GRABSCREEN; + tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL); + tclvareval("grab set -global ", xctx->top_path, ".drw", NULL); + return; + } + #endif + if(key=='Q' && rstate == 0) /* edit attributes in editor */ + { + if(xctx->semaphore >= 2) return; + edit_property(1);return; + } + if(key=='i' && rstate==0) /* descend to symbol */ + { + if(xctx->semaphore >= 2) return; + descend_symbol();return; + } + if((key==XK_Insert && state == ShiftMask) || (key == 'i' && rstate == ControlMask)) /* insert sym */ + { + tcleval("load_file_dialog {Insert symbol} *.\\{sym,tcl\\} INITIALINSTDIR 2"); + return; + } + if((key==XK_Insert) || (key == 'I' && rstate == 0) ) /* insert sym */ + { + if(xctx->semaphore >= 2) return; + start_place_symbol(); + + return; + } + if(key=='s' && SET_MODMASK) /* reload */ + { + if(xctx->semaphore >= 2) return; + tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " + "-message {Are you sure you want to reload from disk?}"); + if(strcmp(tclresult(),"ok")==0) { + char filename[PATH_MAX]; + unselect_all(1); + remove_symbols(); + my_strncpy(filename, abs_sym_path(xctx->sch[xctx->currsch], ""), S(filename)); + load_schematic(1, filename, 1, 1); + draw(); + } + return; + } + if(key=='o' && rstate == ControlMask) /* load */ + { + if(xctx->semaphore >= 2) return; + ask_new_file(); + return; + } + if(key=='S' && rstate == 0) /* change element order */ + { + if(xctx->semaphore >= 2) return; + change_elem_order(-1); + return; + } + if(key=='k' && EQUAL_MODMASK) /* select whole net (all attached wires/labels/pins) */ + { + select_hilight_net(); + return; + } + if(key=='k' && rstate==ControlMask) /* unhilight net */ + { + if(xctx->semaphore >= 2) return; + unhilight_net(); + return; + } + if(key=='K' && rstate == ControlMask) /* hilight net drilling thru elements */ + /* with 'propag=' prop set on pins */ + { + if(xctx->semaphore >= 2) return; + xctx->enable_drill=1; + hilight_net(0); + redraw_hilights(0); + /* draw_hilight_net(1); */ + return; + } + if(key=='k' && rstate==0) /* hilight net */ + { + if(xctx->semaphore >= 2) return; + xctx->enable_drill=0; + hilight_net(0); + redraw_hilights(0); + /* draw_hilight_net(1); */ + return; + } + if(key=='K' && rstate == 0) /* delete hilighted nets */ + { + if(xctx->semaphore >= 2) return; + xctx->enable_drill=0; + clear_all_hilights(); + /* undraw_hilight_net(1); */ + draw(); + return; + } + if(key=='g' && EQUAL_MODMASK) { /* highlight net and send to viewer */ + int tool = 0; + int exists = 0; + char *tool_name = NULL; + char str[200]; + + if(xctx->semaphore >= 2) return; + tcleval("winfo exists .graphdialog"); + if(tclresult()[0] == '1') tool = XSCHEM_GRAPH; + else if(xctx->graph_lastsel >=0 && + xctx->rects[GRIDLAYER] > xctx->graph_lastsel && + xctx->rect[GRIDLAYER][xctx->graph_lastsel].flags & 1) { + tool = XSCHEM_GRAPH; + } + tcleval("info exists sim"); + if(tclresult()[0] == '1') exists = 1; + xctx->enable_drill = 0; + if(exists) { + if(!tool) { + tool = tclgetintvar("sim(spicewave,default)"); + my_snprintf(str, S(str), "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; + else if(strstr(tool_name, "Bespice")) tool=BESPICE; + my_free(_ALLOC_ID_, &tool_name); + } + } + if(tool) { + hilight_net(tool); + redraw_hilights(0); + } + Tcl_ResetResult(interp); + return; + } + if(key=='g' && rstate==0) /* half snap factor */ + { + set_snap(c_snap / 2.0); + change_linewidth(-1.); + draw(); + return; + } + if(key=='g' && rstate==ControlMask) /* set snap factor 20161212 */ + { + 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); + return; + } + if(key=='G' && rstate == 0) /* double snap factor */ + { + set_snap(c_snap * 2.0); + change_linewidth(-1.); + draw(); + return; + } + if(key=='*' && EQUAL_MODMASK) /* svg print , 20121108 */ + { + if(xctx->semaphore >= 2) return; + svg_draw(); + return; + } + if(key=='*' && rstate == 0 ) /* postscript print */ + { + if(xctx->semaphore >= 2) return; + ps_draw(7, 0, 0); + return; + } + if(key=='*' && rstate == ControlMask) /* xpm print */ + { + if(xctx->semaphore >= 2) return; + print_image(); + return; + } + if(key=='u' && EQUAL_MODMASK) /* align to grid */ + { + if(xctx->semaphore >= 2) return; + xctx->push_undo(); + round_schematic_to_grid(c_snap); + set_modify(1); + if(tclgetboolvar("autotrim_wires")) trim_wires(); + xctx->prep_hash_inst=0; + xctx->prep_hash_wires=0; + xctx->prep_net_structs=0; + xctx->prep_hi_structs=0; + + draw(); + return; + } + if(0 && (key=='u') && rstate==ControlMask) /* testmode */ + { + static int x = 0; + + if(x == 0) { + int i; + XFillRectangle(display, xctx->window, xctx->gc[BACKLAYER], xctx->areax1, xctx->areay1, + xctx->areaw, xctx->areah); + XFlush(display); + sleep_ms(400); + for(i = xctx->xrect[0].x; i < xctx->xrect[0].width; i++) { + XDrawLine(display, xctx->window, xctx->gctiled, + i, xctx->xrect[0].y, i, xctx->xrect[0].height); + XFlush(display); + sleep_ms(4); + } + } else if(x == 1) { + int i; + XFillRectangle(display, xctx->window, xctx->gc[BACKLAYER], xctx->areax1, xctx->areay1, + xctx->areaw, xctx->areah); + XFlush(display); + sleep_ms(400); + for(i = xctx->xrect[0].x; i < xctx->xrect[0].width; i++) { + XDrawLine(display, xctx->window, xctx->gctiled, + i, xctx->xrect[0].y, i+1, xctx->xrect[0].height); + XFlush(display); + sleep_ms(4); + } + } + x++; + x %= 2; + return; + } + if(key=='u' && rstate==0) /* undo */ + { + if(xctx->semaphore >= 2) return; + xctx->pop_undo(0, 1); /* 2nd parameter: set_modify_status */ + draw(); + return; + } + if(key=='U' && rstate == 0) /* redo */ + { + if(xctx->semaphore >= 2) return; + xctx->pop_undo(1, 1); /* 2nd parameter: set_modify_status */ + draw(); + return; + } + if(key=='&') /* check wire connectivity */ + { + if(xctx->semaphore >= 2) return; + xctx->push_undo(); + trim_wires(); + draw(); + return; + } + if(key=='l' && rstate == ControlMask) { /* create schematic from selected symbol 20171004 */ + if(xctx->semaphore >= 2) return; + create_sch_from_sym(); + return; + } + if(key=='l' /* && !xctx->ui_state */ && rstate == 0) /* start line */ + { + int prev_state = xctx->ui_state; + if(xctx->semaphore >= 2) return; + if(infix_interface) { + start_line(xctx->mousex_snap, xctx->mousey_snap); + if(prev_state == STARTLINE) { + tcleval("set constr_mv 0" ); + xctx->constr_mv=0; + } + } else { + xctx->last_command = 0; + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTLINE; + } + return; + } + if(key=='l' && EQUAL_MODMASK) { /* add pin label*/ + place_net_label(1); + return; + } + if(key >= '0' && key <= '4' && state == 0) { /* toggle pin logic level */ + if(xctx->semaphore >= 2) return; + if(key == '4') logic_set(-1, 1, NULL); + else logic_set((int)key - '0', 1, NULL); + return; + } + if(key=='L' && EQUAL_MODMASK ) { /* add pin label*/ + place_net_label(0); + return; + } + if(key=='L' && rstate == 0) { /* toggle orthogonal routing */ + if(tclgetboolvar("orthogonal_wiring")){ + tclsetboolvar("orthogonal_wiring", 0); + xctx->manhattan_lines = 0; + } else { + tclsetboolvar("orthogonal_wiring", 1); + } + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + if(key=='F' && rstate == 0) /* flip */ + { + if(xctx->ui_state & STARTMOVE) move_objects(FLIP,0,0,0); + else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP); + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(FLIP,0,0,0); + move_objects(END,0,0,0); + } + return; + } + if(key=='V' && rstate == 0) /* vertical flip */ + { + if(xctx->ui_state & STARTMOVE) { + move_objects(ROTATE,0,0,0); + move_objects(ROTATE,0,0,0); + move_objects(FLIP,0,0,0); + } + else if(xctx->ui_state & STARTCOPY) { + copy_objects(ROTATE); + copy_objects(ROTATE); + copy_objects(FLIP); + } + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(ROTATE,0,0,0); + move_objects(ROTATE,0,0,0); + move_objects(FLIP,0,0,0); + move_objects(END,0,0,0); + } + return; + } + if(key=='v' && EQUAL_MODMASK) /* vertical flip objects around their anchor points */ + { + if(xctx->ui_state & STARTMOVE) { + move_objects(ROTATE|ROTATELOCAL,0,0,0); + move_objects(ROTATE|ROTATELOCAL,0,0,0); + move_objects(FLIP|ROTATELOCAL,0,0,0); + } + else if(xctx->ui_state & STARTCOPY) { + copy_objects(ROTATE|ROTATELOCAL); + copy_objects(ROTATE|ROTATELOCAL); + copy_objects(FLIP|ROTATELOCAL); + } + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(ROTATE|ROTATELOCAL,0,0,0); + move_objects(ROTATE|ROTATELOCAL,0,0,0); + move_objects(FLIP|ROTATELOCAL,0,0,0); + move_objects(END,0,0,0); + } + return; + } + + if(key=='\\' && state==0) /* fullscreen */ + { + + dbg(1, "callback(): toggle fullscreen, win_path=%s\n", win_path); + toggle_fullscreen(win_path); + return; + } + if(key=='f' && EQUAL_MODMASK) /* flip objects around their anchor points 20171208 */ + { + if(xctx->ui_state & STARTMOVE) move_objects(FLIP|ROTATELOCAL,0,0,0); + else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP|ROTATELOCAL); + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(FLIP|ROTATELOCAL,0,0,0); + move_objects(END,0,0,0); + } + return; + } + if(key=='R' && rstate == 0) /* rotate */ + { + if(xctx->ui_state & STARTMOVE) move_objects(ROTATE,0,0,0); + else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE); + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(ROTATE,0,0,0); + move_objects(END,0,0,0); + } + + return; + } + if(key=='r' && EQUAL_MODMASK) /* rotate objects around their anchor points 20171208 */ + { + if(xctx->ui_state & STARTMOVE) move_objects(ROTATE|ROTATELOCAL,0,0,0); + else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE|ROTATELOCAL); + else { + rebuild_selected_array(); + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + move_objects(ROTATE|ROTATELOCAL,0,0,0); + move_objects(END,0,0,0); + } + return; + } + /* Move selection */ + if(key=='m' && rstate==0 && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + 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; + move_objects(START,0,0,0); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTMOVE; + } + return; + } + /* Move selection adding wires to moved pins */ + if(((key == 'M' && rstate == 0) || (key == 'm' && EQUAL_MODMASK)) && + !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + 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; + xctx->my_double_save=xctx->mousey_snap; + /* select_attached_nets(); */ /* stretch nets that land on selected instance pins */ + move_objects(START,0,0,0); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTMOVE; + } + return; + } + /* move selection stretching attached nets */ + if(key=='m' && rstate == ControlMask && + !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + 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; + move_objects(START,0,0,0); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTMOVE; + } + return; + } + + /* move selection, stretch attached nets, create new wires on pin-to-moved-pin connections */ + if(key=='M' && rstate == ControlMask && + !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + 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; + xctx->my_double_save=xctx->mousey_snap; + move_objects(START,0,0,0); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTMOVE; + } + return; + } + + if(key=='c' && EQUAL_MODMASK && /* duplicate selection */ + !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + if(xctx->semaphore >= 2) return; + 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; + xctx->my_double_save=xctx->mousey_snap; + copy_objects(START); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTCOPY; + } + return; + } + + if(key=='c' && rstate==0 && /* duplicate selection */ + !(xctx->ui_state & (STARTMOVE | STARTCOPY))) + { + if(xctx->semaphore >= 2) return; + if(infix_interface) { + xctx->mx_double_save=xctx->mousex_snap; + xctx->my_double_save=xctx->mousey_snap; + copy_objects(START); + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTCOPY; + } + return; + } + if(key=='n' && rstate == ControlMask) /* clear schematic */ + { + if(xctx->semaphore >= 2) return; + tcleval("xschem clear SCHEMATIC"); + return; + } + if(key=='N' && rstate == ControlMask ) /* clear symbol */ + { + if(xctx->semaphore >= 2) return; + tcleval("xschem clear SYMBOL"); + return; + } + if(key=='n' && rstate==0) /* hierarchical netlist */ + { + if(xctx->semaphore >= 2) return; + tcleval("xschem netlist -erc"); + return; + } + if(key=='N' && rstate == 0) /* current level only netlist */ + { + int err = 0; + yyparse_error = 0; + if(xctx->semaphore >= 2) return; + unselect_all(1); + if( set_netlist_dir(0, NULL) ) { + dbg(1, "callback(): -------------\n"); + if(xctx->netlist_type == CAD_SPICE_NETLIST) + err = global_spice_netlist(0, 1); + else if(xctx->netlist_type == CAD_VHDL_NETLIST) + err = global_vhdl_netlist(0, 1); + else if(xctx->netlist_type == CAD_VERILOG_NETLIST) + err = global_verilog_netlist(0, 1); + else if(xctx->netlist_type == CAD_TEDAX_NETLIST) + err = global_tedax_netlist(0, 1); + else + tcleval("tk_messageBox -type ok -parent [xschem get topwindow] " + "-message {Please Set netlisting mode (Options menu)}"); + dbg(1, "callback(): -------------\n"); + } + else { + if(has_x) tcleval("alert_ {Can not write into the netlist directory. Please check} {}"); + else dbg(0, "Can not write into the netlist directory. Please check"); + err = 1; + } + if(err) { + if(has_x) { + tclvareval(xctx->top_path, ".menubar entryconfigure Netlist -background red", NULL); + tclvareval("set tctx::", xctx->current_win_path, "_netlist red", NULL); + } + } else { + if(has_x) { + tclvareval(xctx->top_path, ".menubar entryconfigure Netlist -background Green", NULL); + tclvareval("set tctx::", xctx->current_win_path, "_netlist Green", NULL); + } + } + + return; + } + if(key=='A' && rstate == ControlMask) /* only for graph (toggle hcursor1 if graph_use_ctrl_key set) */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + return; + } + if(key=='A' && rstate == 0) /* toggle show netlist */ + { + int net_s; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + net_s = tclgetboolvar("netlist_show"); + net_s = !net_s; + if(net_s) { + tcleval("alert_ { enabling show netlist window} {}"); + tclsetvar("netlist_show","1"); + } + else { + tcleval("alert_ { disabling show netlist window } {}"); + tclsetvar("netlist_show","0"); + } + return; + } + if(key=='>') { + if(xctx->semaphore >= 2) return; + if(xctx->draw_single_layer< cadlayers-1) xctx->draw_single_layer++; + draw(); + return; + } + if(key=='<') { + if(xctx->semaphore >= 2) return; + if(xctx->draw_single_layer>=0 ) xctx->draw_single_layer--; + draw(); + return; + } + if(key==':') /* toggle flat netlist (only spice) */ + { + if(!tclgetboolvar("flat_netlist")) { + tcleval("alert_ { enabling flat netlist} {}"); + tclsetvar("flat_netlist","1"); + } + else { + tcleval("alert_ { set hierarchical netlist } {}"); + tclsetvar("flat_netlist","0"); + } + return; + } + if(key=='B' && rstate == ControlMask) /* only for graph (toggle hcursor2 if graph_use_ctrl_key set) */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + return; + } + if(key=='B' && rstate == 0) /* edit schematic header/license */ + { + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + tcleval("update_schematic_header"); + } + if(key=='b' && rstate==0) /* merge schematic */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + merge_file(0, ""); /* 2nd parameter not used any more for merge 25122002 */ + return; + } + if(key=='b' && EQUAL_MODMASK) /* hide/show instance details */ + { + if(xctx->semaphore >= 2) return; + xctx->hide_symbols++; + if(xctx->hide_symbols >= 3) xctx->hide_symbols = 0; + tclsetintvar("hide_symbols", xctx->hide_symbols); + draw(); + return; + } + if(key=='d' && rstate == 0) /* unselect object under the mouse */ + { + if(infix_interface) { + unselect_at_mouse_pos(mx, my); + } else { + xctx->ui_state |= (MENUSTART | DESEL_CLICK); + xctx->ui_state2 = MENUSTARTDESEL; + } + return; + } + if(key=='D' && rstate == 0) /* unselect by area */ + { + if( !(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected && + !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !(xctx->ui_state & STARTSELECT)) { + if(infix_interface) { + xctx->mx_save = mx; xctx->my_save = my; + xctx->mx_double_save=xctx->mousex; + xctx->my_double_save=xctx->mousey; + xctx->ui_state |= DESEL_AREA; + } else { + xctx->ui_state |= MENUSTART; + xctx->ui_state2 = MENUSTARTDESEL; + } + } + return; + } + if(key=='d' && rstate == ControlMask) /* delete files */ + { + if(xctx->semaphore >= 2) return; + delete_files(); + return; + } + if(key=='x' && rstate == 0 ) /* new cad session */ + { + new_xschem_process(NULL ,0); + return; + } + if((key=='#') && !(state & ControlMask) ) + { + check_unique_names(0); + return; + } + if((key=='#') && (state & ControlMask) ) + { + check_unique_names(1); + return; + } + if( 0 && (key==';') && (state & ControlMask) ) /* testmode */ + { + return; + } + if(0 && key=='~' && (state & ControlMask)) { /* testmode */ + return; + } + if(0 && key=='|' && !(state & ControlMask)) { /* testmode */ + return; + } + if(0 && key=='|' && (state & ControlMask)) /* testmode */ + { + return; + } + + if(key=='f' && rstate == ControlMask) /* search */ + { + if(xctx->semaphore >= 2) return; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + tcleval("property_search"); + return; + } + if(key=='F' && rstate == ControlMask ) /* full zoom selection */ + { + if(xctx->ui_state == SELECTION) { + zoom_full(1, 1, 3, 0.97); + } + return; + } + if(key=='f' && rstate == 0 ) /* full zoom */ + { + int flags = 1; + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + if(tclgetboolvar("zoom_full_center")) flags |= 2; + zoom_full(1, 0, flags, 0.97); + return; + } + if((key=='z' && rstate==ControlMask)) /* zoom out */ + { + view_unzoom(0.0); + return; + } + if(key=='!' && !(state & ControlMask)) + { + if(xctx->semaphore >= 2) return; + break_wires_at_pins(0); + return; + } + if(key=='!' && (state & ControlMask)) + { + if(xctx->semaphore >= 2) return; + break_wires_at_pins(1); + return; + } + return; +} + +static void handle_button_press(int event, int state, int rstate, KeySym key, int button, int mx, int my, + 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); + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + /* terminate a schematic pan action */ + if(xctx->ui_state & STARTPAN) { + xctx->ui_state &=~STARTPAN; + return; + } + + /* 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; + sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); + if(sel.type) select_connected_nets(0); + } + /* moved to Button3 release */ + /* + * 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) { + zoom_rectangle(START);return; + } + + /* Mouse wheel events */ + else if(handle_mouse_wheel(event, mx, my, key, button, aux, state)) return; + + /* terminate wire placement in snap mode */ + else if(button==Button1 && (state & ShiftMask) && (xctx->ui_state & STARTWIRE) ) { + snapped_wire(c_snap); + } + /* Alt - Button1 click to unselect */ + else if(button==Button1 && (SET_MODMASK) ) { + unselect_at_mouse_pos(mx, my); + } + + /* 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 */ + tcleval(".dialog.f1.b1 invoke"); + return; + } else if(tcleval("winfo exists .dialog.txt")[0] == '1') { /* proc enter_text */ + tcleval(".dialog.buttons.ok invoke"); + return; + } else if(state==0 && tclgetvar("edit_symbol_prop_new_sel")[0]) { + tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke"); /* invoke 'OK' of edit prop dialog */ + } else if((state & ShiftMask) && tclgetvar("edit_symbol_prop_new_sel")[0]) { + select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); + tclsetvar("preserve_unchanged_attrs", "1"); + 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){ + 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; + + /* complete the pending STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */ + if(end_place_move_copy_zoom()) return; + + /* Button1Press to select objects */ + if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) { + Selected sel; + int already_selected = 0; + int prev_last_sel = xctx->lastsel; + int no_shift_no_ctrl = !(state & (ShiftMask | ControlMask)); + + xctx->shape_point_selected = 0; + xctx->mx_save = mx; xctx->my_save = my; + xctx->mx_double_save=xctx->mousex; + xctx->my_double_save=xctx->mousey; + + #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_wire(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) return; + if(add_wire_from_inst(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) return; + } + #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); + + /* 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) { + 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; + case LINE: if(xctx->line[sel.col][sel.n].sel) already_selected = 1; break; + case POLYGON: if(xctx->poly[sel.col][sel.n].sel) already_selected = 1; break; + case xRECT: if(xctx->rect[sel.col][sel.n].sel) already_selected = 1; break; + case ARC: if(xctx->arc[sel.col][sel.n].sel) already_selected = 1; break; + case ELEMENT: if(xctx->inst[sel.n].sel) already_selected = 1; break; + default: break; + } /*end switch */ + + /* Clicking and drag on an instance pin -> drag a new wire */ + if(xctx->intuitive_interface && !already_selected) { + if(add_wire_from_inst(&sel, xctx->mousex_snap, xctx->mousey_snap)) return; + } + + /* 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)) return; + } + + /* 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 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)) return; /* sets xctx->shape_point_selected */ + } + if(xctx->lastsel == 1 && xctx->intuitive_interface) { + int cond = already_selected; + + if(cond && xctx->sel_array[0].type==xRECT) { + if(edit_rect_point(state)) return; /* sets xctx->shape_point_selected */ + } + + if(cond && xctx->sel_array[0].type==LINE) { + if(edit_line_point(state)) return; /* sets xctx->shape_point_selected */ + } + + if(cond && xctx->sel_array[0].type==WIRE) { + if(edit_wire_point(state)) return; /* 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) { + /* enable_stretch (from TCL variable) reverses command if enabled: + * - move --> stretch move + * - stretch move (with ctrl key) --> move + */ + int stretch = (state & ControlMask ? 1 : 0) ^ enable_stretch; + xctx->drag_elements = 1; + /* select attached nets depending on ControlMask and enable_stretch */ + if(stretch) { + select_attached_nets(); /* stretch nets that land on selected instance pins */ + } + /* if dragging instances with stretch enabled and Shift down add wires to pins + * attached to something */ + if((state & ShiftMask) && stretch) { + 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 normal move */ + else move_objects(START,0,0,0); + } + + if(tclgetboolvar("auto_hilight") && !xctx->shape_point_selected) { + if(!(state & ShiftMask) && xctx->hilight_nets && sel.type == 0 ) { + if(!prev_last_sel) { + redraw_hilights(1); /* 1: clear all hilights, then draw */ + } + } + hilight_net(0); + if(xctx->lastsel) { + redraw_hilights(0); + } + } + return; + } + } /* button==Button1 */ + return; +} + +static void handle_button_release(int event, KeySym key, int state, int button, int mx, int my, + int aux, double c_snap, int enable_stretch, int draw_xhair, int snap_cursor, int wire_draw_active, char *str) +{ + if(waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } + xctx->ui_state &= ~DESEL_CLICK; + 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); + } + } + + /* launcher, no intuitive interface */ + if(!xctx->intuitive_interface && state == (Button1Mask | ControlMask) && + !xctx->shape_point_selected && xctx->mouse_moved == 0) { + int savesem = xctx->semaphore; + xctx->semaphore = 0; + launcher(); /* works only if lastsel == 1 */ + xctx->semaphore = savesem; + } + + /* launcher, intuitive_interface, only if no movement has been done */ + else if(xctx->intuitive_interface && state == (Button1Mask | ControlMask) && + !xctx->shape_point_selected && (xctx->ui_state & STARTMOVE) && xctx->mouse_moved == 0) { + int savesem = xctx->semaphore; + move_objects(ABORT, 0, 0.0, 0.0); + unselect_all(1); + select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); + rebuild_selected_array(); + xctx->semaphore = 0; + launcher(); /* works only if lastsel == 1 */ + 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 intuitive_interface copy or move */ + if(xctx->ui_state & STARTCOPY && xctx->drag_elements) { + copy_objects(END); + xctx->constr_mv=0; + tcleval("set constr_mv 0" ); + xctx->drag_elements = 0; + } + else if(xctx->ui_state & STARTMOVE && xctx->drag_elements) { + move_objects(END,0,0,0); + xctx->constr_mv=0; + tcleval("set constr_mv 0" ); + xctx->drag_elements = 0; + } + + /* if a polygon/bezier/rectangle control point was clicked, end point move operation + * and set polygon state back to SELECTED from SELECTED1 */ + else if((xctx->ui_state & (STARTMOVE | SELECTION)) && xctx->shape_point_selected) { + end_shape_point_edit(c_snap); + } + + if(xctx->ui_state & STARTPAN) { + xctx->ui_state &=~STARTPAN; + /* xctx->mx_save = mx; xctx->my_save = my; */ + /* xctx->mx_double_save=xctx->mousex_snap; */ + /* xctx->my_double_save=xctx->mousey_snap; */ + redraw_w_a_l_r_p_z_rubbers(1); + return; + } + dbg(1, "callback(): ButtonRelease ui_state=%d state=%d\n",xctx->ui_state,state); + if(xctx->semaphore >= 2) return; + if(xctx->ui_state & STARTSELECT) { + if(state & ControlMask) { + select_rect(!enable_stretch, END,-1); + } else { + /* Button1 release: end of rectangle select */ + if(!(state & (Button4Mask|Button5Mask) ) ) { + select_rect(enable_stretch, END,-1); + } + } + xctx->ui_state &= ~DESEL_AREA; + rebuild_selected_array(); + my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d path: %s", + xctx->mousex_snap, xctx->mousey_snap, xctx->lastsel, xctx->sch_path[xctx->currsch] ); + statusmsg(str,1); + } + + /* clear start from menu flag or infix_interface=0 start commands */ + if(xctx->ui_state & MENUSTART) { + xctx->ui_state &= ~MENUSTART; + return; + } + if(draw_xhair) draw_crosshair(3, state); /* restore crosshair when selecting / unselecting */ + if(snap_cursor && wire_draw_active) draw_snap_cursor(3); + return; +} + +static void handle_double_click(int event, int state, KeySym key, int button, + int mx, int my, int aux, int cadence_compat) +{ + if( waves_selected(event, key, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + return; + } else { + if(xctx->semaphore >= 2) return; + dbg(1, "callback(): DoubleClick ui_state=%d state=%d\n",xctx->ui_state,state); + if(button==Button1) { + Selected sel; + if(!xctx->lastsel && xctx->ui_state == 0) { + /* Following 5 lines do again a selection overriding lock, + * so locked instance attrs can be edited */ + sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 1, NULL); + if(sel.type) { + xctx->ui_state = SELECTION; + rebuild_selected_array(); + } + } + if(xctx->ui_state == 0 || xctx->ui_state == SELECTION) { + edit_property(0); + } else { + if(xctx->ui_state & STARTWIRE) { + redraw_w_a_l_r_p_z_rubbers(1); + start_wire(mx, my); + xctx->ui_state &= ~STARTWIRE; + } + if(xctx->ui_state & STARTLINE) { + xctx->ui_state &= ~STARTLINE; + } + if( (xctx->ui_state & STARTPOLYGON) && (state ==0 ) ) { + new_polygon(SET, xctx->mousex_snap, xctx->mousey_snap); + } + } + } + } +} + /* 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, ... */ @@ -2436,7 +4481,6 @@ int callback(const char *win_path, int event, int mx, int my, KeySym key, int button, int aux, int state) { char str[PATH_MAX + 100]; - struct stat buf; int redraw_only; double c_snap; #ifndef __unix__ @@ -2577,33 +4621,7 @@ int rstate; /* (reduced state, without ShiftMask) */ break; case EnterNotify: - dbg(2, "callback(): Enter event, ui_state=%d\n", xctx->ui_state); - xctx->mouse_inside = 1; - if(draw_xhair) { - if(crosshair_size == 0) { - tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL); - } - } else - tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL); - /* xschem window *sending* selected objects - when the pointer comes back in abort copy operation since it has been done - in another xschem xctx->window; STARTCOPY set and selection file does not exist any more */ - if(stat(sel_file, &buf) && (xctx->ui_state & STARTCOPY) ) - { - copy_objects(ABORT); - unselect_all(1); - } - /* xschem window *receiving* selected objects selection cleared --> abort */ - else if(xctx->paste_from == 1 && stat(sel_file, &buf) && (xctx->ui_state & STARTMERGE)) { - abort_operation(); - } - /*xschem window *receiving* selected objects - * no selected objects and selection file exists --> start merge */ - else if(xctx->lastsel == 0 && !stat(sel_file, &buf)) { - xctx->mousex_snap = 490; - xctx->mousey_snap = -340; - merge_file(1, ".sch"); - } + handle_enter_notify(draw_xhair, crosshair_size); break; case Expose: @@ -2635,2003 +4653,34 @@ int rstate; /* (reduced state, without ShiftMask) */ break; case MotionNotify: - if( waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - 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); - /* pan schematic */ - if(xctx->ui_state & STARTPAN) pan(RUBBER, mx, my); - - if(xctx->semaphore >= 2) { - if(draw_xhair) { - draw_crosshair(2, state); /* locked UI: draw new crosshair and break out */ - } - if(snap_cursor && wire_draw_active) draw_snap_cursor(2); - break; - } - - /* 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", - xctx->mousex_snap, xctx->mousey_snap, - xctx->lastsel , - xctx->mousex_snap-xctx->mx_double_save, xctx->mousey_snap-xctx->my_double_save - ); - statusmsg(str,1); - } - } - - /* determine direction of a rectangle selection (or unselection with ALT key) */ - if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & (PLACE_SYMBOL | STARTPAN | PLACE_TEXT)) ) { - /* Unselect by area : determine direction */ - if( ((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) { - if(mx >= xctx->mx_save) xctx->nl_dir = 0; - else xctx->nl_dir = 1; - 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(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 or zoom box */ - redraw_w_a_l_r_p_z_rubbers(0); - - /* 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) && - !(xctx->ui_state & STARTPAN) && !(SET_MODMASK) && !xctx->shape_point_selected && - !(state & ShiftMask) && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) - { - if(mx != xctx->mx_save || my != xctx->my_save) { - xctx->mouse_moved = 1; - if(!xctx->drag_elements) { - if( !(xctx->ui_state & STARTSELECT)) { - select_rect(enable_stretch, START,1); - xctx->onetime=1; - } - if(abs(mx-xctx->mx_save) > 8 || - abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ - if(xctx->onetime) { - unselect_all(1); /* 20171026 avoid multiple calls of unselect_all() */ - xctx->onetime=0; - } - xctx->ui_state|=STARTSELECT; /* set it again cause unselect_all(1) clears it... */ - } - } - } - } - /* Unselect by area */ - if( (((state & Button1Mask) && SET_MODMASK) || (xctx->ui_state & DESEL_AREA)) && - !(state & ShiftMask) && - !(xctx->ui_state & STARTPAN) && - !xctx->shape_point_selected && - !(xctx->ui_state & STARTSELECT) && - !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) { /* unselect area */ - select_rect(enable_stretch, START,0); - } - /* Select by area. Shift pressed */ - else if((state&Button1Mask) && (state & ShiftMask) && !(xctx->ui_state & STARTWIRE) && - !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !xctx->shape_point_selected && - !xctx->drag_elements && !(xctx->ui_state & STARTPAN) ) { - if(mx != xctx->mx_save || my != xctx->my_save) { - if( !(xctx->ui_state & STARTSELECT)) { - select_rect(enable_stretch, START,1); - } - if(abs(mx-xctx->mx_save) > 8 || - abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ - if(!xctx->already_selected) { - select_object(X_TO_XSCHEM(xctx->mx_save), - Y_TO_XSCHEM(xctx->my_save), 0, 0, NULL); /* remove near obj if dragging */ - } - rebuild_selected_array(); - } - } - } - if(draw_xhair) { - draw_crosshair(2, state); /* what = 2(draw) */ - } - if(snap_cursor && wire_draw_active) draw_snap_cursor(2); + handle_motion_notify(event, key, state, rstate, button, mx, my, + aux, draw_xhair, enable_stretch, + snap_cursor, wire_draw_active, str); break; case KeyRelease: break; case KeyPress: - if(key==' ') { - if(xctx->ui_state & STARTWIRE) { /* & instead of == 20190409 */ - new_wire(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap); - xctx->manhattan_lines++; - xctx->manhattan_lines %=3; - new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - - } else if(xctx->ui_state & STARTLINE) { - new_line(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap); - xctx->manhattan_lines++; - xctx->manhattan_lines %=3; - new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - } else { - if(xctx->semaphore<2) { - rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ - } - pan(START, mx, my); - xctx->ui_state |= STARTPAN; - } - break; - } - if(key == '_' ) /* toggle change line width */ - { - if(!tclgetboolvar("change_lw")) { - tcleval("alert_ { enabling change line width} {}"); - tclsetvar("change_lw","1"); - } - else { - tcleval("alert_ { disabling change line width} {}"); - tclsetvar("change_lw","0"); - } + handle_key_press(event, key, state, rstate, mx, my, button, aux, + infix_interface, enable_stretch, win_path, c_snap, + cadence_compat, wire_draw_active, snap_cursor, str); break; - } - if(key == 'b' && rstate==ControlMask) /* toggle show text in symbol */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->sym_txt =!xctx->sym_txt; - if(xctx->sym_txt) { - /* tcleval("alert_ { enabling text in symbol} {}"); */ - tclsetvar("sym_txt","1"); - draw(); - } - else { - /* tcleval("alert_ { disabling text in symbol} {}"); */ - tclsetvar("sym_txt","0"); - draw(); - } - break; - } - if(key == '%' ) /* toggle draw grid */ - { - int dr_gr; - dr_gr = tclgetboolvar("draw_grid"); - dr_gr =!dr_gr; - if(dr_gr) { - /* tcleval("alert_ { enabling draw grid} {}"); */ - tclsetvar("draw_grid","1"); - draw(); - } - else { - /* tcleval("alert_ { disabling draw grid} {}"); */ - tclsetvar("draw_grid","0"); - draw(); - } - break; - } - if(key == 'j' && rstate==0 ) /* print list of highlight nets */ - { - if(xctx->semaphore >= 2) break; - print_hilight_net(1); - break; - } - if(key == 'j' && rstate==ControlMask) /* create ipins from highlight nets */ - { - if(xctx->semaphore >= 2) break; - print_hilight_net(0); - break; - } - if(key == 'j' && EQUAL_MODMASK) /* create labels without i prefix from hilight nets */ - { - if(xctx->semaphore >= 2) break; - print_hilight_net(4); - break; - } - if(key == 'J' && SET_MODMASK ) /* create labels with i prefix from hilight nets */ - { - if(xctx->semaphore >= 2) break; - print_hilight_net(2); - break; - } - if(key == 'h' && rstate==ControlMask ) /* go to http link */ - { - int savesem = xctx->semaphore; - xctx->semaphore = 0; - launcher(); - xctx->semaphore = savesem; - break; - } - if(key == 'h' && EQUAL_MODMASK) /* create symbol pins from schematic pins 20171208 */ - { - tcleval("schpins_to_sympins"); - break; - } - if(key == 'h' && rstate == 0) { - /* horizontally constrained drag 20171023 */ - if ( xctx->constr_mv == 1 ) { - tcleval("set constr_mv 0" ); - xctx->constr_mv = 0; - } else { - tcleval("set constr_mv 1" ); - xctx->constr_mv = 1; - } - if(xctx->ui_state & STARTWIRE) { - if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; - if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; - new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - } - if(xctx->ui_state & STARTLINE) { - if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; - if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; - new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - } - break; - } - if(key=='H' && rstate == 0) { /* attach labels to selected instances */ - attach_labels_to_inst(1); - break; - } - if (key == 'H' && rstate == ControlMask) { /* create schematic and symbol from selected components */ - make_schematic_symbol_from_sel(); - break; - } - if(key == 'v' && rstate==0) { - /* vertically constrained drag 20171023 */ - if ( xctx->constr_mv == 2 ) { - tcleval("set constr_mv 0" ); - xctx->constr_mv = 0; - } else { - tcleval("set constr_mv 2" ); - xctx->constr_mv = 2; - } - if(xctx->ui_state & STARTWIRE) { - if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; - if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; - new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - } - if(xctx->ui_state & STARTLINE) { - if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save; - if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save; - new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap); - } - break; - } - if(key == 'j' && SET_MODMASK && (state & ControlMask) ) /* print list of highlight net with label expansion */ - { - print_hilight_net(3); - break; - } - if(key == 'J' && rstate == 0) { - create_plot_cmd(); - break; - } - if(key == '$' && rstate == 0 ) /* toggle pixmap saving */ - { - xctx->draw_pixmap =!xctx->draw_pixmap; - if(xctx->draw_pixmap) tcleval("alert_ { enabling draw pixmap} {}"); - else tcleval("alert_ { disabling draw pixmap} {}"); - break; - } - if(key == '$' && (state &ControlMask) ) /* toggle window drawing */ - { - xctx->draw_window =!xctx->draw_window; - if(xctx->draw_window) { - tcleval("alert_ { enabling draw window} {}"); - tclsetvar("draw_window","1"); - } else { - tcleval("alert_ { disabling draw window} {}"); - tclsetvar("draw_window","0"); - } - break; - } - if(key == '=' && (state &ControlMask)) /* toggle fill rectangles */ - { - int x; - xctx->fill_pattern++; - if(xctx->fill_pattern==3) xctx->fill_pattern=0; - - if(xctx->fill_pattern==1) { - tcleval("alert_ { Stippled pattern fill} {}"); - for(x=0;xfill_type[x]==1) XSetFillStyle(display,xctx->gcstipple[x],FillSolid); - else XSetFillStyle(display,xctx->gcstipple[x],FillStippled); - } - } - else if(xctx->fill_pattern==2) { - tcleval("alert_ { solid pattern fill} {}"); - for(x=0;xgcstipple[x],FillSolid); - } - else { - tcleval("alert_ { No pattern fill} {}"); - for(x=0;xgcstipple[x],FillStippled); - } - - draw(); - break; - } - if(key == '+' && state & ControlMask) /* change line width */ - { - xctx->lw = round_to_n_digits(xctx->lw + 0.5, 2); - change_linewidth(xctx->lw); - tclsetboolvar("change_lw", 0); - draw(); - break; - } - - if(key == '-' && state & ControlMask) /* change line width */ - { - xctx->lw = round_to_n_digits(xctx->lw - 0.5, 2); - if(xctx->lw < 0.0) xctx->lw = 0.0; - change_linewidth(xctx->lw); - tclsetboolvar("change_lw", 0); - draw(); - break; - } - if(key == 'X' && rstate == 0) /* highlight discrepanciens between selected instance pin and net names */ - { - hilight_net_pin_mismatches(); - break; - } - if(key== 'W' /* && !xctx->ui_state */ && rstate == 0 && !cadence_compat) { /* create wire snapping to closest instance pin (original keybind) */ - if(xctx->semaphore >= 2) break; - snapped_wire(c_snap); - break; - } - if(key== 's' /* && !xctx->ui_state */ && rstate == 0 && cadence_compat) { /* create wire snapping to closest instance pin (cadence keybind) */ - if(xctx->semaphore >= 2) break; - snapped_wire(c_snap); - break; - } - if(key == 'w' /* && !xctx->ui_state */ && rstate==0) /* place wire. */ - { - int prev_state = xctx->ui_state; - if(xctx->semaphore >= 2) break; - if(infix_interface) { - start_wire(xctx->mousex_snap, xctx->mousey_snap); - if(prev_state == STARTWIRE) { - tcleval("set constr_mv 0" ); - xctx->constr_mv=0; - } - } else { - xctx->last_command = 0; - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTWIRE; - if(prev_state & STARTWIRE) start_wire(xctx->mousex_snap, xctx->mousey_snap); - } - break; - } - if(key == XK_Return && (state == 0 ) && xctx->ui_state & STARTPOLYGON) { /* close polygon */ - new_polygon(ADD|END, xctx->mousex_snap, xctx->mousey_snap); - break; - } - if(key == XK_Escape) /* abort & redraw */ - { - if(xctx->semaphore < 2) { - abort_operation(); - } - /* stuff that can be done reentrantly ... */ - tclsetvar("tclstop", "1"); /* stop simulation if any running */ - if(xctx->ui_state2 & MENUSTARTWIRE) { - xctx->ui_state2 &= ~MENUSTARTWIRE; - } - if(tclgetboolvar("persistent_command") && (xctx->last_command & STARTWIRE) && cadence_compat) { - xctx->last_command &= ~STARTWIRE; - if(snap_cursor) draw_snap_cursor(1); - } - break; - } - if(key=='z' && rstate == 0 && - !(xctx->ui_state & (STARTRECT | STARTLINE | STARTWIRE | STARTPOLYGON | STARTARC))) /* zoom box */ - { - dbg(1, "callback(): zoom_rectangle call\n"); - zoom_rectangle(START);break; - } - if(key=='Z' && rstate == 0) /* zoom in */ - { - view_zoom(0.0); break; - } - if(key=='z' && EQUAL_MODMASK) /* toggle snap-cursor option */ - { - if(tclgetboolvar("snap_cursor")) { - tclsetvar("snap_cursor", "0"); - draw_snap_cursor(1); - xctx->closest_pin_found = 0; - xctx->prev_snapx = 0.0; - xctx->prev_snapy = 0.0; - } else { - tclsetvar("snap_cursor", "1"); - if(wire_draw_active) draw_snap_cursor(3); - } - } - if(key=='p' && EQUAL_MODMASK) /* add symbol pin */ - { - xctx->push_undo(); - unselect_all(1); - storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5, - xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout"); - xctx->need_reb_sel_arr=1; - rebuild_selected_array(); - move_objects(START,0,0,0); - xctx->ui_state |= START_SYMPIN; - break; - } - if(key=='p' && !(xctx->ui_state & STARTPOLYGON) && rstate==0) /* start polygon */ - { - if(xctx->semaphore >= 2) break; - dbg(1, "callback(): start polygon\n"); - if(infix_interface) { - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - xctx->last_command = 0; - new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTPOLYGON; - } - break; - } - if(key=='P' && rstate == 0) /* pan, other way to. */ - { - xctx->xorigin=-xctx->mousex_snap+xctx->areaw*xctx->zoom/2.0; - xctx->yorigin=-xctx->mousey_snap+xctx->areah*xctx->zoom/2.0; - draw(); - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key=='5' && rstate == 0) { /* 20110112 display only probes */ - xctx->only_probes = !xctx->only_probes; - tclsetboolvar("only_probes", xctx->only_probes); - toggle_only_probes(); - break; - } /* /20110112 */ - if(key<='9' && key >='0' && state==ControlMask) /* choose layer */ - { - char n[30]; - xctx->rectcolor = (int)key - '0'+4; - my_snprintf(n, S(n), "%d", xctx->rectcolor); - tclvareval("xschem set rectcolor ", n, NULL); - - if(has_x) { - if(!strcmp(win_path, ".drw")) { - tclvareval("reconfigure_layers_button {}", NULL); - } else { - tclvareval("reconfigure_layers_button [winfo parent ", win_path, "]", NULL); - } - } - dbg(1, "callback(): new color: %d\n",xctx->color_index[xctx->rectcolor]); - break; - } - if(key==XK_Delete && (xctx->ui_state & SELECTION) ) /* delete selection */ - { - if(xctx->semaphore >= 2) break; - delete(1/* to_push_undo */);break; - } - if(key==XK_Right && state == ControlMask) { - int save = xctx->semaphore; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - if(xctx->semaphore >= 2) break; - xctx->semaphore = 0; - tcleval("next_tab"); - xctx->semaphore = save; - break; - } - if(key==XK_Left && state == ControlMask) { - int save = xctx->semaphore; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - if(xctx->semaphore >= 2) break; - xctx->semaphore = 0; - tcleval("prev_tab"); - xctx->semaphore = save; - break; - } - if(key==XK_Right && !(state & ControlMask)) /* left */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->xorigin+=-CADMOVESTEP*xctx->zoom; - draw(); - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key==XK_Left && !(state & ControlMask)) /* right */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->xorigin-=-CADMOVESTEP*xctx->zoom; - draw(); - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key==XK_Down) /* down */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->yorigin+=-CADMOVESTEP*xctx->zoom; - draw(); - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key==XK_Up) /* up */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->yorigin-=-CADMOVESTEP*xctx->zoom; - draw(); - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key=='w' && rstate == ControlMask) /* close current schematic */ - { - int save_sem; - if(xctx->semaphore >= 2) break; - save_sem = xctx->semaphore; - tcleval("xschem exit"); - xctx->semaphore = save_sem; - break; - } - /* toggle spice_ignore, verilog_ignore, ... flag on selected instances. */ - if(key == 'T' && rstate == 0) { - toggle_ignore(); - } - if(key=='t' && rstate == 0) /* place text */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - if(xctx->semaphore >= 2) break; - xctx->last_command = 0; - xctx->mx_double_save = xctx->mousex_snap; - xctx->my_double_save = xctx->mousey_snap; - if(place_text(0, xctx->mousex_snap, xctx->mousey_snap)) { /* 1 = draw text 24122002 */ - xctx->mousey_snap = xctx->my_double_save; - xctx->mousex_snap = xctx->mx_double_save; - move_objects(START,0,0,0); - xctx->ui_state |= PLACE_TEXT; - } - break; - } - if(key=='t' && (rstate & ControlMask)) - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - break; - } - if(key=='r' /* && !xctx->ui_state */ && rstate==0) /* start rect */ - { - dbg(1, "callback(): start rect\n"); - if(xctx->semaphore >= 2) break; - if(infix_interface) { - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - xctx->last_command = 0; - new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTRECT; - } - break; - } - if(key=='V' && rstate == ControlMask) /* toggle spice/vhdl netlist */ - { - xctx->netlist_type++; if(xctx->netlist_type==6) xctx->netlist_type=1; - set_tcl_netlist_type(); - draw(); /* needed to ungrey or grey out components due to *_ignore attribute */ - break; - } - if((key=='s' && rstate == 0) && !cadence_compat) /* simulate (original keybind) */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " - "-message {Run circuit simulation?}"); - if(strcmp(tclresult(),"ok")==0) { - tcleval("[xschem get top_path].menubar invoke Simulate"); - } - break; - } - if((key=='r' && rstate == ControlMask) && cadence_compat) /* simulate (for cadence users) */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " - "-message {Run circuit simulation?}"); - if(strcmp(tclresult(),"ok")==0) { - tcleval("[xschem get top_path].menubar invoke Simulate"); - } - break; - } - if(key=='s' && rstate == ControlMask ) /* save 20121201 */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - /* check if unnamed schematic, use saveas in this case */ - if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) { - saveas(NULL, SCHEMATIC); - } else { - save(1, 0); - } - break; - } - if(key=='s' && SET_MODMASK && (state & ControlMask) ) /* save as symbol */ - { - if(xctx->semaphore >= 2) break; - saveas(NULL, SYMBOL); - break; - } - if(key=='S' && rstate == ControlMask) /* save as schematic */ - { - if(xctx->semaphore >= 2) break; - saveas(NULL, SCHEMATIC); - break; - } - if(key=='e' && rstate == 0) /* descend to schematic */ - { - if(xctx->semaphore >= 2) break; - descend_schematic(0, 1, 1, 1);break; - } - if(key=='e' && EQUAL_MODMASK) /* edit schematic in new window */ - { - int save = xctx->semaphore; - xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ - /* schematic_in_new_window(0, 1, 0); */ - tcleval("open_sub_schematic"); - xctx->semaphore = save; - break; - } - - if(key=='E' && EQUAL_MODMASK) /* edit schematic in new window - new xschem process */ - { - int save = xctx->semaphore; - xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ - schematic_in_new_window(1, 1, 0); - xctx->semaphore = save; - break; - } - - if(key=='i' && EQUAL_MODMASK) /* edit symbol in new window */ - { - int save = xctx->semaphore; - xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ - symbol_in_new_window(0); - xctx->semaphore = save; - break; - } - - if(key=='I' && EQUAL_MODMASK) /* edit symbol in new window - new xschem process */ - { - int save = xctx->semaphore; - xctx->semaphore--; /* so semaphore for current context wll be saved correctly */ - symbol_in_new_window(1); - xctx->semaphore = save; - break; - } - - - if( (key=='e' && rstate == ControlMask) || (key==XK_BackSpace)) /* back */ - { - if(xctx->semaphore >= 2) break; - go_back(1);break; - } - - if(key=='a' && rstate == 0) /* make symbol */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " - "-message {do you want to make symbol view ?}"); - if(strcmp(tclresult(),"ok")==0) - { - save_schematic(xctx->sch[xctx->currsch], 0); - make_symbol(); - } - break; - } - if(key=='a' && rstate == ControlMask) /* select all */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - select_all(); - break; - } - if(key=='y' && rstate == 0) /* toggle stretching */ - { - enable_stretch = !enable_stretch; - tclsetboolvar("enable_stretch", enable_stretch); - break; - } - if(key=='x' && EQUAL_MODMASK) /* toggle draw crosshair at mouse pos */ - { - if(tclgetboolvar("draw_crosshair")) { - tclsetvar("draw_crosshair", "0"); - } else { - tclsetvar("draw_crosshair", "1"); - } - draw(); - } - if(key=='x' && rstate == ControlMask) /* cut selection into clipboard */ - { - if(xctx->semaphore >= 2) break; - rebuild_selected_array(); - if(xctx->lastsel) { /* 20071203 check if something selected */ - save_selection(2); - delete(1/* to_push_undo */); - } - break; - } - if(key=='c' && rstate == ControlMask) /* copy selection into clipboard */ - { - if(xctx->semaphore >= 2) break; - rebuild_selected_array(); - if(xctx->lastsel) { /* 20071203 check if something selected */ - save_selection(2); - } - break; - } - if(key=='C' /* && !xctx->ui_state */ && rstate == 0) /* place arc */ - { - if(xctx->semaphore >= 2) break; - if(infix_interface) { - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - xctx->last_command = 0; - new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTARC; - } - break; - } - if(key=='C' /* && !xctx->ui_state */ && rstate == ControlMask) /* place circle */ - { - if(xctx->semaphore >= 2) break; - if(infix_interface) { - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - xctx->last_command = 0; - new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTCIRCLE; - } - break; - } - if(key=='O' && rstate == ControlMask ) /* load most recent tile */ - { - tclvareval("xschem load -gui [lindex $recentfile 0]", NULL); - break; - } - if(key=='O' && rstate == 0) /* toggle light/dark colorscheme 20171113 */ - { - int d_c; - d_c = tclgetboolvar("dark_colorscheme"); - d_c = !d_c; - tclsetboolvar("dark_colorscheme", d_c); - tclsetdoublevar("dim_value", 0.0); - tclsetdoublevar("dim_bg", 0.0); - build_colors(0.0, 0.0); - draw(); - break; - } - if(key=='v' && rstate == ControlMask) /* paste from clipboard */ - { - if(xctx->semaphore >= 2) break; - merge_file(2,".sch"); - break; - } - if(key=='Q' && rstate == ControlMask ) /* view attributes */ - { - edit_property(2);break; - } - if(key=='q' && rstate==ControlMask) /* quit xschem */ - { - if(xctx->semaphore >= 2) break; - /* must be set to zero, otherwise switch_tab/switch_win does not proceed - * and these are necessary when closing tabs/windows */ - xctx->semaphore = 0; - tcleval("quit_xschem"); - break; - } - if(key=='q' && rstate==0) /* edit attributes */ - { - if(xctx->semaphore >= 2) break; - edit_property(0); - break; - } - if(key=='q' && EQUAL_MODMASK) /* edit .sch file (DANGER!!) */ - { - if(xctx->semaphore >= 2) break; - rebuild_selected_array(); - if(xctx->lastsel==0 ) { - my_snprintf(str, S(str), "edit_file {%s}", abs_sym_path(xctx->sch[xctx->currsch], "")); - tcleval(str); - } - else if(xctx->sel_array[0].type==ELEMENT) { - my_snprintf(str, S(str), "edit_file {%s}", - abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), "")); - tcleval(str); - - } - break; - } - #if defined(__unix__) && HAS_CAIRO==1 - if(key == XK_Print) { - xctx->ui_state |= GRABSCREEN; - tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL); - tclvareval("grab set -global ", xctx->top_path, ".drw", NULL); - break; - } - #endif - if(key=='Q' && rstate == 0) /* edit attributes in editor */ - { - if(xctx->semaphore >= 2) break; - edit_property(1);break; - } - if(key=='i' && rstate==0) /* descend to symbol */ - { - if(xctx->semaphore >= 2) break; - descend_symbol();break; - } - if((key==XK_Insert && state == ShiftMask) || (key == 'i' && rstate == ControlMask)) /* insert sym */ - { - tcleval("load_file_dialog {Insert symbol} *.\\{sym,tcl\\} INITIALINSTDIR 2"); - break; - } - if((key==XK_Insert) || (key == 'I' && rstate == 0) ) /* insert sym */ - { - if(xctx->semaphore >= 2) break; - start_place_symbol(); - - break; - } - if(key=='s' && SET_MODMASK) /* reload */ - { - if(xctx->semaphore >= 2) break; - tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] " - "-message {Are you sure you want to reload from disk?}"); - if(strcmp(tclresult(),"ok")==0) { - char filename[PATH_MAX]; - unselect_all(1); - remove_symbols(); - my_strncpy(filename, abs_sym_path(xctx->sch[xctx->currsch], ""), S(filename)); - load_schematic(1, filename, 1, 1); - draw(); - } - break; - } - if(key=='o' && rstate == ControlMask) /* load */ - { - if(xctx->semaphore >= 2) break; - ask_new_file(); - break; - } - if(key=='S' && rstate == 0) /* change element order */ - { - if(xctx->semaphore >= 2) break; - change_elem_order(-1); - break; - } - if(key=='k' && EQUAL_MODMASK) /* select whole net (all attached wires/labels/pins) */ - { - select_hilight_net(); - break; - } - if(key=='k' && rstate==ControlMask) /* unhilight net */ - { - if(xctx->semaphore >= 2) break; - unhilight_net(); - break; - } - if(key=='K' && rstate == ControlMask) /* hilight net drilling thru elements */ - /* with 'propag=' prop set on pins */ - { - if(xctx->semaphore >= 2) break; - xctx->enable_drill=1; - hilight_net(0); - redraw_hilights(0); - /* draw_hilight_net(1); */ - break; - } - if(key=='k' && rstate==0) /* hilight net */ - { - if(xctx->semaphore >= 2) break; - xctx->enable_drill=0; - hilight_net(0); - redraw_hilights(0); - /* draw_hilight_net(1); */ - break; - } - if(key=='K' && rstate == 0) /* delete hilighted nets */ - { - if(xctx->semaphore >= 2) break; - xctx->enable_drill=0; - clear_all_hilights(); - /* undraw_hilight_net(1); */ - draw(); - break; - } - if(key=='g' && EQUAL_MODMASK) { /* highlight net and send to viewer */ - int tool = 0; - int exists = 0; - char *tool_name = NULL; - char str[200]; - - if(xctx->semaphore >= 2) break; - tcleval("winfo exists .graphdialog"); - if(tclresult()[0] == '1') tool = XSCHEM_GRAPH; - else if(xctx->graph_lastsel >=0 && - xctx->rects[GRIDLAYER] > xctx->graph_lastsel && - xctx->rect[GRIDLAYER][xctx->graph_lastsel].flags & 1) { - tool = XSCHEM_GRAPH; - } - tcleval("info exists sim"); - if(tclresult()[0] == '1') exists = 1; - xctx->enable_drill = 0; - if(exists) { - if(!tool) { - tool = tclgetintvar("sim(spicewave,default)"); - my_snprintf(str, S(str), "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; - else if(strstr(tool_name, "Bespice")) tool=BESPICE; - my_free(_ALLOC_ID_, &tool_name); - } - } - if(tool) { - hilight_net(tool); - redraw_hilights(0); - } - Tcl_ResetResult(interp); - break; - } - if(key=='g' && rstate==0) /* half snap factor */ - { - set_snap(c_snap / 2.0); - change_linewidth(-1.); - draw(); - break; - } - if(key=='g' && rstate==ControlMask) /* set snap factor 20161212 */ - { - 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); - break; - } - if(key=='G' && rstate == 0) /* double snap factor */ - { - set_snap(c_snap * 2.0); - change_linewidth(-1.); - draw(); - break; - } - if(key=='*' && EQUAL_MODMASK) /* svg print , 20121108 */ - { - if(xctx->semaphore >= 2) break; - svg_draw(); - break; - } - if(key=='*' && rstate == 0 ) /* postscript print */ - { - if(xctx->semaphore >= 2) break; - ps_draw(7, 0, 0); - break; - } - if(key=='*' && rstate == ControlMask) /* xpm print */ - { - if(xctx->semaphore >= 2) break; - print_image(); - break; - } - if(key=='u' && EQUAL_MODMASK) /* align to grid */ - { - if(xctx->semaphore >= 2) break; - xctx->push_undo(); - round_schematic_to_grid(c_snap); - set_modify(1); - if(tclgetboolvar("autotrim_wires")) trim_wires(); - xctx->prep_hash_inst=0; - xctx->prep_hash_wires=0; - xctx->prep_net_structs=0; - xctx->prep_hi_structs=0; - - draw(); - break; - } - if(0 && (key=='u') && rstate==ControlMask) /* testmode */ - { - static int x = 0; - - if(x == 0) { - int i; - XFillRectangle(display, xctx->window, xctx->gc[BACKLAYER], xctx->areax1, xctx->areay1, - xctx->areaw, xctx->areah); - XFlush(display); - sleep_ms(400); - for(i = xctx->xrect[0].x; i < xctx->xrect[0].width; i++) { - XDrawLine(display, xctx->window, xctx->gctiled, - i, xctx->xrect[0].y, i, xctx->xrect[0].height); - XFlush(display); - sleep_ms(4); - } - } else if(x == 1) { - int i; - XFillRectangle(display, xctx->window, xctx->gc[BACKLAYER], xctx->areax1, xctx->areay1, - xctx->areaw, xctx->areah); - XFlush(display); - sleep_ms(400); - for(i = xctx->xrect[0].x; i < xctx->xrect[0].width; i++) { - XDrawLine(display, xctx->window, xctx->gctiled, - i, xctx->xrect[0].y, i+1, xctx->xrect[0].height); - XFlush(display); - sleep_ms(4); - } - } - x++; - x %= 2; - break; - } - if(key=='u' && rstate==0) /* undo */ - { - if(xctx->semaphore >= 2) break; - xctx->pop_undo(0, 1); /* 2nd parameter: set_modify_status */ - draw(); - break; - } - if(key=='U' && rstate == 0) /* redo */ - { - if(xctx->semaphore >= 2) break; - xctx->pop_undo(1, 1); /* 2nd parameter: set_modify_status */ - draw(); - break; - } - if(key=='&') /* check wire connectivity */ - { - if(xctx->semaphore >= 2) break; - xctx->push_undo(); - trim_wires(); - draw(); - break; - } - if(key=='l' && rstate == ControlMask) { /* create schematic from selected symbol 20171004 */ - if(xctx->semaphore >= 2) break; - create_sch_from_sym(); - break; - } - if(key=='l' /* && !xctx->ui_state */ && rstate == 0) /* start line */ - { - int prev_state = xctx->ui_state; - if(xctx->semaphore >= 2) break; - if(infix_interface) { - start_line(xctx->mousex_snap, xctx->mousey_snap); - if(prev_state == STARTLINE) { - tcleval("set constr_mv 0" ); - xctx->constr_mv=0; - } - } else { - xctx->last_command = 0; - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTLINE; - } - break; - } - if(key=='l' && EQUAL_MODMASK) { /* add pin label*/ - place_net_label(1); - break; - } - if(key >= '0' && key <= '4' && state == 0) { /* toggle pin logic level */ - if(xctx->semaphore >= 2) break; - if(key == '4') logic_set(-1, 1, NULL); - else logic_set((int)key - '0', 1, NULL); - break; - } - if(key=='L' && EQUAL_MODMASK ) { /* add pin label*/ - place_net_label(0); - break; - } - if(key=='L' && rstate == 0) { /* toggle orthogonal routing */ - if(tclgetboolvar("orthogonal_wiring")){ - tclsetboolvar("orthogonal_wiring", 0); - xctx->manhattan_lines = 0; - } else { - tclsetboolvar("orthogonal_wiring", 1); - } - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - if(key=='F' && rstate == 0) /* flip */ - { - if(xctx->ui_state & STARTMOVE) move_objects(FLIP,0,0,0); - else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP); - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(FLIP,0,0,0); - move_objects(END,0,0,0); - } - break; - } - if(key=='V' && rstate == 0) /* vertical flip */ - { - if(xctx->ui_state & STARTMOVE) { - move_objects(ROTATE,0,0,0); - move_objects(ROTATE,0,0,0); - move_objects(FLIP,0,0,0); - } - else if(xctx->ui_state & STARTCOPY) { - copy_objects(ROTATE); - copy_objects(ROTATE); - copy_objects(FLIP); - } - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(ROTATE,0,0,0); - move_objects(ROTATE,0,0,0); - move_objects(FLIP,0,0,0); - move_objects(END,0,0,0); - } - break; - } - if(key=='v' && EQUAL_MODMASK) /* vertical flip objects around their anchor points */ - { - if(xctx->ui_state & STARTMOVE) { - move_objects(ROTATE|ROTATELOCAL,0,0,0); - move_objects(ROTATE|ROTATELOCAL,0,0,0); - move_objects(FLIP|ROTATELOCAL,0,0,0); - } - else if(xctx->ui_state & STARTCOPY) { - copy_objects(ROTATE|ROTATELOCAL); - copy_objects(ROTATE|ROTATELOCAL); - copy_objects(FLIP|ROTATELOCAL); - } - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(ROTATE|ROTATELOCAL,0,0,0); - move_objects(ROTATE|ROTATELOCAL,0,0,0); - move_objects(FLIP|ROTATELOCAL,0,0,0); - move_objects(END,0,0,0); - } - break; - } - - if(key=='\\' && state==0) /* fullscreen */ - { - - dbg(1, "callback(): toggle fullscreen, win_path=%s\n", win_path); - toggle_fullscreen(win_path); - break; - } - if(key=='f' && EQUAL_MODMASK) /* flip objects around their anchor points 20171208 */ - { - if(xctx->ui_state & STARTMOVE) move_objects(FLIP|ROTATELOCAL,0,0,0); - else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP|ROTATELOCAL); - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(FLIP|ROTATELOCAL,0,0,0); - move_objects(END,0,0,0); - } - break; - } - if(key=='R' && rstate == 0) /* rotate */ - { - if(xctx->ui_state & STARTMOVE) move_objects(ROTATE,0,0,0); - else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE); - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(ROTATE,0,0,0); - move_objects(END,0,0,0); - } - - break; - } - if(key=='r' && EQUAL_MODMASK) /* rotate objects around their anchor points 20171208 */ - { - if(xctx->ui_state & STARTMOVE) move_objects(ROTATE|ROTATELOCAL,0,0,0); - else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE|ROTATELOCAL); - else { - rebuild_selected_array(); - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - move_objects(ROTATE|ROTATELOCAL,0,0,0); - move_objects(END,0,0,0); - } - break; - } - /* Move selection */ - if(key=='m' && rstate==0 && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - 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; - move_objects(START,0,0,0); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTMOVE; - } - break; - } - /* Move selection adding wires to moved pins */ - if(((key == 'M' && rstate == 0) || (key == 'm' && EQUAL_MODMASK)) && - !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - 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; - xctx->my_double_save=xctx->mousey_snap; - /* select_attached_nets(); */ /* stretch nets that land on selected instance pins */ - move_objects(START,0,0,0); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTMOVE; - } - break; - } - /* move selection stretching attached nets */ - if(key=='m' && rstate == ControlMask && - !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - 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; - move_objects(START,0,0,0); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTMOVE; - } - break; - } - - /* move selection, stretch attached nets, create new wires on pin-to-moved-pin connections */ - if(key=='M' && rstate == ControlMask && - !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - 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; - xctx->my_double_save=xctx->mousey_snap; - move_objects(START,0,0,0); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTMOVE; - } - break; - } - - if(key=='c' && EQUAL_MODMASK && /* duplicate selection */ - !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - if(xctx->semaphore >= 2) break; - 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; - xctx->my_double_save=xctx->mousey_snap; - copy_objects(START); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTCOPY; - } - break; - } - - if(key=='c' && rstate==0 && /* duplicate selection */ - !(xctx->ui_state & (STARTMOVE | STARTCOPY))) - { - if(xctx->semaphore >= 2) break; - if(infix_interface) { - xctx->mx_double_save=xctx->mousex_snap; - xctx->my_double_save=xctx->mousey_snap; - copy_objects(START); - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTCOPY; - } - break; - } - if(key=='n' && rstate == ControlMask) /* clear schematic */ - { - if(xctx->semaphore >= 2) break; - tcleval("xschem clear SCHEMATIC"); - break; - } - if(key=='N' && rstate == ControlMask ) /* clear symbol */ - { - if(xctx->semaphore >= 2) break; - tcleval("xschem clear SYMBOL"); - break; - } - if(key=='n' && rstate==0) /* hierarchical netlist */ - { - if(xctx->semaphore >= 2) break; - tcleval("xschem netlist -erc"); - break; - } - if(key=='N' && rstate == 0) /* current level only netlist */ - { - int err = 0; - yyparse_error = 0; - if(xctx->semaphore >= 2) break; - unselect_all(1); - if( set_netlist_dir(0, NULL) ) { - dbg(1, "callback(): -------------\n"); - if(xctx->netlist_type == CAD_SPICE_NETLIST) - err = global_spice_netlist(0, 1); - else if(xctx->netlist_type == CAD_VHDL_NETLIST) - err = global_vhdl_netlist(0, 1); - else if(xctx->netlist_type == CAD_VERILOG_NETLIST) - err = global_verilog_netlist(0, 1); - else if(xctx->netlist_type == CAD_TEDAX_NETLIST) - err = global_tedax_netlist(0, 1); - else - tcleval("tk_messageBox -type ok -parent [xschem get topwindow] " - "-message {Please Set netlisting mode (Options menu)}"); - dbg(1, "callback(): -------------\n"); - } - else { - if(has_x) tcleval("alert_ {Can not write into the netlist directory. Please check} {}"); - else dbg(0, "Can not write into the netlist directory. Please check"); - err = 1; - } - if(err) { - if(has_x) { - tclvareval(xctx->top_path, ".menubar entryconfigure Netlist -background red", NULL); - tclvareval("set tctx::", xctx->current_win_path, "_netlist red", NULL); - } - } else { - if(has_x) { - tclvareval(xctx->top_path, ".menubar entryconfigure Netlist -background Green", NULL); - tclvareval("set tctx::", xctx->current_win_path, "_netlist Green", NULL); - } - } - - break; - } - if(key=='A' && rstate == ControlMask) /* only for graph (toggle hcursor1 if graph_use_ctrl_key set) */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - break; - } - if(key=='A' && rstate == 0) /* toggle show netlist */ - { - int net_s; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - net_s = tclgetboolvar("netlist_show"); - net_s = !net_s; - if(net_s) { - tcleval("alert_ { enabling show netlist window} {}"); - tclsetvar("netlist_show","1"); - } - else { - tcleval("alert_ { disabling show netlist window } {}"); - tclsetvar("netlist_show","0"); - } - break; - } - if(key=='>') { - if(xctx->semaphore >= 2) break; - if(xctx->draw_single_layer< cadlayers-1) xctx->draw_single_layer++; - draw(); - break; - } - if(key=='<') { - if(xctx->semaphore >= 2) break; - if(xctx->draw_single_layer>=0 ) xctx->draw_single_layer--; - draw(); - break; - } - if(key==':') /* toggle flat netlist (only spice) */ - { - if(!tclgetboolvar("flat_netlist")) { - tcleval("alert_ { enabling flat netlist} {}"); - tclsetvar("flat_netlist","1"); - } - else { - tcleval("alert_ { set hierarchical netlist } {}"); - tclsetvar("flat_netlist","0"); - } - break; - } - if(key=='B' && rstate == ControlMask) /* only for graph (toggle hcursor2 if graph_use_ctrl_key set) */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - break; - } - if(key=='B' && rstate == 0) /* edit schematic header/license */ - { - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - tcleval("update_schematic_header"); - } - if(key=='b' && rstate==0) /* merge schematic */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - merge_file(0, ""); /* 2nd parameter not used any more for merge 25122002 */ - break; - } - if(key=='b' && EQUAL_MODMASK) /* hide/show instance details */ - { - if(xctx->semaphore >= 2) break; - xctx->hide_symbols++; - if(xctx->hide_symbols >= 3) xctx->hide_symbols = 0; - tclsetintvar("hide_symbols", xctx->hide_symbols); - draw(); - break; - } - if(key=='d' && rstate == 0) /* unselect object under the mouse */ - { - if(infix_interface) { - unselect_at_mouse_pos(mx, my); - } else { - xctx->ui_state |= (MENUSTART | DESEL_CLICK); - xctx->ui_state2 = MENUSTARTDESEL; - } - break; - } - if(key=='D' && rstate == 0) /* unselect by area */ - { - if( !(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected && - !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !(xctx->ui_state & STARTSELECT)) { - if(infix_interface) { - xctx->mx_save = mx; xctx->my_save = my; - xctx->mx_double_save=xctx->mousex; - xctx->my_double_save=xctx->mousey; - xctx->ui_state |= DESEL_AREA; - } else { - xctx->ui_state |= MENUSTART; - xctx->ui_state2 = MENUSTARTDESEL; - } - } - break; - } - if(key=='d' && rstate == ControlMask) /* delete files */ - { - if(xctx->semaphore >= 2) break; - delete_files(); - break; - } - if(key=='x' && rstate == 0 ) /* new cad session */ - { - new_xschem_process(NULL ,0); - break; - } - if((key=='#') && !(state & ControlMask) ) - { - check_unique_names(0); - break; - } - if((key=='#') && (state & ControlMask) ) - { - check_unique_names(1); - break; - } - if( 0 && (key==';') && (state & ControlMask) ) /* testmode */ - { - break; - } - if(0 && key=='~' && (state & ControlMask)) { /* testmode */ - break; - } - if(0 && key=='|' && !(state & ControlMask)) { /* testmode */ - break; - } - if(0 && key=='|' && (state & ControlMask)) /* testmode */ - { - break; - } - - if(key=='f' && rstate == ControlMask) /* search */ - { - if(xctx->semaphore >= 2) break; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - tcleval("property_search"); - break; - } - if(key=='F' && rstate == ControlMask ) /* full zoom selection */ - { - if(xctx->ui_state == SELECTION) { - zoom_full(1, 1, 3, 0.97); - } - break; - } - if(key=='f' && rstate == 0 ) /* full zoom */ - { - int flags = 1; - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - if(tclgetboolvar("zoom_full_center")) flags |= 2; - zoom_full(1, 0, flags, 0.97); - break; - } - if((key=='z' && rstate==ControlMask)) /* zoom out */ - { - view_unzoom(0.0); - break; - } - if(key=='!' && !(state & ControlMask)) - { - if(xctx->semaphore >= 2) break; - break_wires_at_pins(0); - break; - } - if(key=='!' && (state & ControlMask)) - { - if(xctx->semaphore >= 2) break; - break_wires_at_pins(1); - break; - } - break; 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; - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); - if(sel.type) select_connected_nets(0); - } - /* moved to Button3 release */ - /* - * 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) { - zoom_rectangle(START);break; - } - - /* Mouse wheel events */ - else if(handle_mouse_wheel(event, mx, my, key, button, aux, state)) break; - - /* terminate wire placement in snap mode */ - else if(button==Button1 && (state & ShiftMask) && (xctx->ui_state & STARTWIRE) ) { - snapped_wire(c_snap); - } - /* Alt - Button1 click to unselect */ - else if(button==Button1 && (SET_MODMASK) ) { - unselect_at_mouse_pos(mx, my); - } - - /* 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 */ - tcleval(".dialog.f1.b1 invoke"); - break; - } else if(tcleval("winfo exists .dialog.txt")[0] == '1') { /* proc enter_text */ - tcleval(".dialog.buttons.ok invoke"); - break; - } else if(state==0 && tclgetvar("edit_symbol_prop_new_sel")[0]) { - tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke"); /* invoke 'OK' of edit prop dialog */ - } else if((state & ShiftMask) && tclgetvar("edit_symbol_prop_new_sel")[0]) { - select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); - tclsetvar("preserve_unchanged_attrs", "1"); - 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){ - 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); - } - break; - } - /* handle all object insertions started from Tools/Edit menu */ - if(check_menu_start_commands(c_snap, mx, my)) break; - - /* complete the pending STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */ - if(end_place_move_copy_zoom()) break; - - /* Button1Press to select objects */ - if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) { - Selected sel; - int already_selected = 0; - int prev_last_sel = xctx->lastsel; - int no_shift_no_ctrl = !(state & (ShiftMask | ControlMask)); - - xctx->shape_point_selected = 0; - xctx->mx_save = mx; xctx->my_save = my; - xctx->mx_double_save=xctx->mousex; - xctx->my_double_save=xctx->mousey; - - #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_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); - - /* 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) { - 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; - case LINE: if(xctx->line[sel.col][sel.n].sel) already_selected = 1; break; - case POLYGON: if(xctx->poly[sel.col][sel.n].sel) already_selected = 1; break; - case xRECT: if(xctx->rect[sel.col][sel.n].sel) already_selected = 1; break; - case ARC: if(xctx->arc[sel.col][sel.n].sel) already_selected = 1; break; - case ELEMENT: if(xctx->inst[sel.n].sel) already_selected = 1; break; - default: break; - } /*end switch */ - - /* Clicking and drag on an instance pin -> drag a new wire */ - if(xctx->intuitive_interface && !already_selected) { - 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 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(cond && xctx->sel_array[0].type==xRECT) { - if(edit_rect_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(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) { - /* enable_stretch (from TCL variable) reverses command if enabled: - * - move --> stretch move - * - stretch move (with ctrl key) --> move - */ - int stretch = (state & ControlMask ? 1 : 0) ^ enable_stretch; - xctx->drag_elements = 1; - /* select attached nets depending on ControlMask and enable_stretch */ - if(stretch) { - select_attached_nets(); /* stretch nets that land on selected instance pins */ - } - /* if dragging instances with stretch enabled and Shift down add wires to pins - * attached to something */ - if((state & ShiftMask) && stretch) { - 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 normal move */ - else move_objects(START,0,0,0); - } - - if(tclgetboolvar("auto_hilight") && !xctx->shape_point_selected) { - if(!(state & ShiftMask) && xctx->hilight_nets && sel.type == 0 ) { - if(!prev_last_sel) { - redraw_hilights(1); /* 1: clear all hilights, then draw */ - } - } - hilight_net(0); - if(xctx->lastsel) { - redraw_hilights(0); - } - } - break; - } - } /* button==Button1 */ - break; + handle_button_press(event, state, rstate, key, button, mx, my, + c_snap, draw_xhair, crosshair_size, enable_stretch, aux); + break; case ButtonRelease: - if(waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } - xctx->ui_state &= ~DESEL_CLICK; - 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); - } - } - - /* launcher, no intuitive interface */ - if(!xctx->intuitive_interface && state == (Button1Mask | ControlMask) && - !xctx->shape_point_selected && xctx->mouse_moved == 0) { - int savesem = xctx->semaphore; - xctx->semaphore = 0; - launcher(); /* works only if lastsel == 1 */ - xctx->semaphore = savesem; - } - - /* launcher, intuitive_interface, only if no movement has been done */ - else if(xctx->intuitive_interface && state == (Button1Mask | ControlMask) && - !xctx->shape_point_selected && (xctx->ui_state & STARTMOVE) && xctx->mouse_moved == 0) { - int savesem = xctx->semaphore; - move_objects(ABORT, 0, 0.0, 0.0); - unselect_all(1); - select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); - rebuild_selected_array(); - xctx->semaphore = 0; - launcher(); /* works only if lastsel == 1 */ - 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 intuitive_interface copy or move */ - if(xctx->ui_state & STARTCOPY && xctx->drag_elements) { - copy_objects(END); - xctx->constr_mv=0; - tcleval("set constr_mv 0" ); - xctx->drag_elements = 0; - } - else if(xctx->ui_state & STARTMOVE && xctx->drag_elements) { - move_objects(END,0,0,0); - xctx->constr_mv=0; - tcleval("set constr_mv 0" ); - xctx->drag_elements = 0; - } - - /* if a polygon/bezier/rectangle control point was clicked, end point move operation - * and set polygon state back to SELECTED from SELECTED1 */ - else if((xctx->ui_state & (STARTMOVE | SELECTION)) && xctx->shape_point_selected) { - end_shape_point_edit(c_snap); - } - - if(xctx->ui_state & STARTPAN) { - xctx->ui_state &=~STARTPAN; - /* xctx->mx_save = mx; xctx->my_save = my; */ - /* xctx->mx_double_save=xctx->mousex_snap; */ - /* xctx->my_double_save=xctx->mousey_snap; */ - redraw_w_a_l_r_p_z_rubbers(1); - break; - } - dbg(1, "callback(): ButtonRelease ui_state=%d state=%d\n",xctx->ui_state,state); - if(xctx->semaphore >= 2) break; - if(xctx->ui_state & STARTSELECT) { - if(state & ControlMask) { - select_rect(!enable_stretch, END,-1); - } else { - /* Button1 release: end of rectangle select */ - if(!(state & (Button4Mask|Button5Mask) ) ) { - select_rect(enable_stretch, END,-1); - } - } - xctx->ui_state &= ~DESEL_AREA; - rebuild_selected_array(); - my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d path: %s", - xctx->mousex_snap, xctx->mousey_snap, xctx->lastsel, xctx->sch_path[xctx->currsch] ); - statusmsg(str,1); - } + handle_button_release(event, key, state, button, mx, my, aux, c_snap, enable_stretch, + draw_xhair, snap_cursor, wire_draw_active, str); + break; - /* clear start from menu flag or infix_interface=0 start commands */ - if(xctx->ui_state & MENUSTART) { - xctx->ui_state &= ~MENUSTART; - break; - } - if(draw_xhair) draw_crosshair(3, state); /* restore crosshair when selecting / unselecting */ - if(snap_cursor && wire_draw_active) draw_snap_cursor(3); - break; case -3: /* double click : edit prop */ - if( waves_selected(event, key, state, button)) { - waves_callback(event, mx, my, key, button, aux, state); - break; - } else { - if(xctx->semaphore >= 2) break; - dbg(1, "callback(): DoubleClick ui_state=%d state=%d\n",xctx->ui_state,state); - if(button==Button1) { - Selected sel; - if(!xctx->lastsel && xctx->ui_state == 0) { - /* Following 5 lines do again a selection overriding lock, - * so locked instance attrs can be edited */ - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 1, NULL); - if(sel.type) { - xctx->ui_state = SELECTION; - rebuild_selected_array(); - } - } - if(xctx->ui_state == 0 || xctx->ui_state == SELECTION) { - edit_property(0); - } else { - if(xctx->ui_state & STARTWIRE) { - redraw_w_a_l_r_p_z_rubbers(1); - start_wire(mx, my); - xctx->ui_state &= ~STARTWIRE; - } - if(xctx->ui_state & STARTLINE) { - xctx->ui_state &= ~STARTLINE; - } - if( (xctx->ui_state & STARTPOLYGON) && (state ==0 ) ) { - new_polygon(SET, xctx->mousex_snap, xctx->mousey_snap); - } - } - } - } - break; + handle_double_click(event, state, key, button, mx, my, aux, cadence_compat); + break; + default: dbg(1, "callback(): Event:%d\n",event); break; @@ -4648,6 +4697,6 @@ int rstate; /* (reduced state, without ShiftMask) */ if(old_win_path[0]) dbg(1, "callback(): reset old_win_path: %s <- %s\n", old_win_path, win_path); my_strncpy(old_win_path, win_path, S(old_win_path)); } - return 0; + return 0; }