2021-11-04 01:23:40 +01:00
|
|
|
/* File: callback.c
|
2020-10-12 13:13:31 +02:00
|
|
|
*
|
2020-08-08 15:47:34 +02:00
|
|
|
* This file is part of XSCHEM,
|
2020-10-12 13:13:31 +02:00
|
|
|
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
|
2020-08-08 15:47:34 +02:00
|
|
|
* simulation.
|
2023-05-21 12:52:19 +02:00
|
|
|
* Copyright (C) 1998-2023 Stefan Frederik Schippers
|
2020-08-08 15:47:34 +02:00
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "xschem.h"
|
2021-12-30 15:45:38 +01:00
|
|
|
|
2023-09-22 15:53:23 +02:00
|
|
|
/* allow to use the Windows keys as alternate for Alt */
|
2023-09-28 21:03:28 +02:00
|
|
|
#define SET_MODMASK ( (rstate & Mod1Mask) || (rstate & Mod4Mask) )
|
|
|
|
|
#define EQUAL_MODMASK ( (rstate == Mod1Mask) || (rstate == Mod4Mask) )
|
2023-09-22 15:53:23 +02:00
|
|
|
|
2022-09-18 05:29:16 +02:00
|
|
|
static int waves_selected(int event, KeySym key, int state, int button)
|
2021-12-22 04:39:23 +01:00
|
|
|
{
|
2023-09-28 21:03:28 +02:00
|
|
|
int rstate; /* state without ShiftMask */
|
2024-03-08 15:08:47 +01:00
|
|
|
int i, check;
|
2022-01-03 18:43:34 +01:00
|
|
|
int is_inside = 0, skip = 0;
|
2022-04-27 13:18:45 +02:00
|
|
|
static unsigned int excl = STARTZOOM | STARTRECT | STARTLINE | STARTWIRE |
|
|
|
|
|
STARTPAN | STARTSELECT | STARTMOVE | STARTCOPY;
|
2023-09-28 21:03:28 +02:00
|
|
|
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
|
|
|
|
|
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sifficient */
|
2022-01-06 05:34:42 +01:00
|
|
|
if(xctx->ui_state & excl) skip = 1;
|
2022-09-21 11:25:45 +02:00
|
|
|
else if(sch_waves_loaded() < 0 ) skip = 1;
|
2024-03-30 20:16:47 +01:00
|
|
|
else if(SET_MODMASK) skip = 1;
|
2022-01-06 22:38:00 +01:00
|
|
|
else if(event == MotionNotify && (state & Button2Mask)) skip = 1;
|
2022-01-07 01:54:41 +01:00
|
|
|
else if(event == MotionNotify && (state & Button1Mask) && (state & ShiftMask)) skip = 1;
|
2022-01-06 22:38:00 +01:00
|
|
|
else if(event == ButtonPress && button == Button2) skip = 1;
|
2022-01-07 01:54:41 +01:00
|
|
|
else if(event == ButtonPress && button == Button1 && (state & ShiftMask) ) skip = 1;
|
2022-01-06 22:38:00 +01:00
|
|
|
else if(event == ButtonRelease && button == Button2) skip = 1;
|
|
|
|
|
else if(event == KeyPress && (state & ShiftMask)) skip = 1;
|
2023-02-18 09:44:11 +01:00
|
|
|
else if(!skip) for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
|
2021-12-30 15:45:38 +01:00
|
|
|
xRect *r;
|
|
|
|
|
r = &xctx->rect[GRIDLAYER][i];
|
|
|
|
|
if(!(r->flags & 1) ) continue;
|
2023-10-18 16:10:08 +02:00
|
|
|
if(!strboolcmp(get_tok_value(xctx->rect[GRIDLAYER][i].prop_ptr, "lock", 0), "true")) continue;
|
2024-03-08 15:08:47 +01:00
|
|
|
check =
|
|
|
|
|
(event != -3 &&
|
2024-03-21 22:28:32 +01:00
|
|
|
(
|
|
|
|
|
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 20, r->y1 + 8, r->x2 - 20, r->y2 - 8) ||
|
|
|
|
|
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x1 + 20, r->y1 + 8) ||
|
|
|
|
|
POINTINSIDE(xctx->mousex, xctx->mousey, r->x2 - 20, r->y2 - 8, r->x2, r->y2)
|
|
|
|
|
)
|
|
|
|
|
) ||
|
2024-03-08 15:08:47 +01:00
|
|
|
( event == -3 &&
|
|
|
|
|
(POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2 - 40, r->y1 + 20) ||
|
2024-03-21 22:28:32 +01:00
|
|
|
POINTINSIDE(xctx->mousex, xctx->mousey, r->x1 + 20, r->y1, r->x2 - 30, r->y2 - 10))
|
|
|
|
|
);
|
2024-03-08 15:08:47 +01:00
|
|
|
if( (xctx->ui_state & GRAPHPAN) || check) {
|
2021-12-30 15:45:38 +01:00
|
|
|
is_inside = 1;
|
2023-09-22 12:48:22 +02:00
|
|
|
draw_crosshair(1);
|
2022-01-04 05:54:25 +01:00
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
|
2021-12-30 15:45:38 +01:00
|
|
|
}
|
2021-12-22 04:39:23 +01:00
|
|
|
}
|
2022-01-04 05:54:25 +01:00
|
|
|
if(!is_inside) {
|
2023-09-22 12:48:22 +02:00
|
|
|
if(tclgetboolvar("draw_crosshair"))
|
|
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL);
|
|
|
|
|
else
|
|
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL);
|
2022-01-04 05:54:25 +01:00
|
|
|
if(xctx->graph_flags & 64) {
|
|
|
|
|
tcleval("graph_show_measure stop");
|
|
|
|
|
}
|
2022-01-03 18:43:34 +01:00
|
|
|
}
|
2021-12-22 18:25:15 +01:00
|
|
|
return is_inside;
|
2021-12-22 04:39:23 +01:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-12-29 03:45:12 +01:00
|
|
|
void redraw_w_a_l_r_p_rubbers(void)
|
|
|
|
|
{
|
|
|
|
|
if(xctx->ui_state & STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2020-12-29 03:45:12 +01:00
|
|
|
new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
|
|
|
|
}
|
|
|
|
|
if(xctx->ui_state & STARTARC) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(RUBBER, 0, xctx->mousex_snap, xctx->mousey_snap);
|
2020-12-29 03:45:12 +01:00
|
|
|
}
|
|
|
|
|
if(xctx->ui_state & STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-12-29 03:45:12 +01:00
|
|
|
}
|
2024-03-06 12:53:49 +01:00
|
|
|
if(xctx->ui_state & STARTRECT) new_rect(RUBBER,xctx->mousex_snap, xctx->mousey_snap);
|
2020-12-29 03:45:12 +01:00
|
|
|
if(xctx->ui_state & STARTPOLYGON) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-12-29 03:45:12 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-02-19 14:31:55 +01:00
|
|
|
|
2023-03-01 18:34:07 +01:00
|
|
|
/* resets UI state, unselect all and abort any pending operation */
|
2022-09-25 21:11:52 +02:00
|
|
|
void abort_operation(void)
|
2021-11-04 02:07:41 +01:00
|
|
|
{
|
|
|
|
|
xctx->no_draw = 0;
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 0" );
|
2023-12-01 23:05:07 +01:00
|
|
|
dbg(1, "abort_operation(): Escape: ui_state=%d, last_command=%d\n", xctx->ui_state, xctx->last_command);
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
2023-12-01 23:05:07 +01:00
|
|
|
if(xctx->last_command && xctx->ui_state & (STARTWIRE | STARTLINE)) {
|
|
|
|
|
if(xctx->ui_state & STARTWIRE) new_wire(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-06 12:53:49 +01:00
|
|
|
if(xctx->ui_state & STARTLINE) new_line(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
|
2023-12-01 23:05:07 +01:00
|
|
|
if(tclgetboolvar("draw_crosshair")) draw_crosshair(2);
|
|
|
|
|
xctx->ui_state = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-11-04 02:07:41 +01:00
|
|
|
xctx->last_command=0;
|
|
|
|
|
xctx->manhattan_lines = 0;
|
|
|
|
|
if(xctx->ui_state & STARTMOVE)
|
|
|
|
|
{
|
|
|
|
|
move_objects(ABORT,0,0,0);
|
2021-11-04 15:08:54 +01:00
|
|
|
if(xctx->ui_state & (START_SYMPIN | PLACE_SYMBOL | PLACE_TEXT)) {
|
2023-12-01 23:05:07 +01:00
|
|
|
int save;
|
2022-09-26 18:38:19 +02:00
|
|
|
save = xctx->modified;
|
2021-11-04 02:07:41 +01:00
|
|
|
delete(1/* to_push_undo */);
|
2022-09-26 18:38:19 +02:00
|
|
|
set_modify(save); /* aborted placement: no change, so reset modify flag set by delete() */
|
2021-11-04 02:07:41 +01:00
|
|
|
xctx->ui_state &= ~START_SYMPIN;
|
2021-11-04 15:08:54 +01:00
|
|
|
xctx->ui_state &= ~PLACE_SYMBOL;
|
|
|
|
|
xctx->ui_state &= ~PLACE_TEXT;
|
2021-11-04 02:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(xctx->ui_state & STARTCOPY)
|
|
|
|
|
{
|
|
|
|
|
copy_objects(ABORT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(xctx->ui_state & STARTMERGE) {
|
|
|
|
|
delete(1/* to_push_undo */);
|
|
|
|
|
set_modify(0); /* aborted merge: no change, so reset modify flag set by delete() */
|
|
|
|
|
}
|
|
|
|
|
xctx->ui_state = 0;
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2021-11-04 02:07:41 +01:00
|
|
|
draw();
|
|
|
|
|
}
|
2020-12-29 03:45:12 +01:00
|
|
|
|
2024-03-06 12:53:49 +01:00
|
|
|
static void start_place_symbol(void)
|
2021-11-04 01:13:44 +01:00
|
|
|
{
|
|
|
|
|
xctx->last_command = 0;
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
if(xctx->lastsel && xctx->sel_array[0].type==ELEMENT) {
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval("set INITIALINSTDIR [file dirname {",
|
2023-05-01 14:37:10 +02:00
|
|
|
abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), ""), "}]", NULL);
|
2021-11-04 01:13:44 +01:00
|
|
|
}
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2021-11-04 01:13:44 +01:00
|
|
|
xctx->mx_double_save = xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save = xctx->mousey_snap;
|
|
|
|
|
if(place_symbol(-1,NULL,xctx->mousex_snap, xctx->mousey_snap, 0, 0, NULL, 4, 1, 1/* to_push_undo */) ) {
|
2023-09-22 15:53:23 +02:00
|
|
|
xctx->mousey_snap = xctx->my_double_save;
|
2021-11-04 01:13:44 +01:00
|
|
|
xctx->mousex_snap = xctx->mx_double_save;
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
xctx->ui_state |= PLACE_SYMBOL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 14:31:55 +01:00
|
|
|
static void start_line(double mx, double my)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = STARTLINE;
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 2) {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->mx_double_save=mx;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 1) {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->my_double_save=my;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) my = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) mx = xctx->mx_double_save;
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->mx_double_save=mx;
|
|
|
|
|
xctx->my_double_save=my;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(PLACE, mx, my);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-19 14:31:55 +01:00
|
|
|
static void start_wire(double mx, double my)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = STARTWIRE;
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 2) {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->mx_double_save = mx;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 1) {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->my_double_save = my;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) my = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) mx = xctx->mx_double_save;
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2024-03-06 12:53:49 +01:00
|
|
|
xctx->mx_double_save=mx;
|
|
|
|
|
xctx->my_double_save=my;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-06 12:53:49 +01:00
|
|
|
new_wire(PLACE,mx, my);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-12-22 04:39:23 +01:00
|
|
|
|
2024-04-01 23:23:45 +02:00
|
|
|
static double interpolate_yval(int idx, int p, double x, int sweep_idx, int point_not_last)
|
2023-10-16 09:53:03 +02:00
|
|
|
{
|
2024-04-01 23:23:45 +02:00
|
|
|
double val = xctx->raw->values[idx][p];
|
2023-10-16 09:53:03 +02:00
|
|
|
/* not operating point, annotate from 'b' cursor */
|
2024-04-01 23:23:45 +02:00
|
|
|
if(point_not_last && (xctx->raw->allpoints > 1) && sweep_idx >= 0) {
|
2023-10-16 09:53:03 +02:00
|
|
|
Raw *raw = xctx->raw;
|
2024-04-01 23:23:45 +02:00
|
|
|
SPICE_DATA *sweep_gv = raw->values[sweep_idx];
|
2023-10-16 09:53:03 +02:00
|
|
|
SPICE_DATA *gv = raw->values[idx];
|
2024-04-01 23:23:45 +02:00
|
|
|
double dx = sweep_gv[p + 1] - sweep_gv[p];
|
|
|
|
|
double dy = gv[p + 1] - gv[p];
|
|
|
|
|
double offset = x - sweep_gv[p];
|
|
|
|
|
double interp = dx != 0.0 ? offset * dy / dx : 0.0;
|
|
|
|
|
val += interp;
|
2023-10-16 09:53:03 +02:00
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
}
|
2024-04-01 23:23:45 +02:00
|
|
|
|
2024-03-30 19:20:51 +01:00
|
|
|
void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
|
2022-09-18 05:29:16 +02:00
|
|
|
{
|
2022-09-21 11:25:45 +02:00
|
|
|
if(sch_waves_loaded() >= 0) {
|
2023-10-16 09:53:03 +02:00
|
|
|
int dset, first = -1, last, dataset = gr->dataset, i, p, ofs = 0, ofs_end;
|
2022-09-18 23:29:48 +02:00
|
|
|
double start, end;
|
2022-09-19 12:19:39 +02:00
|
|
|
int sweepvar_wrap = 0, sweep_idx;
|
2024-03-30 19:20:51 +01:00
|
|
|
double xx, cursor2; /* xx is the p-th sweep variable value, cursor2 is cursor 'b' x position */
|
2023-10-11 14:05:27 +02:00
|
|
|
Raw *raw = xctx->raw;
|
2023-11-09 04:10:06 +01:00
|
|
|
int save_datasets = -1, save_npoints = -1;
|
|
|
|
|
/* transform multiple OP points into a dc sweep */
|
2024-04-01 02:23:30 +02:00
|
|
|
if(raw->sim_type && !strcmp(raw->sim_type, "op") && raw->datasets > 1 && raw->npoints[0] == 1) {
|
2023-11-09 04:10:06 +01:00
|
|
|
save_datasets = raw->datasets;
|
|
|
|
|
raw->datasets = 1;
|
|
|
|
|
save_npoints = raw->npoints[0];
|
|
|
|
|
raw->npoints[0] = raw->allpoints;
|
|
|
|
|
}
|
2024-02-25 12:21:13 +01:00
|
|
|
sweep_idx = get_raw_index(find_nth(get_tok_value(r->prop_ptr, "sweep", 0), ", ", "\"", 0, 1), NULL);
|
2022-09-19 12:19:39 +02:00
|
|
|
if(sweep_idx < 0) sweep_idx = 0;
|
2024-03-30 19:20:51 +01:00
|
|
|
cursor2 = xctx->graph_cursor2_x;
|
2022-09-18 23:29:48 +02:00
|
|
|
start = (gr->gx1 <= gr->gx2) ? gr->gx1 : gr->gx2;
|
|
|
|
|
end = (gr->gx1 <= gr->gx2) ? gr->gx2 : gr->gx1;
|
2024-03-30 19:20:51 +01:00
|
|
|
dbg(1, "start=%g, end=%g\n", start, end);
|
2022-09-19 12:08:07 +02:00
|
|
|
if(gr->logx) {
|
|
|
|
|
start = pow(10, start);
|
|
|
|
|
end = pow(10, end);
|
|
|
|
|
}
|
2024-03-30 19:20:51 +01:00
|
|
|
dbg(1, "cursor b pos: %g dataset=%d\n", cursor2, gr->dataset);
|
2022-09-18 23:29:48 +02:00
|
|
|
if(dataset < 0) dataset = 0; /* if all datasets are plotted use first for backannotation */
|
|
|
|
|
dbg(1, "dataset=%d\n", dataset);
|
2022-09-20 16:49:42 +02:00
|
|
|
ofs = 0;
|
2023-10-11 14:05:27 +02:00
|
|
|
for(dset = 0 ; dset < raw->datasets; dset++) {
|
2022-09-18 23:29:48 +02:00
|
|
|
double prev_x, prev_prev_x;
|
|
|
|
|
int cnt=0, wrap;
|
2023-10-11 14:05:27 +02:00
|
|
|
register SPICE_DATA *gv = raw->values[sweep_idx];
|
2022-09-20 17:59:01 +02:00
|
|
|
int s=0;
|
2023-10-16 09:53:03 +02:00
|
|
|
ofs_end = ofs + raw->npoints[dset];
|
2022-09-18 23:29:48 +02:00
|
|
|
first = -1;
|
|
|
|
|
prev_prev_x = prev_x = 0;
|
|
|
|
|
last = ofs;
|
2023-10-16 09:53:03 +02:00
|
|
|
for(p = ofs ; p < ofs_end; p++) {
|
2022-09-18 23:29:48 +02:00
|
|
|
xx = gv[p];
|
|
|
|
|
wrap = ( cnt > 1 && XSIGN(xx - prev_x) != XSIGN(prev_x - prev_prev_x));
|
|
|
|
|
if(wrap) {
|
|
|
|
|
sweepvar_wrap++;
|
|
|
|
|
cnt = 0;
|
|
|
|
|
}
|
|
|
|
|
if(xx >= start && xx <= end) {
|
2024-03-31 13:36:35 +02:00
|
|
|
if((dataset == sweepvar_wrap)) {
|
2024-03-30 19:20:51 +01:00
|
|
|
dbg(1, "xx=%g cursor2=%g first=%d last=%d start=%g end=%g p=%d wrap=%d sweepvar_wrap=%d ofs=%d\n",
|
|
|
|
|
xx, cursor2, first, last, start, end, p, wrap, sweepvar_wrap, ofs);
|
2022-09-18 23:29:48 +02:00
|
|
|
if(first == -1) first = p;
|
|
|
|
|
if(p == first) {
|
2024-03-30 19:20:51 +01:00
|
|
|
if(xx == cursor2) {goto done;}
|
|
|
|
|
s = XSIGN0(xx - cursor2);
|
2022-09-20 17:59:01 +02:00
|
|
|
dbg(1, "s=%d\n", s);
|
2022-09-18 23:29:48 +02:00
|
|
|
} else {
|
2024-03-30 19:20:51 +01:00
|
|
|
int ss = XSIGN0(xx - cursor2);
|
2022-09-20 17:59:01 +02:00
|
|
|
dbg(1, "s=%d, ss=%d\n", s, ss);
|
2023-10-16 09:53:03 +02:00
|
|
|
if(ss != s) {goto done;}
|
2022-09-18 23:29:48 +02:00
|
|
|
}
|
|
|
|
|
last = p;
|
|
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
++cnt;
|
2022-09-18 23:29:48 +02:00
|
|
|
} /* if(xx >= start && xx <= end) */
|
|
|
|
|
prev_prev_x = prev_x;
|
|
|
|
|
prev_x = xx;
|
2023-10-11 14:05:27 +02:00
|
|
|
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
|
2022-09-18 23:29:48 +02:00
|
|
|
/* offset pointing to next dataset */
|
2023-10-16 09:53:03 +02:00
|
|
|
ofs = ofs_end;
|
2022-09-18 23:29:48 +02:00
|
|
|
sweepvar_wrap++;
|
|
|
|
|
} /* for(dset...) */
|
2023-10-16 09:53:03 +02:00
|
|
|
done:
|
2023-09-28 00:30:00 +02:00
|
|
|
if(first != -1) {
|
|
|
|
|
if(p > last) {
|
|
|
|
|
double sweep0, sweep1;
|
|
|
|
|
p = last;
|
2023-10-11 14:05:27 +02:00
|
|
|
sweep0 = raw->values[sweep_idx][first];
|
|
|
|
|
sweep1 = raw->values[sweep_idx][p];
|
2024-03-30 19:20:51 +01:00
|
|
|
if(fabs(sweep0 - cursor2) < fabs(sweep1 - cursor2)) {
|
2023-09-28 00:30:00 +02:00
|
|
|
p = first;
|
|
|
|
|
}
|
2022-09-18 23:29:48 +02:00
|
|
|
}
|
2023-09-28 00:30:00 +02:00
|
|
|
dbg(1, "xx=%g, p=%d\n", xx, p);
|
2024-03-30 19:20:51 +01:00
|
|
|
Tcl_UnsetVar(interp, "ngspice::ngspice_data", TCL_GLOBAL_ONLY);
|
|
|
|
|
raw->annot_p = p;
|
|
|
|
|
raw->annot_x = cursor2;
|
|
|
|
|
raw->annot_sweep_idx = sweep_idx;
|
|
|
|
|
for(i = 0; i < raw->nvars; ++i) {
|
|
|
|
|
char s[100];
|
2024-04-01 23:23:45 +02:00
|
|
|
raw->cursor_b_val[i] = interpolate_yval(i, p, cursor2, sweep_idx, (p < ofs_end));
|
2024-03-30 19:20:51 +01:00
|
|
|
my_snprintf(s, S(s), "%.5g", raw->cursor_b_val[i]);
|
|
|
|
|
/* tclvareval("array set ngspice::ngspice_data [list {", raw->names[i], "} ", s, "]", NULL); */
|
|
|
|
|
Tcl_SetVar2(interp, "ngspice::ngspice_data", raw->names[i], s, TCL_GLOBAL_ONLY);
|
2023-09-28 00:30:00 +02:00
|
|
|
}
|
2024-03-30 19:20:51 +01:00
|
|
|
Tcl_SetVar2(interp, "ngspice::ngspice_data", "n\\ vars", my_itoa( raw->nvars), TCL_GLOBAL_ONLY);
|
|
|
|
|
Tcl_SetVar2(interp, "ngspice::ngspice_data", "n\\ points", "1", TCL_GLOBAL_ONLY);
|
2022-09-18 23:29:48 +02:00
|
|
|
}
|
2023-11-09 04:10:06 +01:00
|
|
|
if(save_npoints != -1) { /* restore multiple OP points from artificial dc sweep */
|
|
|
|
|
raw->datasets = save_datasets;
|
|
|
|
|
raw->npoints[0] = save_npoints;
|
|
|
|
|
}
|
2022-09-18 23:29:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 04:39:23 +01:00
|
|
|
/* process user input (arrow keys for now) when only graphs are selected */
|
2022-01-02 04:42:15 +01:00
|
|
|
|
|
|
|
|
/* xctx->graph_flags:
|
2022-01-06 01:10:06 +01:00
|
|
|
* 1: dnu, reserved, used in draw_graphs()
|
2022-01-02 04:42:15 +01:00
|
|
|
* 2: draw x-cursor1
|
|
|
|
|
* 4: draw x-cursor2
|
|
|
|
|
* 8: dnu, reserved, used in draw_graphs()
|
|
|
|
|
* 16: move cursor1
|
|
|
|
|
* 32: move cursor2
|
2022-01-03 18:43:34 +01:00
|
|
|
* 64: show measurement tooltip
|
2022-01-02 04:42:15 +01:00
|
|
|
*/
|
2021-12-22 04:39:23 +01:00
|
|
|
static int waves_callback(int event, int mx, int my, KeySym key, int button, int aux, int state)
|
|
|
|
|
{
|
2022-01-05 23:07:08 +01:00
|
|
|
Graph_ctx *gr;
|
2023-09-28 21:03:28 +02:00
|
|
|
int rstate; /* reduced state wit ShiftMask bit filtered out */
|
2022-09-18 11:06:48 +02:00
|
|
|
int i, redraw_all_at_end = 0, need_all_redraw = 0, need_redraw = 0, dataset = 0;
|
2023-09-28 00:30:00 +02:00
|
|
|
double xx1 = 0.0, xx2 = 0.0, yy1, yy2;
|
Better axis label placement, smooth waves move/zoom with mouse, compile option to store sim data as floats instead of doubles, option for axis scaling (p,n,u,m,k,M,G), load waveforms command is a toggle (load / free)
2021-12-24 12:17:00 +01:00
|
|
|
double delta_threshold = 0.25;
|
2021-12-30 15:45:38 +01:00
|
|
|
double zoom_m = 0.5;
|
2022-01-28 04:44:07 +01:00
|
|
|
int save_mouse_at_end = 0, clear_graphpan_at_end = 0;
|
2022-09-02 18:09:51 +02:00
|
|
|
int track_dset = -2; /* used to find dataset of closest wave to mouse if 't' is pressed */
|
2022-08-23 10:01:32 +02:00
|
|
|
xRect *r = NULL;
|
2023-09-28 21:03:28 +02:00
|
|
|
|
2023-10-11 14:05:27 +02:00
|
|
|
if(!xctx->raw) return 0;
|
2023-09-28 21:03:28 +02:00
|
|
|
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
|
|
|
|
|
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sifficient */
|
|
|
|
|
|
2021-12-22 18:25:15 +01:00
|
|
|
#if HAS_CAIRO==1
|
|
|
|
|
cairo_save(xctx->cairo_ctx);
|
|
|
|
|
cairo_save(xctx->cairo_save_ctx);
|
2022-12-25 10:42:07 +01:00
|
|
|
xctx->cairo_font =
|
|
|
|
|
cairo_toy_font_face_create("Sans-Serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
|
|
|
|
cairo_set_font_face(xctx->cairo_ctx, xctx->cairo_font);
|
|
|
|
|
cairo_set_font_face(xctx->cairo_save_ctx, xctx->cairo_font);
|
2022-12-25 23:13:59 +01:00
|
|
|
cairo_font_face_destroy(xctx->cairo_font);
|
2021-12-22 18:25:15 +01:00
|
|
|
#endif
|
2022-01-05 23:07:08 +01:00
|
|
|
gr = &xctx->graph_struct;
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0; i < xctx->rects[GRIDLAYER]; ++i) {
|
2022-01-01 15:46:03 +01:00
|
|
|
if( (xctx->ui_state & GRAPHPAN) && i != xctx->graph_master) continue;
|
2021-12-30 20:52:15 +01:00
|
|
|
r = &xctx->rect[GRIDLAYER][i];
|
2022-01-28 04:44:07 +01:00
|
|
|
/* process only graph boxes */
|
2021-12-30 20:52:15 +01:00
|
|
|
if(!(r->flags & 1) ) continue;
|
|
|
|
|
/* check if this is the master graph (the one containing the mouse pointer) */
|
|
|
|
|
/* determine if mouse pointer is below xaxis or left of yaxis in some graph */
|
2022-01-04 05:54:25 +01:00
|
|
|
if( POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2)) {
|
2022-09-28 19:14:31 +02:00
|
|
|
dbg(1, "mouse inside: %d\n", i);
|
2023-02-26 11:22:19 +01:00
|
|
|
setup_graph_data(i, 0, gr);
|
2022-01-03 18:43:34 +01:00
|
|
|
|
2022-01-01 15:46:03 +01:00
|
|
|
/* move cursor1 */
|
|
|
|
|
/* set cursor position from master graph x-axis */
|
|
|
|
|
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
|
|
|
|
|
xctx->graph_cursor1_x = G_X(xctx->mousex);
|
2024-04-01 00:25:50 +02:00
|
|
|
if(gr->logx) xctx->graph_cursor1_x = pow(10, xctx->graph_cursor1_x);
|
2022-01-01 15:46:03 +01:00
|
|
|
}
|
|
|
|
|
/* move cursor2 */
|
|
|
|
|
/* set cursor position from master graph x-axis */
|
|
|
|
|
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) {
|
2023-10-23 16:03:27 +02:00
|
|
|
int floaters = there_are_floaters();
|
2022-01-01 15:46:03 +01:00
|
|
|
xctx->graph_cursor2_x = G_X(xctx->mousex);
|
2024-04-01 00:25:50 +02:00
|
|
|
if(gr->logx) xctx->graph_cursor2_x = pow(10, xctx->graph_cursor2_x);
|
2022-09-18 12:25:09 +02:00
|
|
|
if(tclgetboolvar("live_cursor2_backannotate")) {
|
2024-03-30 19:20:51 +01:00
|
|
|
backannotate_at_cursor_b_pos(r, gr);
|
2023-10-23 16:03:27 +02:00
|
|
|
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
|
2022-09-18 12:25:09 +02:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
}
|
2022-01-01 15:46:03 +01:00
|
|
|
}
|
2022-09-28 19:14:31 +02:00
|
|
|
gr->master_gx1 = gr->gx1;
|
|
|
|
|
gr->master_gx2 = gr->gx2;
|
|
|
|
|
gr->master_gw = gr->gw;
|
|
|
|
|
gr->master_cx = gr->cx;
|
2022-01-01 15:46:03 +01:00
|
|
|
if(xctx->ui_state & GRAPHPAN) break; /* After GRAPHPAN only need to check Motion events for cursors */
|
2022-01-28 04:44:07 +01:00
|
|
|
if(xctx->mousey_snap < W_Y(gr->gy2)) {
|
|
|
|
|
xctx->graph_top = 1;
|
|
|
|
|
} else {
|
|
|
|
|
xctx->graph_top = 0;
|
|
|
|
|
}
|
2022-01-05 23:07:08 +01:00
|
|
|
if(xctx->mousex_snap < W_X(gr->gx1)) {
|
2021-12-30 20:52:15 +01:00
|
|
|
xctx->graph_left = 1;
|
|
|
|
|
} else {
|
|
|
|
|
xctx->graph_left = 0;
|
|
|
|
|
}
|
2022-01-05 23:07:08 +01:00
|
|
|
if(xctx->mousey_snap > W_Y(gr->gy1)) {
|
2021-12-30 20:52:15 +01:00
|
|
|
xctx->graph_bottom = 1;
|
|
|
|
|
} else {
|
|
|
|
|
xctx->graph_bottom = 0;
|
|
|
|
|
}
|
|
|
|
|
xctx->graph_master = i;
|
2022-01-05 23:07:08 +01:00
|
|
|
zoom_m = (xctx->mousex - gr->x1) / gr->w;
|
2021-12-30 20:52:15 +01:00
|
|
|
if(event == ButtonPress && button == Button1) {
|
2024-03-30 19:20:51 +01:00
|
|
|
/* dragging cursors when mouse is very close */
|
2024-03-31 13:27:12 +02:00
|
|
|
if(xctx->graph_flags & 2) {
|
2024-04-01 00:25:50 +02:00
|
|
|
double cursor1 = xctx->graph_cursor1_x;
|
|
|
|
|
if(gr->logx ) {
|
|
|
|
|
cursor1 = mylog10(cursor1);
|
2024-03-31 13:27:12 +02:00
|
|
|
}
|
2024-04-01 00:25:50 +02:00
|
|
|
if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
|
2024-03-31 13:27:12 +02:00
|
|
|
xctx->graph_flags |= 16; /* Start move cursor1 */
|
|
|
|
|
}
|
2022-01-28 04:44:07 +01:00
|
|
|
}
|
2024-03-31 13:27:12 +02:00
|
|
|
if(xctx->graph_flags & 4) {
|
2024-04-01 00:25:50 +02:00
|
|
|
double cursor2 = xctx->graph_cursor2_x;
|
|
|
|
|
if(gr->logx) {
|
|
|
|
|
cursor2 = mylog10(cursor2);
|
2024-03-31 13:27:12 +02:00
|
|
|
}
|
2024-04-01 00:25:50 +02:00
|
|
|
if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
|
2024-03-31 13:27:12 +02:00
|
|
|
xctx->graph_flags |= 32; /* Start move cursor2 */
|
|
|
|
|
}
|
2021-12-30 15:45:38 +01:00
|
|
|
}
|
2021-12-30 20:52:15 +01:00
|
|
|
}
|
2024-01-05 02:08:13 +01:00
|
|
|
else if(event == ButtonPress && button == Button3) {
|
|
|
|
|
/* Numerically set cursor position */
|
2024-04-01 00:25:50 +02:00
|
|
|
if(xctx->graph_flags & 2) {
|
|
|
|
|
double cursor1 = xctx->graph_cursor1_x;
|
2024-01-05 02:08:13 +01:00
|
|
|
if(gr->logx) {
|
2024-04-01 00:25:50 +02:00
|
|
|
cursor1 = mylog10(cursor1);
|
|
|
|
|
}
|
|
|
|
|
if(fabs(xctx->mousex - W_X(cursor1)) < 10) {
|
2024-01-05 02:08:13 +01:00
|
|
|
tclvareval("input_line {Pos:} {xschem set cursor1_x} ", dtoa_eng(xctx->graph_cursor1_x), NULL);
|
|
|
|
|
}
|
2024-01-05 11:21:34 +01:00
|
|
|
event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
|
2024-01-05 02:08:13 +01:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
}
|
2024-04-01 00:25:50 +02:00
|
|
|
|
|
|
|
|
if(xctx->graph_flags & 4) {
|
|
|
|
|
double cursor2 = xctx->graph_cursor2_x;
|
2024-01-05 02:08:13 +01:00
|
|
|
if(gr->logx) {
|
2024-04-01 00:25:50 +02:00
|
|
|
cursor2 = mylog10(cursor2);
|
|
|
|
|
}
|
|
|
|
|
if(fabs(xctx->mousex - W_X(cursor2)) < 10) {
|
2024-01-05 02:08:13 +01:00
|
|
|
tclvareval("input_line {Pos:} {xschem set cursor2_x} ", dtoa_eng(xctx->graph_cursor2_x), NULL);
|
|
|
|
|
}
|
2024-01-05 11:21:34 +01:00
|
|
|
event = 0; /* avoid further processing ButtonPress that might set GRAPHPAH */
|
2024-01-05 02:08:13 +01:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-28 04:44:07 +01:00
|
|
|
else if(event == -3 && button == Button1) {
|
2022-01-27 21:14:52 +01:00
|
|
|
if(!edit_wave_attributes(1, i, gr)) {
|
2022-04-27 13:18:45 +02:00
|
|
|
tclvareval("graph_edit_properties ", my_itoa(i), NULL);
|
2022-01-27 20:47:27 +01:00
|
|
|
}
|
2022-01-07 12:45:18 +01:00
|
|
|
}
|
2021-12-31 11:58:28 +01:00
|
|
|
/* x cursor1 toggle */
|
2023-09-28 21:03:28 +02:00
|
|
|
else if((key == 'a' && rstate == 0) ) {
|
2021-12-30 20:52:15 +01:00
|
|
|
xctx->graph_flags ^= 2;
|
2022-01-27 20:47:27 +01:00
|
|
|
need_all_redraw = 1;
|
2024-04-01 00:25:50 +02:00
|
|
|
if(xctx->graph_flags & 2) {
|
|
|
|
|
xctx->graph_cursor1_x = G_X(xctx->mousex);
|
|
|
|
|
if(gr->logx) xctx->graph_cursor1_x = pow(10, xctx->graph_cursor1_x);
|
|
|
|
|
}
|
2021-12-30 20:52:15 +01:00
|
|
|
}
|
2021-12-31 11:58:28 +01:00
|
|
|
/* x cursor2 toggle */
|
2021-12-30 20:52:15 +01:00
|
|
|
else if((key == 'b') ) {
|
2023-10-23 16:03:27 +02:00
|
|
|
int floaters = there_are_floaters();
|
2021-12-30 20:52:15 +01:00
|
|
|
xctx->graph_flags ^= 4;
|
2022-09-18 05:29:16 +02:00
|
|
|
if(xctx->graph_flags & 4) {
|
|
|
|
|
xctx->graph_cursor2_x = G_X(xctx->mousex);
|
2024-04-01 00:25:50 +02:00
|
|
|
if(gr->logx) xctx->graph_cursor2_x = pow(10, xctx->graph_cursor2_x);
|
2022-09-18 11:06:48 +02:00
|
|
|
if(tclgetboolvar("live_cursor2_backannotate")) {
|
2024-03-30 19:20:51 +01:00
|
|
|
backannotate_at_cursor_b_pos(r, gr);
|
2023-10-23 16:03:27 +02:00
|
|
|
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
|
2022-09-18 11:06:48 +02:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
} else {
|
|
|
|
|
need_all_redraw = 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-10-11 14:05:27 +02:00
|
|
|
xctx->raw->annot_p = -1;
|
2023-10-15 12:05:48 +02:00
|
|
|
xctx->raw->annot_sweep_idx = -1;
|
2023-06-05 12:58:19 +02:00
|
|
|
/* need_all_redraw = 1; */
|
|
|
|
|
redraw_all_at_end = 1;
|
2022-09-18 05:29:16 +02:00
|
|
|
}
|
2021-12-30 20:52:15 +01:00
|
|
|
}
|
2023-02-08 04:13:50 +01:00
|
|
|
/* swap cursors */
|
|
|
|
|
else if((key == 's') ) {
|
|
|
|
|
double tmp;
|
2023-10-23 16:03:27 +02:00
|
|
|
int floaters = there_are_floaters();
|
2023-02-08 04:13:50 +01:00
|
|
|
tmp = xctx->graph_cursor2_x;
|
|
|
|
|
xctx->graph_cursor2_x = xctx->graph_cursor1_x;
|
|
|
|
|
xctx->graph_cursor1_x = tmp;
|
2023-10-13 15:51:51 +02:00
|
|
|
if(tclgetboolvar("live_cursor2_backannotate")) {
|
2024-03-30 19:20:51 +01:00
|
|
|
backannotate_at_cursor_b_pos(r, gr);
|
2023-10-23 16:03:27 +02:00
|
|
|
if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */
|
2023-10-13 15:51:51 +02:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
}
|
|
|
|
|
else need_all_redraw = 1;
|
2023-02-08 04:13:50 +01:00
|
|
|
}
|
2022-01-03 18:43:34 +01:00
|
|
|
/* measurement tooltip */
|
|
|
|
|
else if((key == 'm') ) {
|
|
|
|
|
xctx->graph_flags ^= 64;
|
|
|
|
|
if(!(xctx->graph_flags & 64)) {
|
2022-01-04 05:54:25 +01:00
|
|
|
tcleval("graph_show_measure stop");
|
2022-01-03 18:43:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-02 18:09:51 +02:00
|
|
|
else if((key == 't') ) {
|
|
|
|
|
if(!gr->digital) {
|
|
|
|
|
const char *d = get_tok_value(r->prop_ptr, "dataset", 0);
|
|
|
|
|
if(d[0]) {
|
|
|
|
|
track_dset = atoi(d);
|
|
|
|
|
} else {
|
|
|
|
|
track_dset = -1;
|
|
|
|
|
}
|
|
|
|
|
if(track_dset < 0) {
|
|
|
|
|
track_dset = find_closest_wave(i, gr);
|
|
|
|
|
} else {
|
|
|
|
|
track_dset = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} /* key == 't' */
|
2021-12-30 20:52:15 +01:00
|
|
|
break;
|
|
|
|
|
} /* if( POINTINSIDE(...) */
|
2023-02-18 09:44:11 +01:00
|
|
|
} /* for(i=0; i < xctx->rects[GRIDLAYER]; ++i) */
|
2022-09-28 19:14:31 +02:00
|
|
|
dbg(1, "out of 1st loop: i=%d\n", i);
|
2022-01-01 15:46:03 +01:00
|
|
|
|
2022-01-28 04:44:07 +01:00
|
|
|
/* check if user clicked on a wave label -> draw wave in bold */
|
|
|
|
|
if(event == ButtonPress && button == Button3 &&
|
|
|
|
|
edit_wave_attributes(2, i, gr)) {
|
2022-09-25 21:11:52 +02:00
|
|
|
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in graph box */
|
2022-01-28 04:44:07 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2022-01-01 15:46:03 +01:00
|
|
|
/* save mouse position when doing pan operations */
|
2022-01-28 04:44:07 +01:00
|
|
|
else if(
|
2022-01-01 15:46:03 +01:00
|
|
|
(
|
|
|
|
|
(event == ButtonPress && (button == Button1 || button == Button3)) ||
|
|
|
|
|
(event == MotionNotify && (state & (Button1Mask | Button3Mask)))
|
|
|
|
|
) &&
|
2022-01-28 04:44:07 +01:00
|
|
|
!(xctx->ui_state & GRAPHPAN) &&
|
|
|
|
|
!xctx->graph_top /* && !xctx->graph_bottom */
|
2022-01-01 15:46:03 +01:00
|
|
|
) {
|
|
|
|
|
xctx->ui_state |= GRAPHPAN;
|
2022-01-28 04:44:07 +01:00
|
|
|
if(!xctx->graph_left) xctx->mx_double_save = xctx->mousex_snap;
|
|
|
|
|
if(xctx->graph_left) xctx->my_double_save = xctx->mousey_snap;
|
2021-12-26 14:33:54 +01:00
|
|
|
}
|
2022-09-28 19:14:31 +02:00
|
|
|
dbg(1, "graph_master=%d\n", xctx->graph_master);
|
2022-01-28 04:44:07 +01:00
|
|
|
|
2022-08-19 01:23:45 +02:00
|
|
|
/* parameters for absolute positioning by mouse drag in bottom graph area */
|
|
|
|
|
if( event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
|
2023-11-09 16:41:53 +01:00
|
|
|
int idx;
|
|
|
|
|
int dset;
|
2022-08-19 01:23:45 +02:00
|
|
|
double wwx1, wwx2, pp, delta, ccx, ddx;
|
2023-11-09 16:41:53 +01:00
|
|
|
|
|
|
|
|
char *rawfile = NULL;
|
|
|
|
|
char *sim_type = NULL;
|
|
|
|
|
int switched = 0;
|
|
|
|
|
|
|
|
|
|
my_strdup2(_ALLOC_ID_, &rawfile, get_tok_value(r->prop_ptr, "rawfile", 0));
|
|
|
|
|
my_strdup2(_ALLOC_ID_, &sim_type, get_tok_value(r->prop_ptr, "sim_type", 0));
|
2023-12-31 20:33:08 +01:00
|
|
|
if(rawfile[0] && sim_type[0]) switched = extra_rawfile(2, rawfile, sim_type, -1.0, -1.0);
|
2023-11-09 16:41:53 +01:00
|
|
|
my_free(_ALLOC_ID_, &rawfile);
|
|
|
|
|
my_free(_ALLOC_ID_, &sim_type);
|
|
|
|
|
|
2024-02-25 12:21:13 +01:00
|
|
|
idx = get_raw_index(find_nth(get_tok_value(r->prop_ptr, "sweep", 0), ", ", "\"", 0, 1), NULL);
|
2023-11-09 16:41:53 +01:00
|
|
|
dset = dataset == -1 ? 0 : dataset;
|
|
|
|
|
|
2022-08-19 01:23:45 +02:00
|
|
|
if(idx < 0 ) idx = 0;
|
|
|
|
|
delta = gr->gw;
|
|
|
|
|
wwx1 = get_raw_value(dset, idx, 0);
|
2023-10-11 14:05:27 +02:00
|
|
|
wwx2 = get_raw_value(dset, idx, xctx->raw->npoints[dset] - 1);
|
2023-11-09 16:41:53 +01:00
|
|
|
if(wwx1 == wwx2) wwx2 += 1e-6;
|
2022-08-19 01:23:45 +02:00
|
|
|
if(gr->logx) {
|
|
|
|
|
wwx1 = mylog10(wwx1);
|
|
|
|
|
wwx2 = mylog10(wwx2);
|
|
|
|
|
}
|
|
|
|
|
ccx = (gr->x2 - gr->x1) / (wwx2 - wwx1);
|
|
|
|
|
ddx = gr->x1 - wwx1 * ccx;
|
|
|
|
|
pp = (xctx->mousex_snap - ddx) / ccx;
|
|
|
|
|
xx1 = pp - delta / 2.0;
|
|
|
|
|
xx2 = pp + delta / 2.0;
|
2023-11-09 16:41:53 +01:00
|
|
|
|
2023-12-31 20:33:08 +01:00
|
|
|
if(switched) extra_rawfile(5, NULL, NULL, -1.0, -1.0); /* switch back to previous raw file */
|
2023-11-09 16:41:53 +01:00
|
|
|
|
2022-08-19 01:23:45 +02:00
|
|
|
}
|
|
|
|
|
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) && !xctx->graph_left && !xctx->graph_top) {
|
|
|
|
|
/* parameters for zoom area by mouse drag */
|
|
|
|
|
xx1 = G_X(xctx->mx_double_save);
|
|
|
|
|
xx2 = G_X(xctx->mousex_snap);
|
2022-09-07 09:31:09 +02:00
|
|
|
if(state & ShiftMask) {
|
|
|
|
|
if(xx1 < xx2) { double tmp; tmp = xx1; xx1 = xx2; xx2 = tmp; }
|
|
|
|
|
} else {
|
|
|
|
|
if(xx2 < xx1) { double tmp; tmp = xx1; xx1 = xx2; xx2 = tmp; }
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-19 01:23:45 +02:00
|
|
|
if(xx1 == xx2) xx2 += 1e-6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-12-31 11:58:28 +01:00
|
|
|
/* second loop: after having determined the master graph do the others */
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
|
2022-01-06 01:10:06 +01:00
|
|
|
r = &xctx->rect[GRIDLAYER][i];
|
2022-01-27 20:47:27 +01:00
|
|
|
need_redraw = 0;
|
2023-11-09 16:41:53 +01:00
|
|
|
if( !(r->flags & 1) ) continue; /* 1: graph; 3: graph_unlocked */
|
2022-01-06 07:37:44 +01:00
|
|
|
gr->gx1 = gr->master_gx1;
|
|
|
|
|
gr->gx2 = gr->master_gx2;
|
|
|
|
|
gr->gw = gr->master_gw;
|
2023-02-26 11:22:19 +01:00
|
|
|
setup_graph_data(i, 1, gr); /* skip flag set, no reload x1 and x2 fields */
|
2023-10-11 14:05:27 +02:00
|
|
|
if(gr->dataset >= 0 /* && gr->dataset < xctx->raw->datasets */) dataset =gr->dataset;
|
2022-02-05 00:28:06 +01:00
|
|
|
else dataset = -1;
|
2022-01-03 18:43:34 +01:00
|
|
|
/* destroy / show measurement widget */
|
|
|
|
|
if(i == xctx->graph_master) {
|
|
|
|
|
if(xctx->graph_flags & 64) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if( POINTINSIDE(xctx->mousex, xctx->mousey, gr->x1, gr->y1, gr->x2, gr->y2)) {
|
2022-01-03 18:43:34 +01:00
|
|
|
char sx[100], sy[100];
|
2022-02-02 18:33:16 +01:00
|
|
|
double xval, yval;
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
|
|
|
|
double deltag = gr->gy2 - gr->gy1;
|
2022-01-04 05:54:25 +01:00
|
|
|
double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
|
|
|
|
|
double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
|
2022-01-03 18:43:34 +01:00
|
|
|
double c = s1 * deltag;
|
|
|
|
|
deltag = deltag * s1 / s2;
|
|
|
|
|
yval=(DG_Y(xctx->mousey) - c) / s2;
|
2022-01-05 23:07:08 +01:00
|
|
|
yval=fmod(yval, deltag ) + gr->gy1;
|
|
|
|
|
if(yval > gr->gy2 + deltag * (s1 + s2) * 0.5) yval -= deltag;
|
2022-01-03 18:43:34 +01:00
|
|
|
} else {
|
|
|
|
|
yval = G_Y(xctx->mousey);
|
|
|
|
|
}
|
2022-02-02 18:33:16 +01:00
|
|
|
|
|
|
|
|
xval = G_X(xctx->mousex);
|
2022-08-05 00:57:03 +02:00
|
|
|
if(gr->logx) xval = pow(10, xval);
|
2022-08-08 01:18:42 +02:00
|
|
|
if(gr->logy) yval = pow(10, yval);
|
|
|
|
|
if(gr->unitx != 1.0)
|
2022-06-29 11:47:10 +02:00
|
|
|
my_snprintf(sx, S(sx), "%.5g%c", gr->unitx * xval, gr->unitx_suffix);
|
2022-02-02 18:33:16 +01:00
|
|
|
else
|
2023-09-28 00:30:00 +02:00
|
|
|
my_strncpy(sx, dtoa_eng(xval), S(sx));
|
2022-02-02 18:33:16 +01:00
|
|
|
|
2022-08-08 01:18:42 +02:00
|
|
|
if(gr->unitx != 1.0)
|
2022-02-02 18:33:16 +01:00
|
|
|
my_snprintf(sy, S(sy), "%.4g%c", gr->unity * yval, gr->unity_suffix);
|
|
|
|
|
else
|
2023-09-28 00:30:00 +02:00
|
|
|
my_strncpy(sy, dtoa_eng(yval), S(sy));
|
2022-01-03 18:43:34 +01:00
|
|
|
|
|
|
|
|
tclvareval("set measure_text \"y=", sy, "\nx=", sx, "\"", NULL);
|
|
|
|
|
tcleval("graph_show_measure");
|
|
|
|
|
} else {
|
2022-01-04 05:54:25 +01:00
|
|
|
tcleval("graph_show_measure stop");
|
2022-01-03 18:43:34 +01:00
|
|
|
}
|
2022-09-28 19:14:31 +02:00
|
|
|
} /* if(xctx->graph_flags & 64) */
|
|
|
|
|
} /* if(i == xctx->graph_master) */
|
2022-01-06 01:10:06 +01:00
|
|
|
dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
|
2022-01-02 04:42:15 +01:00
|
|
|
if( event == KeyPress || event == ButtonPress || event == MotionNotify ) {
|
|
|
|
|
/* move cursor1 */
|
|
|
|
|
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
|
|
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
|
|
|
|
/* move cursor2 */
|
|
|
|
|
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) {
|
2022-09-18 11:06:48 +02:00
|
|
|
if(tclgetboolvar("live_cursor2_backannotate")) {
|
|
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
}
|
2022-09-18 05:29:16 +02:00
|
|
|
else need_redraw = 1;
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else /* drag waves with mouse */
|
|
|
|
|
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom) {
|
|
|
|
|
double delta;
|
|
|
|
|
if(xctx->graph_left) {
|
|
|
|
|
if(i == xctx->graph_master) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
|
|
|
|
delta = gr->posh;
|
2022-01-02 22:24:44 +01:00
|
|
|
delta_threshold = 0.01;
|
2022-01-05 23:07:08 +01:00
|
|
|
if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->dcy * delta) * delta_threshold) {
|
|
|
|
|
yy1 = gr->ypos1 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
|
|
|
|
|
yy2 = gr->ypos2 + (xctx->my_double_save - xctx->mousey_snap) / gr->dcy;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
|
2022-01-02 22:24:44 +01:00
|
|
|
xctx->my_double_save = xctx->mousey_snap;
|
|
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-01-05 23:07:08 +01:00
|
|
|
delta = gr->gh / gr->divy;
|
2022-01-02 22:24:44 +01:00
|
|
|
delta_threshold = 0.01;
|
2022-01-05 23:07:08 +01:00
|
|
|
if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(gr->cy * delta) * delta_threshold) {
|
|
|
|
|
yy1 = gr->gy1 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
|
|
|
|
|
yy2 = gr->gy2 + (xctx->my_double_save - xctx->mousey_snap) / gr->cy;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2022-01-02 22:24:44 +01:00
|
|
|
xctx->my_double_save = xctx->mousey_snap;
|
|
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-01-21 02:16:51 +01:00
|
|
|
save_mouse_at_end = 1;
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2022-01-02 04:42:15 +01:00
|
|
|
delta_threshold = 0.01;
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-09-28 19:14:31 +02:00
|
|
|
dbg(1, "moving waves: %d\n", i);
|
2022-01-05 23:07:08 +01:00
|
|
|
if(fabs(xctx->mx_double_save - xctx->mousex_snap) > fabs(gr->cx * delta) * delta_threshold) {
|
2022-01-06 07:37:44 +01:00
|
|
|
xx1 = gr->gx1 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
|
|
|
|
|
xx2 = gr->gx2 + (xctx->mx_double_save - xctx->mousex_snap) / gr->cx;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-30 20:52:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if((button == Button5 && !(state & ShiftMask))) {
|
|
|
|
|
double delta;
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(i == xctx->graph_master) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
|
|
|
|
delta = gr->posh * 0.05;
|
|
|
|
|
yy1 = gr->ypos1 + delta;
|
|
|
|
|
yy2 = gr->ypos2 + delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
} else {
|
2022-01-05 23:07:08 +01:00
|
|
|
delta = gr->gh/ gr->divy;
|
2022-01-03 00:27:15 +01:00
|
|
|
delta_threshold = 1.0;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy1 = gr->gy1 + delta * delta_threshold;
|
|
|
|
|
yy2 = gr->gy2 + delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if( r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2021-12-31 11:58:28 +01:00
|
|
|
delta_threshold = 0.05;
|
2022-01-06 07:37:44 +01:00
|
|
|
xx1 = gr->gx1 - delta * delta_threshold;
|
|
|
|
|
xx2 =gr->gx2 - delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
2022-09-02 17:11:50 +02:00
|
|
|
else if((key == 't') ) {
|
2022-09-02 18:19:39 +02:00
|
|
|
if(track_dset != -2) {
|
2022-09-03 09:46:22 +02:00
|
|
|
const char *unlocked = strstr(get_tok_value(r->prop_ptr, "flags", 0), "unlocked");
|
2023-10-23 16:03:27 +02:00
|
|
|
int floaters = there_are_floaters();
|
2022-09-03 09:46:22 +02:00
|
|
|
if(i == xctx->graph_master || !unlocked) {
|
2022-09-19 02:04:14 +02:00
|
|
|
gr->dataset = track_dset;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(track_dset)));
|
2023-10-23 16:03:27 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/* do this here to update texts printing current dataset in graph
|
|
|
|
|
* tcleval([xschem getprop rect 2 n dataset]) */
|
|
|
|
|
if(i == xctx->graph_master && floaters) {
|
|
|
|
|
set_modify(-2); /* update floater caches to reflect actual backannotation */
|
|
|
|
|
redraw_all_at_end = 1;
|
2022-09-02 17:11:50 +02:00
|
|
|
}
|
2024-03-30 19:20:51 +01:00
|
|
|
if((xctx->graph_flags & 4) && tclgetboolvar("live_cursor2_backannotate")) {
|
2023-05-16 09:52:23 +02:00
|
|
|
if(i == xctx->graph_master) {
|
2024-03-30 19:20:51 +01:00
|
|
|
backannotate_at_cursor_b_pos(r, gr);
|
2023-05-16 09:52:23 +02:00
|
|
|
}
|
2022-09-19 02:04:14 +02:00
|
|
|
redraw_all_at_end = 1;
|
|
|
|
|
} else {
|
2023-10-23 16:03:27 +02:00
|
|
|
if(!redraw_all_at_end) need_redraw = 1;
|
2022-09-19 02:04:14 +02:00
|
|
|
}
|
2024-03-30 19:20:51 +01:00
|
|
|
|
2022-09-02 17:11:50 +02:00
|
|
|
}
|
|
|
|
|
} /* key == 't' */
|
2022-01-02 04:42:15 +01:00
|
|
|
else if(key == XK_Left) {
|
|
|
|
|
double delta;
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(!gr->digital && i == xctx->graph_master) {
|
2022-01-02 04:42:15 +01:00
|
|
|
double m = G_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->gy1;
|
|
|
|
|
double b = gr->gy2 -m;
|
|
|
|
|
double delta = gr->gh;
|
2022-01-02 04:42:15 +01:00
|
|
|
double var = delta * 0.2;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->gy2 + var * b / delta;
|
|
|
|
|
yy1 = gr->gy1 - var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
} else {
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2022-01-02 04:42:15 +01:00
|
|
|
delta_threshold = 0.05;
|
2022-01-06 07:37:44 +01:00
|
|
|
xx1 = gr->gx1 - delta * delta_threshold;
|
|
|
|
|
xx2 = gr->gx2 - delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2022-01-02 04:42:15 +01:00
|
|
|
need_redraw = 1;
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(button == Button4 && !(state & ShiftMask)) {
|
|
|
|
|
double delta;
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(i == xctx->graph_master) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
|
|
|
|
delta = gr->posh * 0.05;
|
|
|
|
|
yy1 = gr->ypos1 - delta;
|
|
|
|
|
yy2 = gr->ypos2 - delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
} else {
|
2022-01-05 23:07:08 +01:00
|
|
|
delta = gr->gh / gr->divy;
|
2022-01-03 00:27:15 +01:00
|
|
|
delta_threshold = 1.0;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy1 = gr->gy1 - delta * delta_threshold;
|
|
|
|
|
yy2 = gr->gy2 - delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2021-12-31 11:58:28 +01:00
|
|
|
delta_threshold = 0.05;
|
2022-01-06 07:37:44 +01:00
|
|
|
xx1 = gr->gx1 + delta * delta_threshold;
|
|
|
|
|
xx2 = gr->gx2 + delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(key == XK_Right) {
|
|
|
|
|
double delta;
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(!gr->digital && i == xctx->graph_master) {
|
2022-01-02 04:42:15 +01:00
|
|
|
double m = G_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->gy1;
|
|
|
|
|
double b = gr->gy2 -m;
|
|
|
|
|
double delta = gr->gh;
|
2022-01-02 04:42:15 +01:00
|
|
|
double var = delta * 0.2;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->gy2 - var * b / delta;
|
|
|
|
|
yy1 = gr->gy1 + var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
} else {
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2022-01-02 04:42:15 +01:00
|
|
|
delta_threshold = 0.05;
|
2022-01-06 07:37:44 +01:00
|
|
|
xx1 = gr->gx1 + delta * delta_threshold;
|
|
|
|
|
xx2 = gr->gx2 + delta * delta_threshold;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2022-01-02 04:42:15 +01:00
|
|
|
need_redraw = 1;
|
Better axis label placement, smooth waves move/zoom with mouse, compile option to store sim data as floats instead of doubles, option for axis scaling (p,n,u,m,k,M,G), load waveforms command is a toggle (load / free)
2021-12-24 12:17:00 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(button == Button5 && (state & ShiftMask)) {
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(i == xctx->graph_master) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
2022-01-03 00:27:15 +01:00
|
|
|
double m = DG_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->ypos1;
|
|
|
|
|
double b = gr->ypos2 -m;
|
|
|
|
|
double delta = gr->posh;
|
2022-01-03 00:27:15 +01:00
|
|
|
double var = delta * 0.05;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->ypos2 + var * b / delta;
|
|
|
|
|
yy1 = gr->ypos1 - var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
double m = G_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->gy1;
|
|
|
|
|
double b = gr->gy2 -m;
|
|
|
|
|
double delta = (gr->gy2 - gr->gy1);
|
2022-01-03 00:27:15 +01:00
|
|
|
double var = delta * 0.2;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->gy2 + var * b / delta;
|
|
|
|
|
yy1 = gr->gy1 - var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
double var = 0.2 * gr->gw;
|
|
|
|
|
xx2 = gr->gx2 + var * (1 - zoom_m);
|
|
|
|
|
xx1 = gr->gx1 - var * zoom_m;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(key == XK_Down) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(!xctx->graph_left) {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
double var = 0.2 * gr->gw;
|
|
|
|
|
xx2 = gr->gx2 + var * (1 - zoom_m);
|
|
|
|
|
xx1 = gr->gx1 - var * zoom_m;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(button == Button4 && (state & ShiftMask)) {
|
|
|
|
|
if(xctx->graph_left) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(i == xctx->graph_master) {
|
2022-01-05 23:07:08 +01:00
|
|
|
if(gr->digital) {
|
2022-01-03 00:27:15 +01:00
|
|
|
double m = DG_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->ypos1;
|
|
|
|
|
double b = gr->ypos2 -m;
|
|
|
|
|
double delta = (gr->ypos2 - gr->ypos1);
|
2022-01-03 00:27:15 +01:00
|
|
|
double var = delta * 0.05;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->ypos2 - var * b / delta;
|
|
|
|
|
yy1 = gr->ypos1 + var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "ypos2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
} else {
|
|
|
|
|
double m = G_Y(xctx->mousey);
|
2022-01-05 23:07:08 +01:00
|
|
|
double a = m - gr->gy1;
|
|
|
|
|
double b = gr->gy2 -m;
|
|
|
|
|
double delta = (gr->gy2 - gr->gy1);
|
2022-01-03 00:27:15 +01:00
|
|
|
double var = delta * 0.2;
|
2022-01-05 23:07:08 +01:00
|
|
|
yy2 = gr->gy2 - var * b / delta;
|
|
|
|
|
yy1 = gr->gy1 + var * a / delta;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2)));
|
2022-01-03 00:27:15 +01:00
|
|
|
need_redraw = 1;
|
|
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
double var = 0.2 * gr->gw;
|
|
|
|
|
xx2 = gr->gx2 - var * (1 - zoom_m);
|
|
|
|
|
xx1 = gr->gx1 + var * zoom_m;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(key == XK_Up) {
|
2022-01-03 00:27:15 +01:00
|
|
|
if(!xctx->graph_left) {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-06 07:37:44 +01:00
|
|
|
double var = 0.2 * gr->gw;
|
|
|
|
|
xx2 = gr->gx2 - var * (1 - zoom_m);
|
|
|
|
|
xx1 = gr->gx1 + var * zoom_m;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-27 14:12:55 +01:00
|
|
|
}
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
else if(key == 'f') {
|
2023-10-11 14:05:27 +02:00
|
|
|
if(xctx->raw && xctx->raw->values) {
|
2022-08-19 01:23:45 +02:00
|
|
|
if(xctx->graph_left) { /* full Y zoom*/
|
2022-01-03 04:20:45 +01:00
|
|
|
if(i == xctx->graph_master) {
|
2023-02-26 13:07:14 +01:00
|
|
|
need_redraw = graph_fullyzoom(r, gr, dataset);
|
2022-02-17 01:22:15 +01:00
|
|
|
} /* graph_master */
|
2022-08-19 01:23:45 +02:00
|
|
|
} else { /* not graph_left, full X zoom*/
|
|
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2023-10-17 00:42:31 +02:00
|
|
|
need_redraw = graph_fullxzoom(i, gr, dataset);
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2021-12-30 20:52:15 +01:00
|
|
|
}
|
2023-10-11 14:05:27 +02:00
|
|
|
} /* raw->values */
|
2022-02-17 01:22:15 +01:00
|
|
|
} /* key == 'f' */
|
2022-08-19 01:23:45 +02:00
|
|
|
/* absolute positioning by mouse drag in bottom graph area */
|
2022-01-02 04:42:15 +01:00
|
|
|
else if( event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) {
|
|
|
|
|
|
2023-10-11 14:05:27 +02:00
|
|
|
if(xctx->raw && xctx->raw->values) {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-08-19 01:23:45 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* this calculation is done in 1st loop, only for master graph
|
|
|
|
|
* and applied to all locked graphs
|
2024-02-25 12:21:13 +01:00
|
|
|
int idx = get_raw_index(find_nth(get_tok_value(r->prop_ptr, "sweep", 0), ", ", "\"", 0, 1), NULL);
|
2022-02-05 00:28:06 +01:00
|
|
|
int dset = dataset == -1 ? 0 : dataset;
|
2022-08-19 01:23:45 +02:00
|
|
|
double wwx1, wwx2, pp, delta, ccx, ddx;
|
|
|
|
|
|
2022-08-08 09:52:33 +02:00
|
|
|
if(idx < 0 ) idx = 0;
|
2022-01-06 07:37:44 +01:00
|
|
|
delta = gr->gw;
|
2022-08-08 09:52:33 +02:00
|
|
|
wwx1 = get_raw_value(dset, idx, 0);
|
2023-10-11 14:05:27 +02:00
|
|
|
wwx2 = get_raw_value(dset, idx, xctx->raw->npoints[dset] - 1);
|
2022-08-08 09:52:33 +02:00
|
|
|
if(gr->logx) {
|
|
|
|
|
wwx1 = mylog10(wwx1);
|
|
|
|
|
wwx2 = mylog10(wwx2);
|
|
|
|
|
}
|
2022-01-05 23:07:08 +01:00
|
|
|
ccx = (gr->x2 - gr->x1) / (wwx2 - wwx1);
|
|
|
|
|
ddx = gr->x1 - wwx1 * ccx;
|
2022-08-19 01:23:45 +02:00
|
|
|
pp = (xctx->mousex_snap - ddx) / ccx;
|
|
|
|
|
xx1 = pp - delta / 2.0;
|
|
|
|
|
xx2 = pp + delta / 2.0;
|
|
|
|
|
*/
|
|
|
|
|
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2021-12-27 18:42:56 +01:00
|
|
|
need_redraw = 1;
|
2021-12-25 13:37:49 +01:00
|
|
|
}
|
2021-12-26 14:33:54 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} /* if( event == KeyPress || event == ButtonPress || event == MotionNotify ) */
|
2024-01-05 11:21:34 +01:00
|
|
|
else if( event == ButtonRelease) {
|
2022-01-02 04:42:15 +01:00
|
|
|
if(button != Button3) {
|
|
|
|
|
xctx->ui_state &= ~GRAPHPAN;
|
|
|
|
|
xctx->graph_flags &= ~(16 | 32); /* clear move cursor flags */
|
|
|
|
|
}
|
2022-01-28 04:44:07 +01:00
|
|
|
/* zoom area by mouse drag */
|
|
|
|
|
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) &&
|
|
|
|
|
!xctx->graph_left && !xctx->graph_top) {
|
2022-08-19 01:23:45 +02:00
|
|
|
/* selected or locked or master */
|
2022-01-02 04:42:15 +01:00
|
|
|
if(r->sel || !(r->flags & 2) || i == xctx->graph_master) {
|
2022-01-28 04:44:07 +01:00
|
|
|
if(xctx->mx_double_save != xctx->mousex_snap) {
|
|
|
|
|
clear_graphpan_at_end = 1;
|
2022-08-19 01:23:45 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* this calculation is done in 1st loop above,
|
|
|
|
|
* only for graph master and applied to all locked graphs
|
2022-01-28 04:44:07 +01:00
|
|
|
xx1 = G_X(xctx->mx_double_save);
|
|
|
|
|
xx2 = G_X(xctx->mousex_snap);
|
|
|
|
|
if(xx2 < xx1) { tmp = xx1; xx1 = xx2; xx2 = tmp; }
|
|
|
|
|
if(xx1 == xx2) xx2 += 1e-6;
|
2022-08-19 01:23:45 +02:00
|
|
|
*/
|
2023-09-28 00:30:00 +02:00
|
|
|
if(xx1 == xx2) xx2 += 1e-6;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1)));
|
|
|
|
|
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2)));
|
2022-01-28 04:44:07 +01:00
|
|
|
need_redraw = 1;
|
2024-01-05 11:21:34 +01:00
|
|
|
} else if(i == xctx->graph_master) {
|
|
|
|
|
clear_graphpan_at_end = 1;
|
2022-01-28 04:44:07 +01:00
|
|
|
}
|
2021-12-27 18:42:56 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
}
|
|
|
|
|
} /* else if( event == ButtonRelease) */
|
2022-01-27 20:47:27 +01:00
|
|
|
if(need_redraw || need_all_redraw) {
|
2023-02-26 11:22:19 +01:00
|
|
|
setup_graph_data(i, 0, gr);
|
2022-09-25 21:11:52 +02:00
|
|
|
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in each graph box */
|
2021-12-30 15:45:38 +01:00
|
|
|
}
|
2022-01-02 04:42:15 +01:00
|
|
|
} /* for(i=0; i< xctx->rects[GRIDLAYER]; i++ */
|
2022-01-21 02:16:51 +01:00
|
|
|
|
2022-09-18 11:06:48 +02:00
|
|
|
if(redraw_all_at_end ==1) {
|
|
|
|
|
draw();
|
|
|
|
|
redraw_all_at_end = 0;
|
|
|
|
|
}
|
2022-01-28 04:44:07 +01:00
|
|
|
if(clear_graphpan_at_end) xctx->ui_state &= ~GRAPHPAN;
|
2022-01-21 02:16:51 +01:00
|
|
|
/* update saved mouse position after processing all graphs */
|
2022-09-28 19:14:31 +02:00
|
|
|
if(save_mouse_at_end) {
|
|
|
|
|
if( fabs(xctx->mx_double_save - xctx->mousex_snap) > fabs(gr->master_cx * gr->master_gw) * delta_threshold) {
|
|
|
|
|
dbg(1, "save mose pos\n");
|
|
|
|
|
xctx->mx_double_save = xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save = xctx->mousey_snap;
|
|
|
|
|
}
|
2022-01-21 02:16:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-12-22 04:39:23 +01:00
|
|
|
draw_selection(xctx->gc[SELLAYER], 0);
|
2021-12-22 18:25:15 +01:00
|
|
|
#if HAS_CAIRO==1
|
|
|
|
|
cairo_restore(xctx->cairo_ctx);
|
|
|
|
|
cairo_restore(xctx->cairo_save_ctx);
|
|
|
|
|
#endif
|
2021-12-22 04:39:23 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-04 18:29:15 +01:00
|
|
|
/* del == 0 : delete and draw
|
|
|
|
|
* del == 1 : delete
|
|
|
|
|
* del == 2 : draw */
|
2023-09-22 12:48:22 +02:00
|
|
|
void draw_crosshair(int del)
|
|
|
|
|
{
|
|
|
|
|
int sdw, sdp;
|
2023-09-29 00:30:43 +02:00
|
|
|
dbg(1, "draw_crosshair(): del=%d\n", del);
|
2023-09-22 12:48:22 +02:00
|
|
|
sdw = xctx->draw_window;
|
|
|
|
|
sdp = xctx->draw_pixmap;
|
|
|
|
|
|
2023-09-29 10:09:13 +02:00
|
|
|
if(!xctx->mouse_inside) return;
|
2023-09-22 12:48:22 +02:00
|
|
|
xctx->draw_pixmap = 0;
|
|
|
|
|
xctx->draw_window = 1;
|
2023-11-04 18:29:15 +01:00
|
|
|
if(del != 2) {
|
|
|
|
|
if(fix_broken_tiled_fill || !_unix) {
|
|
|
|
|
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0],
|
|
|
|
|
0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw),
|
|
|
|
|
xctx->xrect[0].width, 4 * INT_WIDTH(xctx->lw),
|
|
|
|
|
0, (int)Y_TO_SCREEN(xctx->prev_crossy) - 2 * INT_WIDTH(xctx->lw));
|
|
|
|
|
|
|
|
|
|
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0],
|
|
|
|
|
(int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw), 0,
|
|
|
|
|
4 * INT_WIDTH(xctx->lw), xctx->xrect[0].height,
|
|
|
|
|
(int)X_TO_SCREEN(xctx->prev_crossx) - 2 * INT_WIDTH(xctx->lw), 0);
|
|
|
|
|
} else {
|
|
|
|
|
drawtempline(xctx->gctiled, NOW, X_TO_XSCHEM(xctx->areax1),
|
|
|
|
|
xctx->prev_crossy, X_TO_XSCHEM(xctx->areax2), xctx->prev_crossy);
|
|
|
|
|
drawtempline(xctx->gctiled, NOW, xctx->prev_crossx, Y_TO_XSCHEM(xctx->areay1),
|
|
|
|
|
xctx->prev_crossx, Y_TO_XSCHEM(xctx->areay2));
|
|
|
|
|
}
|
2023-09-27 01:28:31 +02:00
|
|
|
}
|
2023-11-04 18:29:15 +01:00
|
|
|
if(del != 1) {
|
2023-09-29 00:30:43 +02:00
|
|
|
drawline(xctx->crosshair_layer, NOW,X_TO_XSCHEM( xctx->areax1), xctx->mousey_snap,
|
2023-09-22 13:13:35 +02:00
|
|
|
X_TO_XSCHEM(xctx->areax2), xctx->mousey_snap, 3, NULL);
|
2023-09-29 00:30:43 +02:00
|
|
|
drawline(xctx->crosshair_layer, NOW, xctx->mousex_snap, Y_TO_XSCHEM(xctx->areay1),
|
2023-09-22 13:13:35 +02:00
|
|
|
xctx->mousex_snap, Y_TO_XSCHEM(xctx->areay2), 3, NULL);
|
2023-09-22 12:48:22 +02:00
|
|
|
}
|
2023-09-29 00:30:43 +02:00
|
|
|
draw_selection(xctx->gc[SELLAYER], 0);
|
2023-09-22 12:48:22 +02:00
|
|
|
xctx->prev_crossx = xctx->mousex_snap;
|
|
|
|
|
xctx->prev_crossy = xctx->mousey_snap;
|
|
|
|
|
|
|
|
|
|
xctx->draw_window = sdw;
|
|
|
|
|
xctx->draw_pixmap = sdp;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 14:38:32 +01:00
|
|
|
/* complete the STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */
|
2024-03-07 17:48:41 +01:00
|
|
|
static int end_place_move_copy_zoom()
|
2024-03-04 14:38:32 +01:00
|
|
|
{
|
|
|
|
|
if(xctx->ui_state & STARTZOOM) {
|
|
|
|
|
zoom_rectangle(END);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTWIRE) {
|
|
|
|
|
if(tclgetboolvar("persistent_command")) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 2) {
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 1) {
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-04 14:38:32 +01:00
|
|
|
new_wire(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
new_wire(PLACE|END, xctx->mousex_snap, xctx->mousey_snap);
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTARC) {
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(SET, 0, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTLINE) {
|
|
|
|
|
if(tclgetboolvar("persistent_command")) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv != 2) {
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) {
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
} else {
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(PLACE|END, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTRECT) {
|
2024-03-06 12:53:49 +01:00
|
|
|
new_rect(PLACE|END,xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTPOLYGON) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(ADD, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTMOVE) {
|
|
|
|
|
move_objects(END,0,0,0);
|
|
|
|
|
xctx->ui_state &=~START_SYMPIN;
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTCOPY) {
|
|
|
|
|
copy_objects(END);
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-04 14:38:32 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int check_menu_start_commands(double c_snap)
|
|
|
|
|
{
|
|
|
|
|
if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRECUT)) {
|
|
|
|
|
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 1);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRECUT2)) {
|
|
|
|
|
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 0);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTMOVE)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
/* stretch nets that land on selected instance pins if connect_by_kissing == 2 */
|
|
|
|
|
/* select_attached_nets(); */
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTWIRE)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
new_wire(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTSNAPWIRE)) {
|
|
|
|
|
double x, y;
|
|
|
|
|
|
|
|
|
|
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
|
|
|
|
|
xctx->mx_double_save = my_round(x / c_snap) * c_snap;
|
|
|
|
|
xctx->my_double_save = my_round(y / c_snap) * c_snap;
|
|
|
|
|
new_wire(PLACE, x, y);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTLINE)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTRECT)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTPOLYGON)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTARC)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTCIRCLE)) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if((xctx->ui_state & MENUSTART) && (xctx->ui_state2 & MENUSTARTZOOM)) {
|
|
|
|
|
zoom_rectangle(START);
|
|
|
|
|
xctx->ui_state &=~MENUSTART;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 16:33:20 +01:00
|
|
|
|
2024-03-06 16:27:14 +01:00
|
|
|
static int add_wire_from_inst_pin(Selected *sel, double mx, double my)
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
int i, type = sel->type;
|
|
|
|
|
double pinx0, piny0;
|
|
|
|
|
if(type == ELEMENT) {
|
|
|
|
|
int n = sel->n;
|
|
|
|
|
xSymbol *symbol = xctx->sym + xctx->inst[n].ptr;
|
|
|
|
|
int npin = symbol->rects[PINLAYER];
|
|
|
|
|
for(i = 0; i < npin; ++i) {
|
|
|
|
|
get_inst_pin_coord(n, i, &pinx0, &piny0);
|
|
|
|
|
if(pinx0 == mx && piny0 == my) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(i < npin) {
|
|
|
|
|
int save = xctx->modified;
|
|
|
|
|
dbg(1, "pin: %g %g\n", pinx0, piny0);
|
|
|
|
|
unselect_all(1);
|
|
|
|
|
xctx->push_undo();
|
|
|
|
|
storeobject(-1, pinx0, piny0, pinx0, piny0, WIRE, 0, SELECTED1, NULL);
|
|
|
|
|
set_modify(save);
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
xctx->prep_hash_wires=0;
|
|
|
|
|
xctx->need_reb_sel_arr = 1;
|
|
|
|
|
xctx->kissing = 1;
|
|
|
|
|
rebuild_selected_array();
|
2024-03-06 20:04:15 +01:00
|
|
|
move_objects(START,0,0,0);
|
2024-03-06 16:27:14 +01:00
|
|
|
res = 1;
|
|
|
|
|
}
|
2024-03-07 00:08:47 +01:00
|
|
|
} else if(type == WIRE) {
|
|
|
|
|
int n = sel->n;
|
|
|
|
|
double x1 = xctx->wire[n].x1;
|
|
|
|
|
double y1 = xctx->wire[n].y1;
|
|
|
|
|
double x2 = xctx->wire[n].x2;
|
|
|
|
|
double y2 = xctx->wire[n].y2;
|
|
|
|
|
if( (mx == x1 && my == y1) || (mx == x2 && my == y2) ) {
|
|
|
|
|
int save = xctx->modified;
|
|
|
|
|
unselect_all(1);
|
|
|
|
|
xctx->push_undo();
|
|
|
|
|
storeobject(-1, mx, my, mx, my, WIRE, 0, SELECTED1, NULL);
|
|
|
|
|
set_modify(save);
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
xctx->prep_hash_wires=0;
|
|
|
|
|
xctx->need_reb_sel_arr = 1;
|
|
|
|
|
xctx->kissing = 1;
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
res = 1;
|
|
|
|
|
}
|
2024-03-06 16:27:14 +01:00
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-03-04 17:13:36 +01:00
|
|
|
/* sets xctx->shape_point_selected */
|
|
|
|
|
static int edit_line_point(int state)
|
|
|
|
|
{
|
|
|
|
|
int line_n = -1, line_c = -1;
|
|
|
|
|
dbg(1, "1 Line selected\n");
|
|
|
|
|
line_n = xctx->sel_array[0].n;
|
|
|
|
|
line_c = xctx->sel_array[0].col;
|
|
|
|
|
/* lineangle point: Check is user is clicking a control point of a lineangle */
|
|
|
|
|
if(line_n >= 0) {
|
|
|
|
|
double ds = xctx->cadhalfdotsize ;
|
|
|
|
|
xLine *p = &xctx->line[line_c][line_n];
|
|
|
|
|
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x1 - ds, p->y1 - ds, p->x1 + ds, p->y1 + ds)) {
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED1;
|
|
|
|
|
}
|
|
|
|
|
else if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x2 - ds, p->y2 - ds, p->x2 + ds, p->y2 + ds)) {
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED2;
|
|
|
|
|
}
|
|
|
|
|
if(xctx->shape_point_selected) {
|
|
|
|
|
/* move one lineangle selected point */
|
|
|
|
|
if(!(state & (ControlMask | ShiftMask))){
|
2024-03-09 06:16:41 +01:00
|
|
|
/* xctx->push_undo(); */
|
2024-03-04 17:13:36 +01:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} /* if(xctx->shape_point_selected) */
|
|
|
|
|
} /* if(line_n >= 0) */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* sets xctx->shape_point_selected */
|
|
|
|
|
static int edit_wire_point(int state)
|
|
|
|
|
{
|
|
|
|
|
int wire_n = -1;
|
|
|
|
|
dbg(1, "1 Wire selected\n");
|
|
|
|
|
wire_n = xctx->sel_array[0].n;
|
2024-03-06 16:27:14 +01:00
|
|
|
/* wire point: Check is user is clicking a control point of a wire */
|
2024-03-04 17:13:36 +01:00
|
|
|
if(wire_n >= 0) {
|
|
|
|
|
double ds = xctx->cadhalfdotsize ;
|
|
|
|
|
xWire *p = &xctx->wire[wire_n];
|
|
|
|
|
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x1 - ds, p->y1 - ds, p->x1 + ds, p->y1 + ds)) {
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED1;
|
|
|
|
|
}
|
|
|
|
|
else if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x2 - ds, p->y2 - ds, p->x2 + ds, p->y2 + ds)) {
|
|
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED2;
|
|
|
|
|
}
|
|
|
|
|
if(xctx->shape_point_selected) {
|
2024-03-06 16:27:14 +01:00
|
|
|
/* move one wire selected point */
|
2024-03-04 17:13:36 +01:00
|
|
|
if(!(state & (ControlMask | ShiftMask))){
|
2024-03-09 06:16:41 +01:00
|
|
|
/* xctx->push_undo(); */
|
2024-03-04 17:13:36 +01:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} /* if(xctx->shape_point_selected) */
|
|
|
|
|
} /* if(wire_n >= 0) */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 16:33:20 +01:00
|
|
|
/* sets xctx->shape_point_selected */
|
|
|
|
|
static int edit_rect_point(int state)
|
|
|
|
|
{
|
|
|
|
|
int rect_n = -1, rect_c = -1;
|
2024-03-04 17:13:36 +01:00
|
|
|
dbg(1, "1 Rectangle selected\n");
|
2024-03-04 16:33:20 +01:00
|
|
|
rect_n = xctx->sel_array[0].n;
|
|
|
|
|
rect_c = xctx->sel_array[0].col;
|
|
|
|
|
/* rectangle point: Check is user is clicking a control point of a rectangle */
|
|
|
|
|
if(rect_n >= 0) {
|
2024-03-04 17:13:36 +01:00
|
|
|
double ds = xctx->cadhalfdotsize * 2;
|
2024-03-04 16:33:20 +01:00
|
|
|
xRect *p = &xctx->rect[rect_c][rect_n];
|
|
|
|
|
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
2024-03-05 02:54:35 +01:00
|
|
|
if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x1, p->y1, p->x1 + ds, p->y1 + ds)) {
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED1;
|
|
|
|
|
}
|
2024-03-05 02:54:35 +01:00
|
|
|
else if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x2 - ds, p->y1, p->x2, p->y1 + ds)) {
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED2;
|
|
|
|
|
}
|
2024-03-05 02:54:35 +01:00
|
|
|
else if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x1, p->y2 - ds, p->x1 + ds, p->y2)) {
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED3;
|
|
|
|
|
}
|
2024-03-05 02:54:35 +01:00
|
|
|
else if(POINTINSIDE(xctx->mousex, xctx->mousey, p->x2 - ds, p->y2 - ds, p->x2, p->y2)) {
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 1;
|
|
|
|
|
p->sel = SELECTED4;
|
|
|
|
|
}
|
|
|
|
|
if(xctx->shape_point_selected) {
|
|
|
|
|
/* move one rectangle selected point */
|
|
|
|
|
if(!(state & (ControlMask | ShiftMask))){
|
2024-03-09 06:16:41 +01:00
|
|
|
/* xctx->push_undo(); */
|
2024-03-04 16:33:20 +01:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} /* if(xctx->shape_point_selected) */
|
|
|
|
|
} /* if(rect_n >= 0) */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* sets xctx->shape_point_selected */
|
2024-03-04 14:38:32 +01:00
|
|
|
static int edit_polygon_point(int state)
|
|
|
|
|
{
|
|
|
|
|
int poly_n = -1, poly_c = -1;
|
|
|
|
|
dbg(1, "1 Polygon selected\n");
|
|
|
|
|
poly_n = xctx->sel_array[0].n;
|
|
|
|
|
poly_c = xctx->sel_array[0].col;
|
|
|
|
|
/* polygon point: Check is user is clicking a control point of a polygon */
|
|
|
|
|
if(poly_n >= 0) {
|
|
|
|
|
int i;
|
|
|
|
|
double ds = xctx->cadhalfdotsize;
|
|
|
|
|
int c = poly_c;
|
|
|
|
|
int n = poly_n;
|
|
|
|
|
xPoly *p = &xctx->poly[c][n];
|
|
|
|
|
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
for(i = 0; i < p->points; i++) {
|
|
|
|
|
if(
|
|
|
|
|
POINTINSIDE(xctx->mousex, xctx->mousey, p->x[i] - ds, p->y[i] - ds,
|
|
|
|
|
p->x[i] + ds, p->y[i] + ds)
|
|
|
|
|
) {
|
|
|
|
|
dbg(1, "selecting point %d\n", i);
|
|
|
|
|
p->selected_point[i] = 1;
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 1;
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-04 16:33:20 +01:00
|
|
|
if(xctx->shape_point_selected) {
|
2024-03-04 14:38:32 +01:00
|
|
|
int j;
|
|
|
|
|
int points = p->points;
|
|
|
|
|
|
|
|
|
|
/* add a new polygon/bezier point after selected one and start moving it*/
|
|
|
|
|
if(state & ShiftMask) {
|
|
|
|
|
xctx->push_undo();
|
|
|
|
|
points++;
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->x, sizeof(double) * points);
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->y, sizeof(double) * points);
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->selected_point, sizeof(unsigned short) * points);
|
|
|
|
|
p->selected_point[i] = 0;
|
|
|
|
|
for(j = points - 2; j > i; j--) {
|
|
|
|
|
p->x[j + 1] = p->x[j];
|
|
|
|
|
p->y[j + 1] = p->y[j];
|
|
|
|
|
p->selected_point[j + 1] = p->selected_point[j];
|
|
|
|
|
}
|
|
|
|
|
p->selected_point[i + 1] = 1;
|
|
|
|
|
p->x[i + 1] = p->x[i];
|
|
|
|
|
p->y[i + 1] = p->y[i];
|
|
|
|
|
p->points = points;
|
|
|
|
|
p->sel = SELECTED1;
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
/* delete polygon/bezier selected point */
|
|
|
|
|
else if(points > 2 && state & ControlMask) {
|
|
|
|
|
xctx->push_undo();
|
|
|
|
|
points--;
|
|
|
|
|
for(j = i ; j < points ; j++) {
|
|
|
|
|
p->x[j] = p->x[j + 1];
|
|
|
|
|
p->y[j] = p->y[j + 1];
|
|
|
|
|
p->selected_point[j] = p->selected_point[j + 1];
|
|
|
|
|
}
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->x, sizeof(double) * points);
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->y, sizeof(double) * points);
|
|
|
|
|
my_realloc(_ALLOC_ID_, &p->selected_point, sizeof(unsigned short) * points);
|
|
|
|
|
p->points = points;
|
|
|
|
|
p->sel = SELECTED;
|
|
|
|
|
return 1;
|
|
|
|
|
/* move one polygon/bezier selected point */
|
|
|
|
|
} else if(!(state & (ControlMask | ShiftMask))){
|
2024-03-09 06:16:41 +01:00
|
|
|
/* xctx->push_undo(); */
|
2024-03-04 16:33:20 +01:00
|
|
|
p->sel = SELECTED1;
|
2024-03-04 14:38:32 +01:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2024-03-04 16:33:20 +01:00
|
|
|
} /* if(xctx->shape_point_selected) */
|
2024-03-04 14:38:32 +01:00
|
|
|
} /* if(poly_n >= 0) */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 12:53:49 +01:00
|
|
|
static void context_menu_action(double mx, double my)
|
2024-03-04 14:38:32 +01:00
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
const char *status;
|
|
|
|
|
int prev_state;
|
|
|
|
|
xctx->semaphore++;
|
|
|
|
|
status = tcleval("context_menu");
|
|
|
|
|
xctx->semaphore--;
|
|
|
|
|
if(!status) return;
|
|
|
|
|
ret = atoi(status);
|
|
|
|
|
switch(ret) {
|
|
|
|
|
case 1:
|
2024-03-06 12:53:49 +01:00
|
|
|
start_place_symbol();
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
prev_state = xctx->ui_state;
|
|
|
|
|
start_wire(mx, my);
|
|
|
|
|
if(prev_state == STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv=0;
|
2024-03-04 14:38:32 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
prev_state = xctx->ui_state;
|
|
|
|
|
start_line(mx, my);
|
|
|
|
|
if(prev_state == STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv=0;
|
2024-03-04 14:38:32 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_rect(PLACE,mx, my);
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(PLACE, mx, my);
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
case 6: /* place text */
|
|
|
|
|
xctx->last_command = 0;
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-06 12:53:49 +01:00
|
|
|
if(place_text(0, mx, my)) { /* 1 = draw text */
|
2024-03-04 14:38:32 +01:00
|
|
|
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;
|
|
|
|
|
case 7: /* cut selection into clipboard */
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
if(xctx->lastsel) { /* 20071203 check if something selected */
|
|
|
|
|
save_selection(2);
|
|
|
|
|
delete(1/* to_push_undo */);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8: /* paste from clipboard */
|
|
|
|
|
merge_file(2,".sch");
|
|
|
|
|
break;
|
|
|
|
|
case 9: /* load most recent file */
|
|
|
|
|
tclvareval("xschem load [lindex $recentfile 0] gui", NULL);
|
|
|
|
|
break;
|
|
|
|
|
case 10: /* edit attributes */
|
|
|
|
|
edit_property(0);
|
|
|
|
|
break;
|
|
|
|
|
case 11: /* edit attributes in editor */
|
|
|
|
|
edit_property(1);
|
|
|
|
|
break;
|
|
|
|
|
case 12:
|
|
|
|
|
descend_schematic(0, 1, 1);
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
descend_symbol();
|
|
|
|
|
break;
|
|
|
|
|
case 14:
|
|
|
|
|
go_back(1);
|
|
|
|
|
break;
|
|
|
|
|
case 15: /* copy selection into clipboard */
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
if(xctx->lastsel) {
|
|
|
|
|
save_selection(2);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 16: /* move selection */
|
|
|
|
|
if(!(xctx->ui_state & (STARTMOVE | STARTCOPY))) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 17: /* duplicate selection */
|
|
|
|
|
if(!(xctx->ui_state & (STARTMOVE | STARTCOPY))) {
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
copy_objects(START);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 18: /* delete selection */
|
|
|
|
|
if(xctx->ui_state & SELECTION) delete(1/* to_push_undo */);
|
|
|
|
|
break;
|
|
|
|
|
case 19: /* place arc */
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 180., mx, my);
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
case 20: /* place circle */
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 360., mx, my);
|
2024-03-04 14:38:32 +01:00
|
|
|
break;
|
|
|
|
|
case 21: /* abort & redraw */
|
|
|
|
|
abort_operation();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 12:53:49 +01:00
|
|
|
/* Mouse wheel events */
|
2024-03-04 14:38:32 +01:00
|
|
|
static int handle_mouse_wheel(int event, int mx, int my, KeySym key, int button, int aux, int state)
|
|
|
|
|
{
|
|
|
|
|
if(button==Button5 && state == 0 ) {
|
|
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
view_unzoom(CADZOOMSTEP);
|
|
|
|
|
}
|
|
|
|
|
else if(button==Button4 && state == 0 ) {
|
|
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
view_zoom(CADZOOMSTEP);
|
|
|
|
|
}
|
|
|
|
|
else if(button==Button4 && (state & ShiftMask) && !(state & Button2Mask)) {
|
|
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
xctx->xorigin+=-CADMOVESTEP*xctx->zoom/2.;
|
|
|
|
|
draw();
|
|
|
|
|
redraw_w_a_l_r_p_rubbers();
|
|
|
|
|
}
|
|
|
|
|
else if(button==Button5 && (state & ShiftMask) && !(state & Button2Mask)) {
|
|
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
xctx->xorigin-=-CADMOVESTEP*xctx->zoom/2.;
|
|
|
|
|
draw();
|
|
|
|
|
redraw_w_a_l_r_p_rubbers();
|
|
|
|
|
}
|
|
|
|
|
else if(button==Button4 && (state & ControlMask) && !(state & Button2Mask)) {
|
|
|
|
|
xctx->yorigin+=-CADMOVESTEP*xctx->zoom/2.;
|
|
|
|
|
draw();
|
|
|
|
|
redraw_w_a_l_r_p_rubbers();
|
|
|
|
|
}
|
|
|
|
|
else if(button==Button5 && (state & ControlMask) && !(state & Button2Mask)) {
|
|
|
|
|
xctx->yorigin-=-CADMOVESTEP*xctx->zoom/2.;
|
|
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 02:54:35 +01:00
|
|
|
static void end_shape_point_edit()
|
|
|
|
|
{
|
2024-03-06 16:27:14 +01:00
|
|
|
int save = xctx->modified;
|
|
|
|
|
dbg(1, "%g %g %g %g\n",
|
|
|
|
|
xctx->mx_double_save, xctx->my_double_save, xctx->mousex_snap, xctx->mousey_snap);
|
2024-03-05 02:54:35 +01:00
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) {
|
|
|
|
|
int k;
|
|
|
|
|
int n = xctx->sel_array[0].n;
|
|
|
|
|
int c = xctx->sel_array[0].col;
|
|
|
|
|
move_objects(END,0,0,0);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-05 02:54:35 +01:00
|
|
|
xctx->poly[c][n].sel = SELECTED;
|
|
|
|
|
xctx->shape_point_selected = 0;
|
|
|
|
|
for(k=0; k<xctx->poly[c][n].points; ++k) {
|
|
|
|
|
xctx->poly[c][n].selected_point[k] = 0;
|
|
|
|
|
}
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->lastsel == 1 && xctx->sel_array[0].type==xRECT) {
|
|
|
|
|
int n = xctx->sel_array[0].n;
|
|
|
|
|
int c = xctx->sel_array[0].col;
|
|
|
|
|
move_objects(END,0,0,0);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-05 02:54:35 +01:00
|
|
|
xctx->rect[c][n].sel = SELECTED;
|
|
|
|
|
xctx->shape_point_selected = 0;
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->lastsel == 1 && xctx->sel_array[0].type==LINE) {
|
|
|
|
|
int n = xctx->sel_array[0].n;
|
|
|
|
|
int c = xctx->sel_array[0].col;
|
|
|
|
|
move_objects(END,0,0,0);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-05 02:54:35 +01:00
|
|
|
xctx->line[c][n].sel = SELECTED;
|
|
|
|
|
xctx->shape_point_selected = 0;
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->lastsel == 1 && xctx->sel_array[0].type==WIRE) {
|
|
|
|
|
int n = xctx->sel_array[0].n;
|
|
|
|
|
move_objects(END,0,0,0);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-05 02:54:35 +01:00
|
|
|
xctx->wire[n].sel = SELECTED;
|
|
|
|
|
xctx->shape_point_selected = 0;
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
}
|
2024-03-06 16:27:14 +01:00
|
|
|
if(xctx->mx_double_save == xctx->mousex_snap && xctx->my_double_save == xctx->mousey_snap) {
|
|
|
|
|
set_modify(save);
|
|
|
|
|
}
|
2024-03-05 02:54:35 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-20 03:53:56 +01:00
|
|
|
#if defined(__unix__) && HAS_CAIRO==1
|
|
|
|
|
static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key,
|
|
|
|
|
int button, int aux, int state)
|
|
|
|
|
{
|
|
|
|
|
static int grab_state = 0;
|
|
|
|
|
static int x1, y1, x2, y2;
|
|
|
|
|
int rmx, rmy, wmx, wmy;
|
|
|
|
|
unsigned int msq;
|
|
|
|
|
Window rw, cw;
|
|
|
|
|
XSetWindowAttributes winattr;
|
|
|
|
|
XGCValues gcv;
|
|
|
|
|
static GC gc = NULL;
|
|
|
|
|
static Window clientwin = 0;
|
|
|
|
|
static int first_motion = 1;
|
|
|
|
|
static int displayh = 0, displayw = 0;
|
|
|
|
|
static unsigned long white = 0;
|
|
|
|
|
|
|
|
|
|
if(grab_state == 0 && event == ButtonPress && button == Button1) {
|
|
|
|
|
unsigned long gcvm = GCFunction | GCForeground;
|
|
|
|
|
|
|
|
|
|
white = WhitePixel(display, screen_number);
|
|
|
|
|
displayh = DisplayHeight(display, screen_number);
|
|
|
|
|
displayw = DisplayWidth(display, screen_number);
|
|
|
|
|
|
|
|
|
|
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
|
|
|
|
|
gcv.function = GXxor;
|
|
|
|
|
gcv.foreground = white;
|
|
|
|
|
gc = XCreateGC(display, rw, gcvm, &gcv);
|
|
|
|
|
|
|
|
|
|
winattr.override_redirect = True;
|
|
|
|
|
clientwin = XCreateWindow(display, rw, 0, 0, displayw, displayh, 0, screendepth,
|
|
|
|
|
InputOutput, visual, CWOverrideRedirect, &winattr);
|
|
|
|
|
XMapRaised(display,clientwin);
|
|
|
|
|
|
|
|
|
|
x1 = rmx;
|
|
|
|
|
y1 = rmy;
|
|
|
|
|
dbg(1, "grabscreen(): got point1: %d %d\n", x1, y1);
|
|
|
|
|
grab_state = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(grab_state == 1 && event == MotionNotify) {
|
|
|
|
|
static int xx1, xx2, yy1, yy2;
|
|
|
|
|
xx1 = x1; yy1 = y1; xx2 = x2; yy2 = y2;
|
|
|
|
|
INT_RECTORDER(xx1, yy1, xx2, yy2);
|
|
|
|
|
dbg(1, "Motion: %d %d %d %d\n", xx1, yy1, xx2, yy2);
|
|
|
|
|
if(!first_motion) {
|
|
|
|
|
XDrawRectangle(display, clientwin, gc, xx1 - 1, yy1 - 1, xx2 - xx1 + 2, yy2 - yy1 + 2);
|
|
|
|
|
}
|
|
|
|
|
first_motion = 0;
|
|
|
|
|
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
|
|
|
|
|
x2 = xx2 = rmx;
|
|
|
|
|
y2 = yy2 = rmy;
|
|
|
|
|
xx1 = x1; yy1 = y1;
|
|
|
|
|
INT_RECTORDER(xx1, yy1, xx2, yy2);
|
|
|
|
|
XDrawRectangle(display, clientwin, gc, xx1 - 1, yy1 - 1, xx2 - xx1 + 2, yy2 - yy1 + 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(grab_state == 1 && event == ButtonRelease) {
|
|
|
|
|
int grab_w = 0, grab_h = 0;
|
|
|
|
|
cairo_surface_t *sfc = NULL, *subsfc = NULL;
|
|
|
|
|
png_to_byte_closure_t closure;
|
|
|
|
|
char *encoded_data = NULL;
|
|
|
|
|
size_t olength;
|
|
|
|
|
char *prop = NULL;
|
2024-03-21 22:10:27 +01:00
|
|
|
|
|
|
|
|
|
2024-03-20 03:53:56 +01:00
|
|
|
grab_state = 0;
|
|
|
|
|
first_motion = 1;
|
|
|
|
|
xctx->ui_state &= ~GRABSCREEN;
|
|
|
|
|
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
|
|
|
|
|
x2 = rmx;
|
|
|
|
|
y2 = rmy;
|
|
|
|
|
INT_RECTORDER(x1, y1, x2, y2);
|
2024-03-21 22:37:39 +01:00
|
|
|
tclvareval("grab release ", xctx->top_path, ".drw", NULL);
|
2024-03-20 03:53:56 +01:00
|
|
|
if(x2 - x1 > 10 && y2 -y1 > 10) {
|
2024-04-12 00:06:36 +02:00
|
|
|
xctx->push_undo();
|
2024-03-20 03:53:56 +01:00
|
|
|
grab_w = (x2 - x1 + 1);
|
|
|
|
|
grab_h = (y2 - y1 + 1);
|
|
|
|
|
dbg(1, "grabscreen(): grab area: %d %d - %d %d\n", x1, y1, x2, y2);
|
|
|
|
|
dbg(1, "grabscreen(): root w=%d, h=%d\n", displayw, displayh);
|
|
|
|
|
sfc = cairo_xlib_surface_create(display, rw, visual, displayw, displayh);
|
|
|
|
|
if(!sfc || cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
dbg(0, "grabscreen(): failure creating sfc\n");
|
|
|
|
|
XFreeGC(display, gc);
|
|
|
|
|
XDestroyWindow(display, clientwin);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
dbg(1, "sfc: w=%d, h=%d\n",
|
|
|
|
|
cairo_xlib_surface_get_width(sfc),
|
|
|
|
|
cairo_xlib_surface_get_height(sfc));
|
|
|
|
|
subsfc = cairo_surface_create_for_rectangle(sfc, x1, y1, grab_w, grab_h);
|
|
|
|
|
if(!subsfc || cairo_surface_status(subsfc) != CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
dbg(0, "grabscreen(): failure creating subsfc\n");
|
|
|
|
|
cairo_surface_destroy(sfc);
|
|
|
|
|
XFreeGC(display, gc);
|
|
|
|
|
XDestroyWindow(display, clientwin);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
closure.buffer = NULL;
|
|
|
|
|
closure.size = 0;
|
|
|
|
|
closure.pos = 0;
|
|
|
|
|
cairo_surface_write_to_png_stream(subsfc, png_writer, &closure);
|
|
|
|
|
cairo_surface_destroy(subsfc);
|
|
|
|
|
cairo_surface_destroy(sfc);
|
|
|
|
|
closure.size = closure.pos;
|
|
|
|
|
dbg(1, "closure.size = %ld\n", closure.size);
|
|
|
|
|
encoded_data = base64_encode((unsigned char *)closure.buffer, closure.size, &olength, 0);
|
|
|
|
|
dbg(1, "olength = %ld\n", olength);
|
|
|
|
|
my_free(_ALLOC_ID_, &closure.buffer);
|
|
|
|
|
my_mstrcat(_ALLOC_ID_, &prop, "flags=image,unscaled\nalpha=0.8\nimage_data=", encoded_data, NULL);
|
|
|
|
|
my_free(_ALLOC_ID_, &encoded_data);
|
|
|
|
|
storeobject(-1, xctx->mousex_snap, xctx->mousey_snap, xctx->mousex_snap + grab_w, xctx->mousey_snap + grab_h,
|
|
|
|
|
xRECT, GRIDLAYER, SELECTED, prop);
|
|
|
|
|
my_free(_ALLOC_ID_, &prop);
|
|
|
|
|
xctx->need_reb_sel_arr=1;
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
xctx->ui_state |= START_SYMPIN;
|
|
|
|
|
}
|
|
|
|
|
XFreeGC(display, gc);
|
|
|
|
|
XDestroyWindow(display, clientwin);
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* main window callback */
|
|
|
|
|
/* mx and my are set to the mouse coord. relative to window */
|
2022-09-04 14:16:38 +02:00
|
|
|
/* winpath: set to .drw or sub windows .x1.drw, .x2.drw, ... */
|
2021-11-09 19:05:56 +01:00
|
|
|
int callback(const char *winpath, int event, int mx, int my, KeySym key,
|
2020-10-12 13:13:31 +02:00
|
|
|
int button, int aux, int state)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-16 22:28:10 +01:00
|
|
|
char str[PATH_MAX + 100];
|
2020-08-08 15:47:34 +02:00
|
|
|
struct stat buf;
|
2021-11-16 22:28:10 +01:00
|
|
|
int redraw_only;
|
2021-11-17 01:30:37 +01:00
|
|
|
double c_snap;
|
2020-09-22 21:02:51 +02:00
|
|
|
#ifndef __unix__
|
2021-11-10 13:43:08 +01:00
|
|
|
short cstate = GetKeyState(VK_CAPITAL);
|
|
|
|
|
short nstate = GetKeyState(VK_NUMLOCK);
|
2021-11-16 22:28:10 +01:00
|
|
|
#else
|
|
|
|
|
XKeyboardState kbdstate;
|
|
|
|
|
#endif
|
2023-09-22 12:48:22 +02:00
|
|
|
int draw_xhair = tclgetboolvar("draw_crosshair");
|
2023-09-28 21:03:28 +02:00
|
|
|
int rstate; /* (reduced state, without ShiftMask) */
|
2021-11-16 22:28:10 +01:00
|
|
|
|
2023-10-28 11:19:23 +02:00
|
|
|
/* this fix uses an alternative method for getting mouse coordinates on KeyPress/KeyRelease
|
|
|
|
|
* events. Some remote connection softwares do not generate the correct coordinates
|
|
|
|
|
* on such events */
|
|
|
|
|
if(fix_mouse_coord) {
|
|
|
|
|
if(event == KeyPress || event == KeyRelease) {
|
|
|
|
|
tclvareval("getmousex ", winpath, NULL);
|
|
|
|
|
mx = atoi(tclresult());
|
|
|
|
|
tclvareval("getmousey ", winpath, NULL);
|
|
|
|
|
my = atoi(tclresult());
|
|
|
|
|
dbg(1, "mx = %d my=%d\n", mx, my);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-16 22:28:10 +01:00
|
|
|
#ifndef __unix__
|
2021-11-10 13:43:08 +01:00
|
|
|
if(cstate & 0x0001) { /* caps lock */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
|
2021-11-10 13:43:08 +01:00
|
|
|
} else if (nstate & 0x0001) { /* num lock */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
|
2021-11-10 13:43:08 +01:00
|
|
|
} else { /* normal state */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
|
2021-11-10 13:43:08 +01:00
|
|
|
}
|
2020-09-22 21:02:51 +02:00
|
|
|
#else
|
2020-09-22 15:47:53 +02:00
|
|
|
XGetKeyboardControl(display, &kbdstate);
|
2021-11-08 16:27:07 +01:00
|
|
|
if(kbdstate.led_mask & 1) { /* caps lock */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {CAPS LOCK SET! }", NULL);
|
2021-11-08 16:27:07 +01:00
|
|
|
} else if(kbdstate.led_mask & 2) { /* num lock */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state active -text {NUM LOCK SET! }", NULL);
|
2021-11-08 16:27:07 +01:00
|
|
|
} else { /* normal state */
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.8 configure -state normal -text {}", NULL);
|
2020-09-22 15:47:53 +02:00
|
|
|
}
|
2020-09-22 21:02:51 +02:00
|
|
|
#endif
|
2021-11-16 22:28:10 +01:00
|
|
|
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.7 configure -text $netlist_type", NULL);
|
|
|
|
|
tclvareval(xctx->top_path, ".statusbar.3 delete 0 end;",
|
2021-11-17 01:12:55 +01:00
|
|
|
xctx->top_path, ".statusbar.3 insert 0 $cadsnap",
|
|
|
|
|
NULL);
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval(xctx->top_path, ".statusbar.5 delete 0 end;",
|
2021-11-17 01:12:55 +01:00
|
|
|
xctx->top_path, ".statusbar.5 insert 0 $cadgrid",
|
|
|
|
|
NULL);
|
|
|
|
|
|
2021-11-16 22:28:10 +01:00
|
|
|
#if 0
|
|
|
|
|
/* exclude Motion and Expose events */
|
2023-09-22 15:53:23 +02:00
|
|
|
if(event!=6 /* && event!=12 */) {
|
|
|
|
|
dbg(0, "callback(): state=%d event=%d, winpath=%s, old_winpath=%s, semaphore=%d\n",
|
|
|
|
|
state, event, winpath, old_winpath, xctx->semaphore+1);
|
|
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Schematic window context switch */
|
|
|
|
|
redraw_only =0;
|
|
|
|
|
if(strcmp(old_winpath, winpath) ) {
|
|
|
|
|
if( xctx->semaphore >= 1 || event == Expose) {
|
|
|
|
|
dbg(1, "callback(): semaphore >=2 (or Expose) switching window context: %s --> %s\n", old_winpath, winpath);
|
|
|
|
|
redraw_only = 1;
|
2023-10-25 11:43:43 +02:00
|
|
|
new_schematic("switch_no_tcl_ctx", winpath, "", 1);
|
2021-11-16 22:28:10 +01:00
|
|
|
} else {
|
2022-01-09 05:14:25 +01:00
|
|
|
dbg(1, "callback(): switching window context: %s --> %s, semaphore=%d\n", old_winpath, winpath, xctx->semaphore);
|
2023-10-25 11:43:43 +02:00
|
|
|
new_schematic("switch", winpath, "", 1);
|
2021-11-16 22:28:10 +01:00
|
|
|
}
|
2022-07-15 12:32:57 +02:00
|
|
|
tclvareval("housekeeping_ctx", NULL);
|
2021-11-16 22:28:10 +01:00
|
|
|
}
|
|
|
|
|
/* artificially set semaphore to allow only redraw operations in switched schematic,
|
|
|
|
|
* so we don't need to switch tcl context which is costly performance-wise
|
|
|
|
|
*/
|
2022-01-09 05:14:25 +01:00
|
|
|
if(redraw_only) {
|
|
|
|
|
dbg(1, "callback(): incrementing semaphore for redraw_only\n");
|
|
|
|
|
xctx->semaphore++;
|
|
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
|
|
|
|
|
xctx->semaphore++; /* to recognize recursive callback() calls */
|
|
|
|
|
|
2021-11-10 13:43:08 +01:00
|
|
|
c_snap = tclgetdoublevar("cadsnap");
|
2023-09-27 21:00:02 +02:00
|
|
|
#ifdef __unix__
|
2023-09-27 18:35:40 +02:00
|
|
|
state &= (1 <<13) -1; /* filter out anything above bit 12 (4096) */
|
2023-09-27 21:00:02 +02:00
|
|
|
#endif
|
2023-09-28 21:03:28 +02:00
|
|
|
state &= ~Mod2Mask; /* 20170511 filter out NumLock status */
|
|
|
|
|
state &= ~LockMask; /* filter out Caps Lock */
|
|
|
|
|
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
|
|
|
|
|
rstate &= ~ShiftMask; /* don't use ShiftMask, identifying characters is sifficient */
|
2024-03-07 12:31:18 +01:00
|
|
|
rstate &= ~Button1Mask; /* ignore button-1 */
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->semaphore >= 2)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
if(debug_var>=2)
|
2020-11-22 00:51:24 +01:00
|
|
|
if(event != MotionNotify)
|
2022-04-28 10:12:16 +02:00
|
|
|
fprintf(errfp, "callback(): reentrant call of callback(), semaphore=%d, ev=%d, ui_state=%d\n",
|
2021-11-04 12:57:41 +01:00
|
|
|
xctx->semaphore, event, xctx->ui_state);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mousex=X_TO_XSCHEM(mx);
|
|
|
|
|
xctx->mousey=Y_TO_XSCHEM(my);
|
2021-12-17 15:40:19 +01:00
|
|
|
xctx->mousex_snap=my_round(xctx->mousex / c_snap) * c_snap;
|
|
|
|
|
xctx->mousey_snap=my_round(xctx->mousey / c_snap) * c_snap;
|
2022-10-07 23:29:42 +02:00
|
|
|
|
|
|
|
|
if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2021-01-08 21:25:11 +01:00
|
|
|
|
2023-09-27 13:13:15 +02:00
|
|
|
dbg(1, "key=%d EQUAL_MODMASK=%d, SET_MODMASK=%d\n", key, SET_MODMASK, EQUAL_MODMASK);
|
2024-03-20 03:53:56 +01:00
|
|
|
|
|
|
|
|
#if defined(__unix__) && HAS_CAIRO==1
|
|
|
|
|
if(xctx->ui_state & GRABSCREEN) {
|
|
|
|
|
grabscreen(winpath, event, mx, my, key, button, aux, state);
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
2020-08-08 15:47:34 +02:00
|
|
|
switch(event)
|
|
|
|
|
{
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2023-09-29 00:30:43 +02:00
|
|
|
case LeaveNotify:
|
2023-09-30 00:22:10 +02:00
|
|
|
if(draw_xhair) draw_crosshair(1);
|
|
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL);
|
2023-09-29 10:09:13 +02:00
|
|
|
xctx->mouse_inside = 0;
|
2023-09-29 00:30:43 +02:00
|
|
|
break;
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
case EnterNotify:
|
2024-03-04 15:33:11 +01:00
|
|
|
dbg(2, "callback(): Enter event, ui_state=%d\n", xctx->ui_state);
|
2023-09-29 10:09:13 +02:00
|
|
|
xctx->mouse_inside = 1;
|
2023-09-30 00:22:10 +02:00
|
|
|
if(draw_xhair)
|
2023-09-22 12:48:22 +02:00
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor none" , NULL);
|
|
|
|
|
else
|
|
|
|
|
tclvareval(xctx->top_path, ".drw configure -cursor {}" , NULL);
|
2020-10-12 13:13:31 +02:00
|
|
|
/* xschem window *sending* selected objects
|
|
|
|
|
when the pointer comes back in abort copy operation since it has been done
|
2020-12-03 04:20:05 +01:00
|
|
|
in another xschem xctx->window; STARTCOPY set and selection file does not exist any more */
|
2024-03-04 14:38:32 +01:00
|
|
|
if(stat(sel_file, &buf) && (xctx->ui_state & STARTCOPY) )
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2024-03-04 14:38:32 +01:00
|
|
|
copy_objects(ABORT);
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-11-28 18:41:38 +01:00
|
|
|
/* xschem window *receiving* selected objects selection cleared --> abort */
|
2024-03-07 18:32:42 +01:00
|
|
|
else if(xctx->paste_from == 1 && stat(sel_file, &buf) && (xctx->ui_state & STARTMERGE)) {
|
2023-11-28 18:41:38 +01:00
|
|
|
abort_operation();
|
|
|
|
|
}
|
|
|
|
|
/*xschem window *receiving* selected objects
|
|
|
|
|
* no selected objects and selection file exists --> start merge */
|
2024-03-04 14:38:32 +01:00
|
|
|
else if(xctx->lastsel == 0 && !stat(sel_file, &buf)) {
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mousex_snap = 490;
|
|
|
|
|
xctx->mousey_snap = -340;
|
2020-08-08 15:47:34 +02:00
|
|
|
merge_file(1, ".sch");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Expose:
|
2021-12-23 03:43:34 +01:00
|
|
|
dbg(1, "callback: Expose, winpath=%s, %dx%d+%d+%d\n", winpath, button, aux, mx, my);
|
2023-09-21 23:51:17 +02:00
|
|
|
MyXCopyArea(display, xctx->save_pixmap, xctx->window, xctx->gc[0], mx,my,button,aux,mx,my);
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
XRectangle xr[1];
|
2022-04-28 10:12:16 +02:00
|
|
|
xr[0].x=(short)mx;
|
|
|
|
|
xr[0].y=(short)my;
|
|
|
|
|
xr[0].width=(unsigned short)button;
|
|
|
|
|
xr[0].height=(unsigned short)aux;
|
2020-08-08 15:47:34 +02:00
|
|
|
/* redraw selection on expose, needed if no backing store available on the server 20171112 */
|
2021-11-16 22:28:10 +01:00
|
|
|
XSetClipRectangles(display, xctx->gc[SELLAYER], 0,0, xr, 1, Unsorted);
|
2020-08-08 15:47:34 +02:00
|
|
|
rebuild_selected_array();
|
2023-06-06 19:39:40 +02:00
|
|
|
if(tclgetboolvar("compare_sch") /* && xctx->sch_to_compare[0] */){
|
2022-12-13 13:51:33 +01:00
|
|
|
compare_schematics("");
|
|
|
|
|
} else {
|
|
|
|
|
draw_selection(xctx->gc[SELLAYER],0);
|
|
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
XSetClipMask(display, xctx->gc[SELLAYER], None);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
dbg(1, "callback(): Expose\n");
|
|
|
|
|
break;
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
case ConfigureNotify:
|
2022-09-04 14:16:38 +02:00
|
|
|
dbg(1,"callback(): ConfigureNotify event\n");
|
2020-12-22 00:13:25 +01:00
|
|
|
resetwin(1, 1, 0, 0, 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MotionNotify:
|
2022-09-18 05:29:16 +02:00
|
|
|
if( waves_selected(event, key, state, button)) {
|
2021-12-22 18:25:15 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-11-04 18:29:15 +01:00
|
|
|
if(draw_xhair) {
|
|
|
|
|
draw_crosshair(1);
|
|
|
|
|
}
|
2023-10-27 23:45:54 +02:00
|
|
|
if(xctx->ui_state & STARTPAN) pan(RUBBER, mx, my);
|
2023-11-08 22:45:31 +01:00
|
|
|
if(xctx->semaphore >= 2) {
|
|
|
|
|
if(draw_xhair) {
|
|
|
|
|
draw_crosshair(2);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-03-01 00:12:44 +01:00
|
|
|
dbg(1, "ui_state=%d deltax=%g\n", xctx->ui_state, xctx->deltax);
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state) {
|
2022-10-07 23:29:42 +02:00
|
|
|
if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) {
|
|
|
|
|
my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d w=%.16g h=%.16g",
|
|
|
|
|
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);
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-22 00:13:25 +01:00
|
|
|
if(xctx->ui_state & STARTZOOM) zoom_rectangle(RUBBER);
|
2024-03-01 00:12:44 +01:00
|
|
|
|
|
|
|
|
/* determine direction of a rectangle selection (or unselection with ALT key) */
|
2022-01-17 22:41:36 +01:00
|
|
|
if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & (PLACE_SYMBOL | STARTPAN | PLACE_TEXT)) ) {
|
2024-03-01 00:12:44 +01:00
|
|
|
/* Unselect by area : determine direction */
|
|
|
|
|
if( (state & Button1Mask) && SET_MODMASK) {
|
2023-10-21 19:09:17 +02:00
|
|
|
if(mx >= xctx->mx_save) xctx->nl_dir = 0;
|
|
|
|
|
else xctx->nl_dir = 1;
|
|
|
|
|
select_rect(RUBBER,0);
|
2024-03-01 00:12:44 +01:00
|
|
|
/* select by area : determine direction */
|
2020-08-08 15:47:34 +02:00
|
|
|
} else if(state & Button1Mask) {
|
2023-10-21 19:09:17 +02:00
|
|
|
if(mx >= xctx->mx_save) xctx->nl_dir = 0;
|
|
|
|
|
else xctx->nl_dir = 1;
|
2021-12-22 18:25:15 +01:00
|
|
|
select_rect(RUBBER,1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTMOVE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2020-08-08 15:47:34 +02:00
|
|
|
move_objects(RUBBER,0,0,0);
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTCOPY) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2020-08-08 15:47:34 +02:00
|
|
|
copy_objects(RUBBER);
|
|
|
|
|
}
|
2020-12-29 03:45:12 +01:00
|
|
|
|
|
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2024-03-01 00:48:04 +01:00
|
|
|
/* 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 */
|
2020-12-02 15:10:47 +01:00
|
|
|
if(!(xctx->ui_state & STARTPOLYGON) && (state&Button1Mask) && !(xctx->ui_state & STARTWIRE) &&
|
2024-03-04 16:33:20 +01:00
|
|
|
!(xctx->ui_state & STARTPAN) && !(SET_MODMASK) && !xctx->shape_point_selected &&
|
2024-03-02 14:15:30 +01:00
|
|
|
!xctx->drag_elements &&
|
2021-11-04 15:08:54 +01:00
|
|
|
!(state & ShiftMask) && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2024-03-01 00:12:44 +01:00
|
|
|
|
2024-03-01 00:48:04 +01:00
|
|
|
if(mx != xctx->mx_save || my != xctx->my_save) {
|
2020-12-02 15:10:47 +01:00
|
|
|
if( !(xctx->ui_state & STARTSELECT)) {
|
2020-11-03 12:10:55 +01:00
|
|
|
select_rect(START,1);
|
2021-11-18 01:55:01 +01:00
|
|
|
xctx->onetime=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-11-06 03:24:45 +01:00
|
|
|
if(abs(mx-xctx->mx_save) > 8 ||
|
|
|
|
|
abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */
|
2021-11-18 01:55:01 +01:00
|
|
|
if(xctx->onetime) {
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1); /* 20171026 avoid multiple calls of unselect_all() */
|
2021-11-18 01:55:01 +01:00
|
|
|
xctx->onetime=0;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2022-08-25 13:59:36 +02:00
|
|
|
xctx->ui_state|=STARTSELECT; /* set it again cause unselect_all(1) clears it... */
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-23 23:41:39 +02:00
|
|
|
/* Unselect by area */
|
2023-09-22 15:53:23 +02:00
|
|
|
if((state & Button1Mask) && (SET_MODMASK) && !(state & ShiftMask) &&
|
2024-03-04 16:33:20 +01:00
|
|
|
!(xctx->ui_state & STARTPAN) && !xctx->shape_point_selected &&
|
2021-11-06 03:24:45 +01:00
|
|
|
!(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT))) { /* unselect area */
|
2020-12-02 15:10:47 +01:00
|
|
|
if( !(xctx->ui_state & STARTSELECT)) {
|
2020-11-03 12:10:55 +01:00
|
|
|
select_rect(START,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-23 23:41:39 +02:00
|
|
|
/* Select by area. Shift pressed */
|
2021-11-06 03:24:45 +01:00
|
|
|
else if((state&Button1Mask) && (state & ShiftMask) &&
|
2024-03-04 16:33:20 +01:00
|
|
|
!(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)) && !xctx->shape_point_selected &&
|
2024-03-02 14:15:30 +01:00
|
|
|
!xctx->drag_elements && !(xctx->ui_state & STARTPAN) ) {
|
2020-12-06 16:10:22 +01:00
|
|
|
if(mx != xctx->mx_save || my != xctx->my_save) {
|
2020-12-02 15:10:47 +01:00
|
|
|
if( !(xctx->ui_state & STARTSELECT)) {
|
2020-11-03 12:10:55 +01:00
|
|
|
select_rect(START,1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-11-06 03:24:45 +01:00
|
|
|
if(abs(mx-xctx->mx_save) > 8 ||
|
|
|
|
|
abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */
|
2023-10-23 23:41:39 +02:00
|
|
|
if(!xctx->already_selected) {
|
|
|
|
|
select_object(X_TO_XSCHEM(xctx->mx_save),
|
2024-03-05 11:57:15 +01:00
|
|
|
Y_TO_XSCHEM(xctx->my_save), 0, 0, NULL); /* remove near obj if dragging */
|
2023-10-23 23:41:39 +02:00
|
|
|
}
|
2020-09-01 10:50:08 +02:00
|
|
|
rebuild_selected_array();
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-04 15:56:42 +01:00
|
|
|
if(draw_xhair) {
|
2023-11-04 18:29:15 +01:00
|
|
|
draw_crosshair(2);
|
2023-11-04 15:56:42 +01:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
case KeyRelease:
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
case KeyPress:
|
2020-08-08 15:47:34 +02:00
|
|
|
if(key==' ') {
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTWIRE) { /* & instead of == 20190409 */
|
|
|
|
|
new_wire(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->manhattan_lines++;
|
|
|
|
|
xctx->manhattan_lines %=3;
|
2020-12-02 15:10:47 +01:00
|
|
|
new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-12-02 15:10:47 +01:00
|
|
|
} else if(xctx->ui_state==STARTLINE) {
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(RUBBER|CLEAR, xctx->mousex_snap, xctx->mousey_snap);
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->manhattan_lines++;
|
|
|
|
|
xctx->manhattan_lines %=3;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore<2) {
|
2020-12-25 15:14:41 +01:00
|
|
|
rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2022-01-17 22:41:36 +01:00
|
|
|
pan(START, mx, my);
|
|
|
|
|
xctx->ui_state |= STARTPAN;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key == '_' ) /* toggle change line width */
|
|
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
if(!tclgetboolvar("change_lw")) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("alert_ { enabling change line width} {}");
|
|
|
|
|
tclsetvar("change_lw","1");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tcleval("alert_ { disabling change line width} {}");
|
|
|
|
|
tclsetvar("change_lw","0");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'b' && rstate==ControlMask) /* toggle show text in symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-16 22:28:10 +01:00
|
|
|
xctx->sym_txt =!xctx->sym_txt;
|
|
|
|
|
if(xctx->sym_txt) {
|
2020-08-08 15:47:34 +02:00
|
|
|
/* 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 */
|
|
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
int dr_gr;
|
|
|
|
|
dr_gr = tclgetboolvar("draw_grid");
|
|
|
|
|
dr_gr =!dr_gr;
|
|
|
|
|
if(dr_gr) {
|
2020-08-08 15:47:34 +02:00
|
|
|
/* tcleval("alert_ { enabling draw grid} {}"); */
|
|
|
|
|
tclsetvar("draw_grid","1");
|
|
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* tcleval("alert_ { disabling draw grid} {}"); */
|
|
|
|
|
tclsetvar("draw_grid","0");
|
|
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'j' && rstate==0 ) /* print list of highlight nets */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
print_hilight_net(1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'j' && rstate==ControlMask) /* create ipins from highlight nets */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
print_hilight_net(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key == 'j' && EQUAL_MODMASK) /* create labels without i prefix from hilight nets */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
print_hilight_net(4);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'J' && SET_MODMASK ) /* create labels with i prefix from hilight nets */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
print_hilight_net(2);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'h' && rstate==ControlMask ) /* go to http link */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-03-13 12:37:30 +01:00
|
|
|
int savesem = xctx->semaphore;
|
|
|
|
|
xctx->semaphore = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
launcher();
|
2023-03-13 12:37:30 +01:00
|
|
|
xctx->semaphore = savesem;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key == 'h' && EQUAL_MODMASK) /* create symbol pins from schematic pins 20171208 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
tcleval("schpins_to_sympins");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'h' && rstate == 0) {
|
2020-08-08 15:47:34 +02:00
|
|
|
/* horizontally constrained drag 20171023 */
|
2024-03-07 17:48:41 +01:00
|
|
|
if ( xctx->constr_mv == 1 ) {
|
|
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 1" );
|
|
|
|
|
xctx->constr_mv = 1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2020-12-02 15:10:47 +01:00
|
|
|
new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='H' && rstate == 0) { /* attach labels to selected instances */
|
2021-11-29 14:37:39 +01:00
|
|
|
attach_labels_to_inst(1);
|
2021-01-05 01:24:45 +01:00
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if (key == 'H' && rstate == ControlMask) { /* create schematic and symbol from selected components */
|
2021-06-05 08:58:38 +02:00
|
|
|
make_schematic_symbol_from_sel();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'v' && rstate==0) {
|
2020-08-08 15:47:34 +02:00
|
|
|
/* vertically constrained drag 20171023 */
|
2024-03-07 17:48:41 +01:00
|
|
|
if ( xctx->constr_mv == 2 ) {
|
|
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 2" );
|
|
|
|
|
xctx->constr_mv = 2;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2020-12-02 15:10:47 +01:00
|
|
|
new_wire(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
if(xctx->constr_mv == 1) xctx->mousey_snap = xctx->my_double_save;
|
|
|
|
|
if(xctx->constr_mv == 2) xctx->mousex_snap = xctx->mx_double_save;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_line(RUBBER, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key == 'j' && SET_MODMASK && (state & ControlMask) ) /* print list of highlight net with label expansion */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
print_hilight_net(3);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'J' && rstate == 0) {
|
2021-09-19 00:21:20 +02:00
|
|
|
create_plot_cmd();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == '$' && rstate == 0 ) /* toggle pixmap saving */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-10-26 00:04:13 +02:00
|
|
|
xctx->draw_pixmap =!xctx->draw_pixmap;
|
|
|
|
|
if(xctx->draw_pixmap) tcleval("alert_ { enabling draw pixmap} {}");
|
2020-08-08 15:47:34 +02:00
|
|
|
else tcleval("alert_ { disabling draw pixmap} {}");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key == '$' && (state &ControlMask) ) /* toggle window drawing */
|
|
|
|
|
{
|
2021-11-16 22:28:10 +01:00
|
|
|
xctx->draw_window =!xctx->draw_window;
|
|
|
|
|
if(xctx->draw_window) {
|
2020-08-08 15:47:34 +02:00
|
|
|
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;
|
2021-11-16 22:28:10 +01:00
|
|
|
xctx->fill_pattern++;
|
|
|
|
|
if(xctx->fill_pattern==3) xctx->fill_pattern=0;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->fill_pattern==1) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("alert_ { Stippled pattern fill} {}");
|
|
|
|
|
for(x=0;x<cadlayers;x++) {
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->fill_type[x]==1) XSetFillStyle(display,xctx->gcstipple[x],FillSolid);
|
|
|
|
|
else XSetFillStyle(display,xctx->gcstipple[x],FillStippled);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->fill_pattern==2) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("alert_ { solid pattern fill} {}");
|
2020-10-12 13:13:31 +02:00
|
|
|
for(x=0;x<cadlayers;x++)
|
2021-11-16 22:28:10 +01:00
|
|
|
XSetFillStyle(display,xctx->gcstipple[x],FillSolid);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tcleval("alert_ { No pattern fill} {}");
|
2020-10-12 13:13:31 +02:00
|
|
|
for(x=0;x<cadlayers;x++)
|
2021-11-16 22:28:10 +01:00
|
|
|
XSetFillStyle(display,xctx->gcstipple[x],FillStippled);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-12-12 01:14:40 +01:00
|
|
|
if(key == '+' && state & ControlMask) /* change line width */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-12-12 01:14:40 +01:00
|
|
|
xctx->lw = round_to_n_digits(xctx->lw + 0.5, 2);
|
2020-10-17 00:53:19 +02:00
|
|
|
change_linewidth(xctx->lw);
|
2023-12-12 01:14:40 +01:00
|
|
|
tclsetboolvar("change_lw", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2023-12-12 01:14:40 +01:00
|
|
|
if(key == '-' && state & ControlMask) /* change line width */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-12-12 01:14:40 +01:00
|
|
|
xctx->lw = round_to_n_digits(xctx->lw - 0.5, 2);
|
|
|
|
|
if(xctx->lw < 0.0) xctx->lw = 0.0;
|
2020-10-17 00:53:19 +02:00
|
|
|
change_linewidth(xctx->lw);
|
2023-12-12 01:14:40 +01:00
|
|
|
tclsetboolvar("change_lw", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key == 'X' && rstate == 0) /* highlight discrepanciens between selected instance pin and net names */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-24 23:00:41 +02:00
|
|
|
hilight_net_pin_mismatches();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-02-27 16:43:49 +01:00
|
|
|
if(key== 'W' /* && !xctx->ui_state */ && rstate == 0) { /* create wire snapping to closest instance pin */
|
2020-08-08 15:47:34 +02:00
|
|
|
double x, y;
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-02 15:10:47 +01:00
|
|
|
if(!(xctx->ui_state & STARTWIRE)){
|
|
|
|
|
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
|
2021-12-17 15:40:19 +01:00
|
|
|
xctx->mx_double_save = my_round(x / c_snap) * c_snap;
|
|
|
|
|
xctx->my_double_save = my_round(y / c_snap) * c_snap;
|
2020-08-08 15:47:34 +02:00
|
|
|
new_wire(PLACE, x, y);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-12-02 15:10:47 +01:00
|
|
|
find_closest_net_or_symbol_pin(xctx->mousex, xctx->mousey, &x, &y);
|
2020-08-08 15:47:34 +02:00
|
|
|
new_wire(RUBBER, x, y);
|
|
|
|
|
new_wire(PLACE|END, x, y);
|
2024-03-07 17:48:41 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-02-27 16:43:49 +01:00
|
|
|
if(key == 'w' /* && !xctx->ui_state */ && rstate==0) /* place wire. */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-01-05 01:24:45 +01:00
|
|
|
int prev_state = xctx->ui_state;
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2024-03-06 12:53:49 +01:00
|
|
|
start_wire(xctx->mousex_snap, xctx->mousey_snap);
|
2021-01-05 01:24:45 +01:00
|
|
|
if(prev_state == STARTWIRE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv=0;
|
2021-01-05 01:24:45 +01:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(key == XK_Return && (state == 0 ) && xctx->ui_state & STARTPOLYGON) { /* close polygon */
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(ADD|END, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2021-11-04 23:52:24 +01:00
|
|
|
if(key == XK_Escape) /* abort & redraw */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-04 23:52:24 +01:00
|
|
|
if(xctx->semaphore < 2) {
|
|
|
|
|
abort_operation();
|
|
|
|
|
}
|
|
|
|
|
/* stuff that can be done reentrantly ... */
|
|
|
|
|
tclsetvar("tclstop", "1"); /* stop simulation if any running */
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='z' && rstate == 0) /* zoom box */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-22 00:13:25 +01:00
|
|
|
dbg(1, "callback(): zoom_rectangle call\n");
|
|
|
|
|
zoom_rectangle(START);break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='Z' && rstate == 0) /* zoom in */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
view_zoom(0.0); break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='p' && EQUAL_MODMASK) /* add symbol pin */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2024-04-12 00:06:36 +02:00
|
|
|
xctx->push_undo();
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2020-12-02 15:10:47 +01:00
|
|
|
storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5,
|
2020-08-08 15:47:34 +02:00
|
|
|
xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout");
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->need_reb_sel_arr=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
rebuild_selected_array();
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->ui_state |= START_SYMPIN;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-03-01 12:19:15 +01:00
|
|
|
if(key=='p' && !(xctx->ui_state & STARTPOLYGON) && rstate==0) /* start polygon */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(1, "callback(): start polygon\n");
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='P' && rstate == 0) /* pan, other way to. */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->xorigin=-xctx->mousex_snap+xctx->areaw*xctx->zoom/2.0;
|
|
|
|
|
xctx->yorigin=-xctx->mousey_snap+xctx->areah*xctx->zoom/2.0;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='5' && rstate == 0) { /* 20110112 display only probes */
|
2021-11-17 23:12:17 +01:00
|
|
|
xctx->only_probes = !xctx->only_probes;
|
|
|
|
|
tclsetboolvar("only_probes", xctx->only_probes);
|
2020-08-08 15:47:34 +02:00
|
|
|
toggle_only_probes();
|
|
|
|
|
break;
|
|
|
|
|
} /* /20110112 */
|
|
|
|
|
if(key<='9' && key >='0' && state==ControlMask) /* choose layer */
|
|
|
|
|
{
|
2020-09-16 00:50:15 +02:00
|
|
|
char n[30];
|
2022-04-28 10:12:16 +02:00
|
|
|
xctx->rectcolor = (int)key - '0'+4;
|
2020-12-06 16:40:08 +01:00
|
|
|
my_snprintf(n, S(n), "%d", xctx->rectcolor);
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval("xschem set rectcolor ", n, NULL);
|
2021-11-09 19:05:56 +01:00
|
|
|
|
2023-06-25 23:33:26 +02:00
|
|
|
if(has_x) {
|
|
|
|
|
if(!strcmp(winpath, ".drw")) {
|
|
|
|
|
tclvareval("reconfigure_layers_button {}", NULL);
|
|
|
|
|
} else {
|
|
|
|
|
tclvareval("reconfigure_layers_button [winfo parent ", winpath, "]", NULL);
|
|
|
|
|
}
|
2021-11-09 19:05:56 +01:00
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
dbg(1, "callback(): new color: %d\n",xctx->color_index[xctx->rectcolor]);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2021-11-04 01:13:44 +01:00
|
|
|
if(key==XK_Delete && (xctx->ui_state & SELECTION) ) /* delete selection */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-04 01:13:44 +01:00
|
|
|
delete(1/* to_push_undo */);break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-06-04 09:28:22 +02:00
|
|
|
if(key==XK_Right && state == ControlMask) {
|
|
|
|
|
int save = xctx->semaphore;
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
|
|
|
|
xctx->semaphore = 0;
|
2022-01-10 04:30:51 +01:00
|
|
|
tcleval("next_tab");
|
2023-06-04 09:28:22 +02:00
|
|
|
xctx->semaphore = save;
|
|
|
|
|
}
|
|
|
|
|
if(key==XK_Left && state == ControlMask) {
|
|
|
|
|
int save = xctx->semaphore;
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
|
|
|
|
xctx->semaphore = 0;
|
|
|
|
|
tcleval("prev_tab");
|
|
|
|
|
xctx->semaphore = save;
|
2022-01-10 04:30:51 +01:00
|
|
|
}
|
2022-01-11 22:57:55 +01:00
|
|
|
if(key==XK_Right && !(state & ControlMask)) /* left */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-22 04:39:23 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->xorigin+=-CADMOVESTEP*xctx->zoom;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2022-01-11 22:57:55 +01:00
|
|
|
if(key==XK_Left && !(state & ControlMask)) /* right */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-22 04:39:23 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->xorigin-=-CADMOVESTEP*xctx->zoom;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key==XK_Down) /* down */
|
|
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-22 04:39:23 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->yorigin+=-CADMOVESTEP*xctx->zoom;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key==XK_Up) /* up */
|
|
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-22 04:39:23 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->yorigin-=-CADMOVESTEP*xctx->zoom;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='w' && rstate == ControlMask) /* close current schematic */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-06-03 23:57:35 +02:00
|
|
|
int save_sem;
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-06-03 23:57:35 +02:00
|
|
|
save_sem = xctx->semaphore;
|
|
|
|
|
tcleval("xschem exit");
|
|
|
|
|
xctx->semaphore = save_sem;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-02-17 02:58:53 +01:00
|
|
|
/* toggle spice_ignore, verilog_ignore, ... flag on selected instances. */
|
|
|
|
|
if(key == 'T' && rstate == 0) {
|
|
|
|
|
toggle_ignore();
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='t' && rstate == 0) /* place text */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2022-09-02 17:11:50 +02:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
2021-11-06 03:24:45 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-02-29 03:40:08 +01:00
|
|
|
if(key=='r' /* && !xctx->ui_state */ && rstate==0) /* start rect */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
dbg(1, "callback(): start rect\n");
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-12-23 00:06:01 +01:00
|
|
|
if(key=='V' && rstate == ControlMask) /* toggle spice/vhdl netlist */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-16 22:28:10 +01:00
|
|
|
xctx->netlist_type++; if(xctx->netlist_type==6) xctx->netlist_type=1;
|
2021-11-17 01:12:55 +01:00
|
|
|
set_tcl_netlist_type();
|
2023-05-24 09:08:57 +02:00
|
|
|
draw(); /* needed to ungrey or grey out components due to *_ignore attribute */
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='s' && rstate == 0 ) /* simulate */
|
2022-04-25 08:39:51 +02:00
|
|
|
{
|
2023-02-08 04:13:50 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
|
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-09-13 00:31:20 +02:00
|
|
|
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
|
|
|
|
|
"-message {Run circuit simulation?}");
|
|
|
|
|
if(strcmp(tclresult(),"ok")==0) {
|
|
|
|
|
tcleval("[xschem get top_path].menubar.simulate invoke");
|
|
|
|
|
}
|
2022-04-25 08:39:51 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='s' && rstate == ControlMask ) /* save 20121201 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-09-30 23:55:07 +02:00
|
|
|
/* check if unnamed schematic, use saveas in this case */
|
2020-10-15 17:39:21 +02:00
|
|
|
if(!strcmp(xctx->sch[xctx->currsch],"") || strstr(xctx->sch[xctx->currsch], "untitled")) {
|
2020-09-14 10:27:45 +02:00
|
|
|
saveas(NULL, SCHEMATIC);
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
|
|
|
|
save(1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='s' && SET_MODMASK && (state & ControlMask) ) /* save as symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-09-10 10:12:51 +02:00
|
|
|
saveas(NULL, SYMBOL);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='S' && rstate == ControlMask) /* save as schematic */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-09-14 10:27:45 +02:00
|
|
|
saveas(NULL, SCHEMATIC);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='e' && rstate == 0) /* descend to schematic */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2024-02-09 17:00:56 +01:00
|
|
|
descend_schematic(0, 1, 1);break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='e' && EQUAL_MODMASK) /* edit schematic in new window */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-01-10 18:54:07 +01:00
|
|
|
int save = xctx->semaphore;
|
|
|
|
|
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
|
2023-11-20 17:53:28 +01:00
|
|
|
/* schematic_in_new_window(0, 1, 0); */
|
|
|
|
|
tcleval("open_sub_schematic");
|
2022-01-10 18:54:07 +01:00
|
|
|
xctx->semaphore = save;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-11-13 18:00:30 +01:00
|
|
|
|
|
|
|
|
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 */
|
2023-11-20 17:53:28 +01:00
|
|
|
schematic_in_new_window(1, 1, 0);
|
2023-11-13 18:00:30 +01:00
|
|
|
xctx->semaphore = save;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='i' && EQUAL_MODMASK) /* edit symbol in new window */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-01-10 18:54:07 +01:00
|
|
|
int save = xctx->semaphore;
|
|
|
|
|
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
|
2023-03-03 18:29:17 +01:00
|
|
|
symbol_in_new_window(0);
|
2022-01-10 18:54:07 +01:00
|
|
|
xctx->semaphore = save;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-11-13 18:00:30 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-09-28 21:03:28 +02:00
|
|
|
if( (key=='e' && rstate == ControlMask) || (key==XK_BackSpace)) /* back */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
go_back(1);break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='a' && rstate == 0) /* make symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-30 15:45:38 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-12-17 03:29:53 +01:00
|
|
|
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
|
|
|
|
|
"-message {do you want to make symbol view ?}");
|
2020-10-12 13:13:31 +02:00
|
|
|
if(strcmp(tclresult(),"ok")==0)
|
2020-09-14 10:27:45 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
save_schematic(xctx->sch[xctx->currsch]);
|
2020-09-14 10:27:45 +02:00
|
|
|
make_symbol();
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='a' && rstate == ControlMask) /* select all */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
select_all();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='y' && rstate == 0) /* toggle stretching */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
int en_s;
|
|
|
|
|
en_s = tclgetboolvar("enable_stretch");
|
|
|
|
|
en_s = !en_s;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2021-11-10 13:43:08 +01:00
|
|
|
if(en_s) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tclsetvar("enable_stretch","1");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tclsetvar("enable_stretch","0");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-03-10 12:11:51 +01:00
|
|
|
if(key=='x' && EQUAL_MODMASK) /* toggle draw crosshair at mouse pos */
|
2022-12-13 13:51:33 +01:00
|
|
|
{
|
2024-03-10 12:11:51 +01:00
|
|
|
if(tclgetboolvar("draw_crosshair")) {
|
|
|
|
|
tclsetvar("draw_crosshair", "0");
|
2022-12-13 13:51:33 +01:00
|
|
|
} else {
|
2024-03-10 12:11:51 +01:00
|
|
|
tclsetvar("draw_crosshair", "1");
|
2022-12-13 13:51:33 +01:00
|
|
|
}
|
|
|
|
|
draw();
|
2022-08-25 13:59:36 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='x' && rstate == ControlMask) /* cut selection into clipboard */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->lastsel) { /* 20071203 check if something selected */
|
2020-08-08 15:47:34 +02:00
|
|
|
save_selection(2);
|
2021-11-04 01:13:44 +01:00
|
|
|
delete(1/* to_push_undo */);
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='c' && rstate == ControlMask) /* copy selection into clipboard */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->lastsel) { /* 20071203 check if something selected */
|
2020-08-08 15:47:34 +02:00
|
|
|
save_selection(2);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-02-27 16:43:49 +01:00
|
|
|
if(key=='C' /* && !xctx->ui_state */ && rstate == 0) /* place arc */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-02-27 16:43:49 +01:00
|
|
|
if(key=='C' /* && !xctx->ui_state */ && rstate == ControlMask) /* place circle */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
2024-03-06 12:53:49 +01:00
|
|
|
new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='O' && rstate == ControlMask ) /* load most recent tile */
|
2020-12-25 04:37:53 +01:00
|
|
|
{
|
2023-04-08 13:19:49 +02:00
|
|
|
tclvareval("xschem load [lindex $recentfile 0] gui", NULL);
|
2020-12-25 04:37:53 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='O' && rstate == 0) /* toggle light/dark colorscheme 20171113 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
int d_c;
|
|
|
|
|
d_c = tclgetboolvar("dark_colorscheme");
|
|
|
|
|
d_c = !d_c;
|
|
|
|
|
tclsetboolvar("dark_colorscheme", d_c);
|
2021-11-16 22:28:10 +01:00
|
|
|
tclsetdoublevar("dim_value", 0.0);
|
|
|
|
|
tclsetdoublevar("dim_bg", 0.0);
|
|
|
|
|
build_colors(0.0, 0.0);
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='v' && rstate == ControlMask) /* paste from clipboard */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
merge_file(2,".sch");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='Q' && rstate == ControlMask ) /* view attributes */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
edit_property(2);break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='q' && rstate==ControlMask) /* quit xschem */
|
2023-06-03 23:57:35 +02:00
|
|
|
{
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-10-22 02:53:03 +02:00
|
|
|
/* must be set to zero, otherwise switch_tab/switch_win does not proceed
|
|
|
|
|
* and these are necessary when closing tabs/windows */
|
|
|
|
|
xctx->semaphore = 0;
|
2023-06-03 23:57:35 +02:00
|
|
|
tcleval("quit_xschem");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='q' && rstate==0) /* edit attributes */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
edit_property(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='q' && EQUAL_MODMASK) /* edit .sch file (DANGER!!) */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->lastsel==0 ) {
|
2020-10-15 17:39:21 +02:00
|
|
|
my_snprintf(str, S(str), "edit_file {%s}", abs_sym_path(xctx->sch[xctx->currsch], ""));
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval(str);
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
else if(xctx->sel_array[0].type==ELEMENT) {
|
2020-10-12 13:13:31 +02:00
|
|
|
my_snprintf(str, S(str), "edit_file {%s}",
|
2023-05-01 14:37:10 +02:00
|
|
|
abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), ""));
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval(str);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-03-20 03:53:56 +01:00
|
|
|
#if defined(__unix__) && HAS_CAIRO==1
|
|
|
|
|
if(key == XK_Print) {
|
|
|
|
|
xctx->ui_state |= GRABSCREEN;
|
2024-03-21 22:37:39 +01:00
|
|
|
tclvareval("grab set -global ", xctx->top_path, ".drw", NULL);
|
2024-03-20 03:53:56 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='Q' && rstate == 0) /* edit attributes in editor */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
edit_property(1);break;
|
|
|
|
|
}
|
2023-11-01 02:23:21 +01:00
|
|
|
if(key=='i' && rstate==0) /* descend to symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
descend_symbol();break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if((key==XK_Insert && state == ShiftMask) || (key == 'i' && rstate == ControlMask)) /* insert sym */
|
2022-09-26 18:38:19 +02:00
|
|
|
{
|
2023-04-29 00:28:24 +02:00
|
|
|
tcleval("load_file_dialog {Insert symbol} {} INITIALINSTDIR 2");
|
2022-09-27 09:27:39 +02:00
|
|
|
break;
|
2022-09-25 21:11:52 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if((key==XK_Insert && state == 0) || (key == 'I' && rstate == 0) ) /* insert sym */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2024-03-06 12:53:49 +01:00
|
|
|
start_place_symbol();
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='s' && SET_MODMASK) /* reload */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-12-17 03:29:53 +01:00
|
|
|
tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
|
|
|
|
|
"-message {Are you sure you want to reload from disk?}");
|
2020-08-16 03:34:45 +02:00
|
|
|
if(strcmp(tclresult(),"ok")==0) {
|
2020-08-08 15:47:34 +02:00
|
|
|
char filename[PATH_MAX];
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
remove_symbols();
|
2020-10-15 17:39:21 +02:00
|
|
|
my_strncpy(filename, abs_sym_path(xctx->sch[xctx->currsch], ""), S(filename));
|
2023-03-25 09:41:53 +01:00
|
|
|
load_schematic(1, filename, 1, 1);
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='o' && rstate == ControlMask) /* load */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
ask_new_file();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='S' && rstate == 0) /* change element order */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-09-17 00:13:52 +02:00
|
|
|
change_elem_order(-1);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='k' && EQUAL_MODMASK) /* select whole net (all attached wires/labels/pins) */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-11-16 15:44:51 +01:00
|
|
|
select_hilight_net();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='k' && rstate==ControlMask) /* unhilight net */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
unhilight_net();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='K' && rstate == ControlMask) /* hilight net drilling thru elements */
|
2021-01-02 20:33:34 +01:00
|
|
|
/* with 'propag=' prop set on pins */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->enable_drill=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
hilight_net(0);
|
2021-01-08 21:25:11 +01:00
|
|
|
redraw_hilights(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
/* draw_hilight_net(1); */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='k' && rstate==0) /* hilight net */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->enable_drill=0;
|
2020-08-08 15:47:34 +02:00
|
|
|
hilight_net(0);
|
2021-01-08 21:25:11 +01:00
|
|
|
redraw_hilights(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
/* draw_hilight_net(1); */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='K' && rstate == 0) /* delete hilighted nets */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->enable_drill=0;
|
2020-12-25 04:37:53 +01:00
|
|
|
clear_all_hilights();
|
2020-08-08 15:47:34 +02:00
|
|
|
/* undraw_hilight_net(1); */
|
|
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='g' && EQUAL_MODMASK) { /* highlight net and send to viewer */
|
2021-09-19 00:21:20 +02:00
|
|
|
int tool = 0;
|
|
|
|
|
int exists = 0;
|
|
|
|
|
char *tool_name = NULL;
|
|
|
|
|
char str[200];
|
|
|
|
|
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2022-01-29 02:36:54 +01:00
|
|
|
tcleval("winfo exists .graphdialog");
|
|
|
|
|
if(tclresult()[0] == '1') tool = XSCHEM_GRAPH;
|
2022-01-29 12:27:54 +01:00
|
|
|
else if(xctx->graph_lastsel >=0 &&
|
2022-01-30 03:10:09 +01:00
|
|
|
xctx->rects[GRIDLAYER] > xctx->graph_lastsel &&
|
|
|
|
|
xctx->rect[GRIDLAYER][xctx->graph_lastsel].flags & 1) {
|
2022-01-29 12:27:54 +01:00
|
|
|
tool = XSCHEM_GRAPH;
|
|
|
|
|
}
|
2021-09-19 00:21:20 +02:00
|
|
|
tcleval("info exists sim");
|
|
|
|
|
if(tclresult()[0] == '1') exists = 1;
|
2021-10-25 17:05:43 +02:00
|
|
|
xctx->enable_drill = 0;
|
2021-09-19 00:21:20 +02:00
|
|
|
if(exists) {
|
2022-01-29 02:36:54 +01:00
|
|
|
if(!tool) {
|
2023-10-03 10:27:29 +02:00
|
|
|
tool = tclgetintvar("sim(spicewave,default)");
|
2022-01-29 02:36:54 +01:00
|
|
|
my_snprintf(str, S(str), "sim(spicewave,%d,name)", tool);
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup(_ALLOC_ID_, &tool_name, tclgetvar(str));
|
2022-01-29 02:36:54 +01:00
|
|
|
dbg(1,"callback(): tool_name=%s\n", tool_name);
|
|
|
|
|
if(strstr(tool_name, "Gaw")) tool=GAW;
|
|
|
|
|
else if(strstr(tool_name, "Bespice")) tool=BESPICE;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_free(_ALLOC_ID_, &tool_name);
|
2021-09-19 00:21:20 +02:00
|
|
|
}
|
2022-01-29 02:36:54 +01:00
|
|
|
}
|
|
|
|
|
if(tool) {
|
|
|
|
|
hilight_net(tool);
|
|
|
|
|
redraw_hilights(0);
|
2021-09-19 00:21:20 +02:00
|
|
|
}
|
|
|
|
|
Tcl_ResetResult(interp);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='g' && rstate==0) /* half snap factor */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
set_snap(c_snap / 2.0);
|
2024-03-02 03:46:08 +01:00
|
|
|
change_linewidth(-1.);
|
2024-03-01 00:39:24 +01:00
|
|
|
draw();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='g' && rstate==ControlMask) /* set snap factor 20161212 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
my_snprintf(str, S(str),
|
2020-10-12 13:13:31 +02:00
|
|
|
"input_line {Enter snap value (default: %.16g current: %.16g)} {xschem set cadsnap} {%g} 10",
|
2021-11-10 13:43:08 +01:00
|
|
|
CADSNAP, c_snap, c_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval(str);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='G' && rstate == 0) /* double snap factor */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
set_snap(c_snap * 2.0);
|
2024-03-02 03:46:08 +01:00
|
|
|
change_linewidth(-1.);
|
2024-03-01 00:39:24 +01:00
|
|
|
draw();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='*' && EQUAL_MODMASK) /* svg print , 20121108 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-22 00:13:25 +01:00
|
|
|
svg_draw();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='*' && rstate == 0 ) /* postscript print */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-12-12 01:14:40 +01:00
|
|
|
ps_draw(7, 0, 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='*' && rstate == ControlMask) /* xpm print */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-22 00:13:25 +01:00
|
|
|
print_image();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='u' && EQUAL_MODMASK) /* align to grid */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-29 11:52:32 +01:00
|
|
|
xctx->push_undo();
|
2021-11-10 13:43:08 +01:00
|
|
|
round_schematic_to_grid(c_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
set_modify(1);
|
2021-11-10 13:43:08 +01:00
|
|
|
if(tclgetboolvar("autotrim_wires")) trim_wires();
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_hash_inst=0;
|
|
|
|
|
xctx->prep_hash_wires=0;
|
|
|
|
|
xctx->prep_net_structs=0;
|
|
|
|
|
xctx->prep_hi_structs=0;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-10-29 23:52:33 +01:00
|
|
|
if(0 && (key=='u') && rstate==ControlMask) /* testmode */
|
2023-10-27 10:48:53 +02:00
|
|
|
{
|
2023-10-27 12:42:08 +02:00
|
|
|
static int x = 0;
|
|
|
|
|
|
2023-10-27 10:48:53 +02:00
|
|
|
if(x == 0) {
|
|
|
|
|
int i;
|
2023-10-29 23:52:33 +01:00
|
|
|
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++) {
|
2023-10-27 10:48:53 +02:00
|
|
|
XDrawLine(display, xctx->window, xctx->gctiled,
|
2023-10-29 23:52:33 +01:00
|
|
|
i, xctx->xrect[0].y, i, xctx->xrect[0].height);
|
|
|
|
|
XFlush(display);
|
|
|
|
|
sleep_ms(4);
|
2023-10-27 10:48:53 +02:00
|
|
|
}
|
2023-10-29 23:52:33 +01:00
|
|
|
} else if(x == 1) {
|
2023-10-27 12:42:08 +02:00
|
|
|
int i;
|
2023-10-29 23:52:33 +01:00
|
|
|
XFillRectangle(display, xctx->window, xctx->gc[BACKLAYER], xctx->areax1, xctx->areay1,
|
|
|
|
|
xctx->areaw, xctx->areah);
|
|
|
|
|
XFlush(display);
|
|
|
|
|
sleep_ms(400);
|
2023-10-27 12:42:08 +02:00
|
|
|
for(i = xctx->xrect[0].x; i < xctx->xrect[0].width; i++) {
|
|
|
|
|
XDrawLine(display, xctx->window, xctx->gctiled,
|
2023-10-29 23:52:33 +01:00
|
|
|
i, xctx->xrect[0].y, i+1, xctx->xrect[0].height);
|
|
|
|
|
XFlush(display);
|
|
|
|
|
sleep_ms(4);
|
2023-10-27 12:42:08 +02:00
|
|
|
}
|
2023-10-27 10:48:53 +02:00
|
|
|
}
|
|
|
|
|
x++;
|
2023-10-29 23:52:33 +01:00
|
|
|
x %= 2;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='u' && rstate==0) /* undo */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-29 11:52:32 +01:00
|
|
|
xctx->pop_undo(0, 1); /* 2nd parameter: set_modify_status */
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='U' && rstate == 0) /* redo */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-29 11:52:32 +01:00
|
|
|
xctx->pop_undo(1, 1); /* 2nd parameter: set_modify_status */
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key=='&') /* check wire connectivity */
|
|
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-29 11:52:32 +01:00
|
|
|
xctx->push_undo();
|
2020-08-08 15:47:34 +02:00
|
|
|
trim_wires();
|
|
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='l' && rstate == ControlMask) { /* create schematic from selected symbol 20171004 */
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
create_sch_from_sym();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-02-29 03:40:08 +01:00
|
|
|
if(key=='l' /* && !xctx->ui_state */ && rstate == 0) /* start line */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-01-05 01:24:45 +01:00
|
|
|
int prev_state = xctx->ui_state;
|
2024-03-06 12:53:49 +01:00
|
|
|
start_line(xctx->mousex_snap, xctx->mousey_snap);
|
2021-01-05 01:24:45 +01:00
|
|
|
if(prev_state == STARTLINE) {
|
2024-03-07 17:48:41 +01:00
|
|
|
tcleval("set constr_mv 0" );
|
|
|
|
|
xctx->constr_mv=0;
|
2021-01-05 01:24:45 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='l' && EQUAL_MODMASK) { /* add pin label*/
|
2021-01-05 01:24:45 +01:00
|
|
|
place_net_label(1);
|
|
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-11-04 01:13:44 +01:00
|
|
|
if(key >= '0' && key <= '4' && state == 0) { /* toggle pin logic level */
|
2021-01-05 01:24:45 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-03-10 02:42:04 +01:00
|
|
|
if(key == '4') logic_set(-1, 1, NULL);
|
|
|
|
|
else logic_set((int)key - '0', 1, NULL);
|
2021-01-05 01:24:45 +01:00
|
|
|
break;
|
2020-12-26 19:26:33 +01:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='L' && EQUAL_MODMASK ) { /* add pin label*/
|
2020-10-24 23:00:41 +02:00
|
|
|
place_net_label(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='F' && rstate == 0) /* flip */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTMOVE) move_objects(FLIP,0,0,0);
|
|
|
|
|
else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP);
|
2020-08-08 15:47:34 +02:00
|
|
|
else {
|
|
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2023-09-17 00:13:52 +02:00
|
|
|
move_objects(FLIP,0,0,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
move_objects(END,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-12-23 00:06:01 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 01:13:44 +01:00
|
|
|
if(key=='\\' && state==0) /* fullscreen */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-09 19:05:56 +01:00
|
|
|
|
|
|
|
|
dbg(1, "callback(): toggle fullscreen, winpath=%s\n", winpath);
|
|
|
|
|
toggle_fullscreen(winpath);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='f' && EQUAL_MODMASK) /* flip objects around their anchor points 20171208 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTMOVE) move_objects(FLIP|ROTATELOCAL,0,0,0);
|
|
|
|
|
else if(xctx->ui_state & STARTCOPY) copy_objects(FLIP|ROTATELOCAL);
|
2020-08-08 15:47:34 +02:00
|
|
|
else {
|
|
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
move_objects(FLIP|ROTATELOCAL,0,0,0);
|
|
|
|
|
move_objects(END,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='R' && rstate == 0) /* rotate */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTMOVE) move_objects(ROTATE,0,0,0);
|
|
|
|
|
else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE);
|
2020-08-08 15:47:34 +02:00
|
|
|
else {
|
|
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2023-09-17 00:13:52 +02:00
|
|
|
move_objects(ROTATE,0,0,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
move_objects(END,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='r' && EQUAL_MODMASK) /* rotate objects around their anchor points 20171208 */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTMOVE) move_objects(ROTATE|ROTATELOCAL,0,0,0);
|
|
|
|
|
else if(xctx->ui_state & STARTCOPY) copy_objects(ROTATE|ROTATELOCAL);
|
2020-08-08 15:47:34 +02:00
|
|
|
else {
|
|
|
|
|
rebuild_selected_array();
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
move_objects(ROTATE|ROTATELOCAL,0,0,0);
|
|
|
|
|
move_objects(END,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='m' && rstate==0 && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2022-01-03 18:43:34 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2023-09-25 15:28:40 +02:00
|
|
|
if(tclgetboolvar("enable_stretch"))
|
|
|
|
|
select_attached_nets(); /* stretch nets that land on selected instance pins */
|
2020-11-03 12:10:55 +01:00
|
|
|
move_objects(START,0,0,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(((key == 'M' && rstate == 0) || (key == 'm' && EQUAL_MODMASK)) &&
|
2023-09-25 23:23:08 +02:00
|
|
|
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
|
2023-06-10 18:57:32 +02:00
|
|
|
{
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2023-09-28 12:34:10 +02:00
|
|
|
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
|
2023-09-18 13:29:49 +02:00
|
|
|
/* select_attached_nets(); */ /* stretch nets that land on selected instance pins */
|
2023-06-10 18:57:32 +02:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='m' && rstate == ControlMask &&
|
2023-09-25 23:23:08 +02:00
|
|
|
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
|
2023-09-18 13:29:49 +02:00
|
|
|
{
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2023-09-25 15:28:40 +02:00
|
|
|
if(!tclgetboolvar("enable_stretch"))
|
|
|
|
|
select_attached_nets(); /* stretch nets that land on selected instance pins */
|
2023-09-18 13:29:49 +02:00
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
if(key=='M' && state == (ControlMask | ShiftMask) &&
|
|
|
|
|
!(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
|
|
|
|
|
{
|
|
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
if(!tclgetboolvar("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 */
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 13:29:49 +02:00
|
|
|
|
2023-09-25 23:23:08 +02:00
|
|
|
if(key=='c' && EQUAL_MODMASK && /* duplicate selection */
|
|
|
|
|
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
|
|
|
|
|
{
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-09-28 12:34:10 +02:00
|
|
|
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
|
2023-09-25 23:23:08 +02:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
|
|
|
|
copy_objects(START);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='c' && rstate==0 && /* duplicate selection */
|
2020-12-02 15:10:47 +01:00
|
|
|
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2020-11-03 12:10:55 +01:00
|
|
|
copy_objects(START);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='n' && rstate == ControlMask) /* clear schematic */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("xschem clear SCHEMATIC");
|
2021-10-09 10:25:24 +02:00
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='N' && rstate == ControlMask ) /* clear symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("xschem clear SYMBOL");
|
2021-10-09 10:25:24 +02:00
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='n' && rstate==0) /* hierarchical netlist */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-11-05 00:14:55 +01:00
|
|
|
int err = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
yyparse_error = 0;
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
if(set_netlist_dir(0, NULL)) {
|
|
|
|
|
dbg(1, "callback(): -------------\n");
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->netlist_type == CAD_SPICE_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_spice_netlist(1);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_VHDL_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_vhdl_netlist(1);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_VERILOG_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_verilog_netlist(1);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_TEDAX_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_tedax_netlist(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
else
|
2022-09-13 00:31:20 +02:00
|
|
|
tcleval("tk_messageBox -type ok -parent [xschem get topwindow] "
|
|
|
|
|
"-message {Please Set netlisting mode (Options menu)}");
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
dbg(1, "callback(): -------------\n");
|
|
|
|
|
}
|
2023-11-14 23:40:41 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2023-11-05 00:14:55 +01:00
|
|
|
if(err) {
|
2023-11-06 16:47:14 +01:00
|
|
|
if(has_x) {
|
|
|
|
|
tclvareval(xctx->top_path, ".menubar.netlist configure -bg red", NULL);
|
|
|
|
|
tclvareval("set tctx::", xctx->current_win_path, "_netlist red", NULL);
|
|
|
|
|
}
|
2023-11-05 14:13:20 +01:00
|
|
|
|
2023-11-05 00:14:55 +01:00
|
|
|
} else {
|
2023-11-06 16:47:14 +01:00
|
|
|
if(has_x) {
|
2024-03-03 00:40:51 +01:00
|
|
|
tclvareval(xctx->top_path, ".menubar.netlist configure -bg Green", NULL);
|
|
|
|
|
tclvareval("set tctx::", xctx->current_win_path, "_netlist Green", NULL);
|
2023-11-06 16:47:14 +01:00
|
|
|
}
|
2023-11-05 00:14:55 +01:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='N' && rstate == 0) /* current level only netlist */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-11-05 00:14:55 +01:00
|
|
|
int err = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
yyparse_error = 0;
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2022-08-25 13:59:36 +02:00
|
|
|
unselect_all(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
if( set_netlist_dir(0, NULL) ) {
|
|
|
|
|
dbg(1, "callback(): -------------\n");
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->netlist_type == CAD_SPICE_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_spice_netlist(0);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_VHDL_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_vhdl_netlist(0);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_VERILOG_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_verilog_netlist(0);
|
2021-11-16 22:28:10 +01:00
|
|
|
else if(xctx->netlist_type == CAD_TEDAX_NETLIST)
|
2023-11-05 00:14:55 +01:00
|
|
|
err = global_tedax_netlist(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
else
|
2022-09-13 00:31:20 +02:00
|
|
|
tcleval("tk_messageBox -type ok -parent [xschem get topwindow] "
|
|
|
|
|
"-message {Please Set netlisting mode (Options menu)}");
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(1, "callback(): -------------\n");
|
|
|
|
|
}
|
2023-11-15 00:32:41 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2023-11-05 00:14:55 +01:00
|
|
|
if(err) {
|
2023-11-06 16:47:14 +01:00
|
|
|
if(has_x) {
|
|
|
|
|
tclvareval(xctx->top_path, ".menubar.netlist configure -bg red", NULL);
|
|
|
|
|
tclvareval("set tctx::", xctx->current_win_path, "_netlist red", NULL);
|
|
|
|
|
}
|
2023-11-05 00:14:55 +01:00
|
|
|
} else {
|
2023-11-06 16:47:14 +01:00
|
|
|
if(has_x) {
|
2024-03-03 00:40:51 +01:00
|
|
|
tclvareval(xctx->top_path, ".menubar.netlist configure -bg Green", NULL);
|
|
|
|
|
tclvareval("set tctx::", xctx->current_win_path, "_netlist Green", NULL);
|
2023-11-06 16:47:14 +01:00
|
|
|
}
|
2023-11-05 00:14:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='A' && rstate == 0) /* toggle show netlist */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-11-10 13:43:08 +01:00
|
|
|
int net_s;
|
|
|
|
|
net_s = tclgetboolvar("netlist_show");
|
|
|
|
|
net_s = !net_s;
|
|
|
|
|
if(net_s) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("alert_ { enabling show netlist window} {}");
|
|
|
|
|
tclsetvar("netlist_show","1");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tcleval("alert_ { disabling show netlist window } {}");
|
|
|
|
|
tclsetvar("netlist_show","0");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
if(key=='>') {
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-10-26 00:04:13 +02:00
|
|
|
if(xctx->draw_single_layer< cadlayers-1) xctx->draw_single_layer++;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
if(key=='<') {
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-10-26 00:04:13 +02:00
|
|
|
if(xctx->draw_single_layer>=0 ) xctx->draw_single_layer--;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key==':') /* toggle flat netlist (only spice) */
|
|
|
|
|
{
|
2022-09-18 05:29:16 +02:00
|
|
|
if(!tclgetboolvar("flat_netlist")) {
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("alert_ { enabling flat netlist} {}");
|
|
|
|
|
tclsetvar("flat_netlist","1");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tcleval("alert_ { set hierarchical netlist } {}");
|
|
|
|
|
tclsetvar("flat_netlist","0");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='B' && rstate == 0) /* edit schematic header/license */
|
2023-01-02 19:34:27 +01:00
|
|
|
{
|
|
|
|
|
tcleval("update_schematic_header");
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='b' && rstate==0) /* merge schematic */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-30 15:45:38 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
merge_file(0, ""); /* 2nd parameter not used any more for merge 25122002 */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-22 15:53:23 +02:00
|
|
|
if(key=='b' && EQUAL_MODMASK) /* hide/show instance details */
|
2020-09-05 00:58:56 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2021-11-16 22:28:10 +01:00
|
|
|
xctx->hide_symbols++;
|
|
|
|
|
if(xctx->hide_symbols >= 3) xctx->hide_symbols = 0;
|
|
|
|
|
tclsetintvar("hide_symbols", xctx->hide_symbols);
|
2020-09-05 00:58:56 +02:00
|
|
|
draw();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='D' && rstate == 0) /* delete files */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-10-24 23:46:19 +02:00
|
|
|
delete_files();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='x' && rstate == 0 ) /* new cad session */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2022-01-05 17:38:01 +01:00
|
|
|
new_xschem_process(NULL ,0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if((key=='#') && !(state & ControlMask) )
|
|
|
|
|
{
|
|
|
|
|
check_unique_names(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if((key=='#') && (state & ControlMask) )
|
|
|
|
|
{
|
|
|
|
|
check_unique_names(1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-06-17 23:58:35 +02:00
|
|
|
if( 0 && (key==';') && (state & ControlMask) ) /* testmode */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-10-09 22:19:54 +02:00
|
|
|
if(0 && key=='~' && (state & ControlMask)) { /* testmode */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(0 && key=='|' && !(state & ControlMask)) { /* testmode */
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-10-09 22:19:54 +02:00
|
|
|
if(0 && key=='|' && (state & ControlMask)) /* testmode */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='f' && rstate == ControlMask) /* search */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval("property_search");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='F' && rstate == ControlMask ) /* full zoom selection */
|
2022-01-08 00:00:13 +01:00
|
|
|
{
|
|
|
|
|
if(xctx->ui_state == SELECTION) {
|
|
|
|
|
zoom_full(1, 1, 3, 0.97);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if(key=='f' && rstate == 0 ) /* full zoom */
|
2023-03-09 22:48:25 +01:00
|
|
|
{
|
|
|
|
|
int flags = 1;
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-22 18:25:15 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-03-09 22:48:25 +01:00
|
|
|
if(tclgetboolvar("zoom_full_center")) flags |= 2;
|
|
|
|
|
zoom_full(1, 0, flags, 0.97);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-09-28 21:03:28 +02:00
|
|
|
if((key=='z' && rstate==ControlMask)) /* zoom out */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
view_unzoom(0.0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2023-06-10 17:24:12 +02:00
|
|
|
if(key=='!' && !(state & ControlMask))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2023-06-10 17:24:12 +02:00
|
|
|
break_wires_at_pins(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(key=='!' && (state & ControlMask))
|
|
|
|
|
{
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
|
|
|
|
break_wires_at_pins(1);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2023-06-10 17:24:12 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
case ButtonPress: /* end operation */
|
2022-04-28 10:12:16 +02:00
|
|
|
dbg(1, "callback(): ButtonPress ui_state=%d state=%d\n",xctx->ui_state,state);
|
2022-09-18 05:29:16 +02:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
2021-12-26 14:33:54 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-01-17 22:41:36 +01:00
|
|
|
if(xctx->ui_state & STARTPAN) {
|
|
|
|
|
xctx->ui_state &=~STARTPAN;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2022-01-29 02:36:54 +01:00
|
|
|
|
2021-12-22 18:25:15 +01:00
|
|
|
if(button == Button3 && state == ControlMask && xctx->semaphore <2)
|
2021-01-03 12:37:15 +01:00
|
|
|
{
|
2023-10-04 00:09:12 +02:00
|
|
|
Selected sel;
|
2024-03-05 11:57:15 +01:00
|
|
|
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
|
2023-10-04 00:09:12 +02:00
|
|
|
if(sel.type) select_connected_nets(1);
|
2021-01-03 12:37:15 +01:00
|
|
|
}
|
2023-12-09 00:32:41 +01:00
|
|
|
else if(button == Button3 && EQUAL_MODMASK && !(state & ShiftMask) && xctx->semaphore <2)
|
2023-06-13 11:51:16 +02:00
|
|
|
{
|
2023-09-22 10:40:57 +02:00
|
|
|
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 1);
|
|
|
|
|
}
|
2023-12-09 00:32:41 +01:00
|
|
|
else if(button == Button3 && EQUAL_MODMASK && (state & ShiftMask) && xctx->semaphore <2)
|
2023-09-22 10:40:57 +02:00
|
|
|
{
|
|
|
|
|
break_wires_at_point(xctx->mousex_snap, xctx->mousey_snap, 0);
|
2023-06-13 11:51:16 +02:00
|
|
|
}
|
2021-01-03 12:37:15 +01:00
|
|
|
else if(button == Button3 && state == ShiftMask && xctx->semaphore <2)
|
|
|
|
|
{
|
2023-10-04 00:09:12 +02:00
|
|
|
Selected sel;
|
2024-03-05 11:57:15 +01:00
|
|
|
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
|
2023-10-04 00:09:12 +02:00
|
|
|
if(sel.type) select_connected_nets(0);
|
2021-01-03 12:37:15 +01:00
|
|
|
}
|
|
|
|
|
else if(button == Button3 && state == 0 && xctx->semaphore <2) {
|
2024-03-06 12:53:49 +01:00
|
|
|
context_menu_action(xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-04 14:38:32 +01:00
|
|
|
/* Mouse wheel events */
|
|
|
|
|
else if(handle_mouse_wheel(event, mx, my, key, button, aux, state)) break;
|
2023-10-23 23:41:39 +02:00
|
|
|
/* Alt - Button1 click to unselect */
|
2023-09-22 15:53:23 +02:00
|
|
|
else if(button==Button1 && (SET_MODMASK) ) {
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->last_command = 0;
|
|
|
|
|
xctx->mx_save = mx; xctx->my_save = my;
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-05 11:57:15 +01:00
|
|
|
select_object(xctx->mousex, xctx->mousey, 0, 0, NULL);
|
2020-12-25 15:14:41 +01:00
|
|
|
rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
else if(button==Button2 && (state == 0)) {
|
2022-01-17 22:41:36 +01:00
|
|
|
pan(START, mx, my);
|
|
|
|
|
xctx->ui_state |= STARTPAN;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-03 04:20:05 +01:00
|
|
|
else if(xctx->semaphore >= 2) { /* button1 click to select another instance while edit prop dialog open */
|
2022-10-24 14:11:34 +02:00
|
|
|
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 */
|
2022-10-24 13:05:32 +02:00
|
|
|
tcleval(".dialog.buttons.ok invoke");
|
|
|
|
|
break;
|
2023-10-03 15:28:42 +02:00
|
|
|
} else if(button==Button1 && state==0 && tclgetvar("edit_symbol_prop_new_sel")[0]) {
|
2020-08-16 03:34:45 +02:00
|
|
|
tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke"); /* invoke 'OK' of edit prop dialog */
|
2023-10-03 15:28:42 +02:00
|
|
|
} else if(button==Button1 && (state & ShiftMask) && tclgetvar("edit_symbol_prop_new_sel")[0]) {
|
2024-03-05 11:57:15 +01:00
|
|
|
select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
|
2023-10-04 17:15:52 +02:00
|
|
|
tclsetvar("preserve_unchanged_attrs", "1");
|
2020-08-16 09:41:39 +02:00
|
|
|
rebuild_selected_array();
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-03-05 02:54:35 +01:00
|
|
|
else if(button==Button1) /* MOD button is not pressed here. Processed above */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2024-03-04 14:38:32 +01:00
|
|
|
xctx->drag_elements = 0;
|
2021-11-10 13:43:08 +01:00
|
|
|
if(tclgetboolvar("persistent_command") && xctx->last_command) {
|
2024-03-06 12:53:49 +01:00
|
|
|
if(xctx->last_command == STARTLINE) start_line(xctx->mousex_snap, xctx->mousey_snap);
|
|
|
|
|
if(xctx->last_command == STARTWIRE) start_wire(xctx->mousex_snap, xctx->mousey_snap);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2024-03-04 14:38:32 +01:00
|
|
|
/* handle all object insertions started from Tools menu */
|
|
|
|
|
if(check_menu_start_commands(c_snap)) break;
|
|
|
|
|
/* complete the STARTWIRE, STARTRECT, STARTZOOM, STARTCOPY ... operations */
|
2024-03-07 17:48:41 +01:00
|
|
|
if(end_place_move_copy_zoom()) break;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2023-10-23 23:41:39 +02:00
|
|
|
/* Button1Press to select objects */
|
2024-03-02 02:29:03 +01:00
|
|
|
if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) {
|
2023-10-04 00:09:12 +02:00
|
|
|
Selected sel;
|
2024-03-05 11:57:15 +01:00
|
|
|
int already_selected = 0;
|
2020-12-02 15:10:47 +01:00
|
|
|
int prev_last_sel = xctx->lastsel;
|
2024-03-05 10:04:39 +01:00
|
|
|
int no_shift_no_ctrl = !(state & (ShiftMask | ControlMask));
|
|
|
|
|
|
2024-03-04 16:33:20 +01:00
|
|
|
xctx->shape_point_selected = 0;
|
2020-12-06 16:10:22 +01:00
|
|
|
xctx->mx_save = mx; xctx->my_save = my;
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mx_double_save=xctx->mousex_snap;
|
|
|
|
|
xctx->my_double_save=xctx->mousey_snap;
|
2024-03-01 00:12:44 +01:00
|
|
|
|
2024-03-06 20:04:15 +01:00
|
|
|
/* Clicking on an instance pin -> drag a new wire
|
|
|
|
|
* if an instance is already selected */
|
|
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==ELEMENT) {
|
2024-03-07 00:08:47 +01:00
|
|
|
if(add_wire_from_inst_pin(&xctx->sel_array[0], xctx->mousex_snap, xctx->mousey_snap)) break;
|
2024-03-06 20:04:15 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 10:04:39 +01:00
|
|
|
if(!xctx->intuitive_interface && no_shift_no_ctrl ) unselect_all(1);
|
2024-03-05 11:57:15 +01:00
|
|
|
sel = find_closest_obj(xctx->mousex, xctx->mousey, 0);
|
|
|
|
|
|
2024-03-06 20:04:15 +01:00
|
|
|
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;
|
2024-03-05 11:57:15 +01:00
|
|
|
} /*end switch */
|
|
|
|
|
|
2024-03-06 16:27:14 +01:00
|
|
|
/* Clicking on an instance pin -> drag a new wire */
|
|
|
|
|
if(xctx->intuitive_interface && !already_selected) {
|
2024-03-07 00:08:47 +01:00
|
|
|
if(add_wire_from_inst_pin(&sel, xctx->mousex_snap, xctx->mousey_snap)) break;
|
2024-03-06 16:27:14 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 13:02:53 +01:00
|
|
|
if(xctx->intuitive_interface && !already_selected && no_shift_no_ctrl ) unselect_all(1);
|
|
|
|
|
|
2024-03-05 11:57:15 +01:00
|
|
|
if(!already_selected) select_object(xctx->mousex, xctx->mousey, SELECTED, 0, &sel);
|
2024-03-04 17:13:36 +01:00
|
|
|
rebuild_selected_array();
|
2024-03-05 02:54:35 +01:00
|
|
|
|
2024-03-04 14:38:32 +01:00
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON)
|
2024-03-04 16:33:20 +01:00
|
|
|
if(edit_polygon_point(state)) break; /* sets xctx->shape_point_selected */
|
|
|
|
|
|
|
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==xRECT)
|
|
|
|
|
if(edit_rect_point(state)) break; /* sets xctx->shape_point_selected */
|
2024-03-03 20:13:43 +01:00
|
|
|
|
2024-03-04 17:13:36 +01:00
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==LINE)
|
|
|
|
|
if(edit_line_point(state)) break; /* sets xctx->shape_point_selected */
|
|
|
|
|
|
|
|
|
|
if(xctx->lastsel == 1 && xctx->sel_array[0].type==WIRE)
|
|
|
|
|
if(edit_wire_point(state)) break; /* sets xctx->shape_point_selected */
|
|
|
|
|
|
2024-03-02 14:15:30 +01:00
|
|
|
/* intuitive interface: directly drag elements */
|
2024-03-02 16:03:37 +01:00
|
|
|
if(sel.type && xctx->intuitive_interface && xctx->lastsel >= 1 &&
|
2024-03-04 16:33:20 +01:00
|
|
|
!xctx->shape_point_selected) {
|
2024-03-09 06:08:22 +01:00
|
|
|
/* xctx->push_undo(); */
|
2024-03-03 05:15:51 +01:00
|
|
|
xctx->drag_elements = 1;
|
|
|
|
|
|
2024-03-07 17:48:41 +01:00
|
|
|
if( state & ControlMask && !tclgetboolvar("enable_stretch")) {
|
2024-03-03 05:15:51 +01:00
|
|
|
select_attached_nets(); /* stretch nets that land on selected instance pins */
|
|
|
|
|
}
|
2024-03-07 17:48:41 +01:00
|
|
|
|
|
|
|
|
if(state == (ShiftMask | ControlMask) ) {
|
|
|
|
|
xctx->connect_by_kissing = 2; /* 2 will be used to reset var to 0 at end of move */
|
|
|
|
|
move_objects(START,0,0,0);
|
|
|
|
|
}
|
|
|
|
|
else if(state == ShiftMask) copy_objects(START);
|
2024-03-18 02:39:54 +01:00
|
|
|
else move_objects(START,0,0,0);
|
2024-03-02 14:15:30 +01:00
|
|
|
}
|
|
|
|
|
|
2023-10-04 00:09:12 +02:00
|
|
|
#ifndef __unix__
|
2022-01-13 17:24:04 +01:00
|
|
|
draw_selection(xctx->gc[SELLAYER], 0);
|
2023-10-04 00:09:12 +02:00
|
|
|
#endif
|
2024-03-04 16:33:20 +01:00
|
|
|
if(tclgetboolvar("auto_hilight") && !xctx->shape_point_selected) {
|
2024-03-02 02:29:03 +01:00
|
|
|
if(!(state & ShiftMask) && xctx->hilight_nets && sel.type == 0 ) {
|
2020-09-01 10:50:08 +02:00
|
|
|
if(!prev_last_sel) {
|
2021-01-08 21:25:11 +01:00
|
|
|
redraw_hilights(1); /* 1: clear all hilights, then draw */
|
2020-09-01 10:50:08 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
hilight_net(0);
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->lastsel) {
|
2021-01-08 21:25:11 +01:00
|
|
|
redraw_hilights(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} /* button==Button1 */
|
|
|
|
|
break;
|
2024-03-01 00:12:44 +01:00
|
|
|
|
2024-03-05 23:17:42 +01:00
|
|
|
case ButtonRelease:
|
2024-03-03 02:24:38 +01:00
|
|
|
if(waves_selected(event, key, state, button)) {
|
|
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-03-20 18:43:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* launcher, no intuitive interface */
|
|
|
|
|
if(!xctx->intuitive_interface && state == (Button1Mask | ControlMask)) {
|
|
|
|
|
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) &&
|
2024-03-18 02:39:54 +01:00
|
|
|
xctx->deltax == 0 && xctx->deltay == 0) {
|
|
|
|
|
int savesem = xctx->semaphore;
|
|
|
|
|
move_objects(ABORT,0,0,0);
|
|
|
|
|
xctx->semaphore = 0;
|
|
|
|
|
launcher(); /* works only if lastsel == 1 */
|
|
|
|
|
xctx->semaphore = savesem;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-03 20:13:43 +01:00
|
|
|
/* end intuitive_interface copy or move */
|
|
|
|
|
if(xctx->ui_state & STARTCOPY && xctx->drag_elements) {
|
|
|
|
|
copy_objects(END);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-03 20:13:43 +01:00
|
|
|
xctx->drag_elements = 0;
|
|
|
|
|
}
|
|
|
|
|
else if(xctx->ui_state & STARTMOVE && xctx->drag_elements) {
|
2024-03-02 14:15:30 +01:00
|
|
|
move_objects(END,0,0,0);
|
2024-03-08 00:48:05 +01:00
|
|
|
xctx->constr_mv=0;
|
|
|
|
|
tcleval("set constr_mv 0" );
|
2024-03-02 14:15:30 +01:00
|
|
|
xctx->drag_elements = 0;
|
|
|
|
|
}
|
2024-03-03 20:13:43 +01:00
|
|
|
|
2024-03-04 16:33:20 +01:00
|
|
|
/* if a polygon/bezier/rectangle control point was clicked, end point move operation
|
2024-03-03 20:13:43 +01:00
|
|
|
* and set polygon state back to SELECTED from SELECTED1 */
|
2024-03-04 16:33:20 +01:00
|
|
|
else if((xctx->ui_state & (STARTMOVE | SELECTION)) && xctx->shape_point_selected) {
|
2024-03-05 02:54:35 +01:00
|
|
|
end_shape_point_edit();
|
2024-03-01 00:12:44 +01:00
|
|
|
}
|
2024-03-07 00:08:47 +01:00
|
|
|
|
2022-01-17 22:41:36 +01:00
|
|
|
if(xctx->ui_state & STARTPAN) {
|
|
|
|
|
xctx->ui_state &=~STARTPAN;
|
2022-07-25 10:09:35 +02:00
|
|
|
/* xctx->mx_save = mx; xctx->my_save = my; */
|
|
|
|
|
/* xctx->mx_double_save=xctx->mousex_snap; */
|
|
|
|
|
/* xctx->my_double_save=xctx->mousey_snap; */
|
2020-12-29 03:45:12 +01:00
|
|
|
redraw_w_a_l_r_p_rubbers();
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2022-04-28 10:12:16 +02:00
|
|
|
dbg(1, "callback(): ButtonRelease ui_state=%d state=%d\n",xctx->ui_state,state);
|
2020-12-03 04:20:05 +01:00
|
|
|
if(xctx->semaphore >= 2) break;
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->ui_state & STARTSELECT) {
|
2020-08-08 15:47:34 +02:00
|
|
|
if(state & ControlMask) {
|
2023-09-24 00:29:15 +02:00
|
|
|
int es = tclgetboolvar("enable_stretch");
|
|
|
|
|
tclsetboolvar("enable_stretch", !es);
|
2020-08-08 15:47:34 +02:00
|
|
|
select_rect(END,-1);
|
2023-09-24 00:29:15 +02:00
|
|
|
tclsetboolvar("enable_stretch", es);
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2024-03-01 00:12:44 +01:00
|
|
|
/* Button1 release: end of rectangle select */
|
|
|
|
|
if(!(state & (Button4Mask|Button5Mask) ) ) {
|
|
|
|
|
select_rect(END,-1);
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-09-01 10:50:08 +02:00
|
|
|
rebuild_selected_array();
|
2020-10-12 13:13:31 +02:00
|
|
|
my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d path: %s",
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->mousex_snap, xctx->mousey_snap, xctx->lastsel, xctx->sch_path[xctx->currsch] );
|
2020-09-01 10:50:08 +02:00
|
|
|
statusmsg(str,1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2024-03-04 20:42:29 +01:00
|
|
|
if(draw_xhair) draw_crosshair(0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
case -3: /* double click : edit prop */
|
2022-09-18 05:29:16 +02:00
|
|
|
if( waves_selected(event, key, state, button)) {
|
2022-01-27 20:47:27 +01:00
|
|
|
waves_callback(event, mx, my, key, button, aux, state);
|
|
|
|
|
break;
|
2022-07-31 09:06:10 +02:00
|
|
|
} else {
|
|
|
|
|
if(xctx->semaphore >= 2) break;
|
|
|
|
|
dbg(1, "callback(): DoubleClick ui_state=%d state=%d\n",xctx->ui_state,state);
|
|
|
|
|
if(button==Button1) {
|
2023-10-04 00:09:12 +02:00
|
|
|
Selected sel;
|
2023-09-25 15:28:40 +02:00
|
|
|
if(!xctx->lastsel && xctx->ui_state == 0) {
|
2023-09-24 00:17:48 +02:00
|
|
|
/* Following 5 lines do again a selection overriding lock,
|
|
|
|
|
* so locked instance attrs can be edited */
|
2024-03-05 11:57:15 +01:00
|
|
|
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 1, NULL);
|
2023-10-04 00:09:12 +02:00
|
|
|
if(sel.type) {
|
2023-09-24 00:17:48 +02:00
|
|
|
xctx->ui_state = SELECTION;
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-31 09:06:10 +02:00
|
|
|
if(xctx->ui_state == 0 || xctx->ui_state == SELECTION) {
|
|
|
|
|
edit_property(0);
|
|
|
|
|
} else {
|
|
|
|
|
if(xctx->ui_state & STARTWIRE) {
|
|
|
|
|
xctx->ui_state &= ~STARTWIRE;
|
|
|
|
|
}
|
|
|
|
|
if(xctx->ui_state & STARTLINE) {
|
|
|
|
|
xctx->ui_state &= ~STARTLINE;
|
|
|
|
|
}
|
|
|
|
|
if( (xctx->ui_state & STARTPOLYGON) && (state ==0 ) ) {
|
2024-03-06 12:53:49 +01:00
|
|
|
new_polygon(SET, xctx->mousex_snap, xctx->mousey_snap);
|
2022-07-31 09:06:10 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-03-05 23:17:42 +01:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
#ifndef __unix__
|
|
|
|
|
case MOUSE_WHEEL_UP: /* windows do not use button4 and button5 like X */
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->xorigin += -CADMOVESTEP * xctx->zoom / 2.;
|
2020-08-08 15:47:34 +02:00
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
default:
|
|
|
|
|
dbg(1, "callback(): Event:%d\n",event);
|
|
|
|
|
break;
|
2021-11-16 22:28:10 +01:00
|
|
|
} /* switch(event) */
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2023-10-22 02:53:03 +02:00
|
|
|
if(xctx->semaphore > 0) xctx->semaphore--;
|
2021-11-16 22:28:10 +01:00
|
|
|
if(redraw_only) {
|
|
|
|
|
xctx->semaphore--; /* decrement articially incremented semaphore (see above) */
|
|
|
|
|
dbg(1, "callback(): semaphore >=2 restoring window context: %s <-- %s\n", old_winpath, winpath);
|
2023-10-25 11:43:43 +02:00
|
|
|
if(old_winpath[0]) new_schematic("switch_no_tcl_ctx", old_winpath, "", 1);
|
2021-11-16 22:28:10 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(strcmp(old_winpath, winpath)) {
|
|
|
|
|
if(old_winpath[0]) dbg(1, "callback(): reset old_winpath: %s <- %s\n", old_winpath, winpath);
|
|
|
|
|
my_strncpy(old_winpath, winpath, S(old_winpath));
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|