/* * COPYRIGHT * * cschem - modular/flexible schematics editor - libcschem (core library) * Copyright (C) 2022 Tibor 'Igor2' Palinkas * * (Supported by NLnet NGI0 PET Fund in 2022) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version.* * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA * * Contact: * Project page: http://repo.hu/projects/sch-rnd * contact lead developer: http://www.repo.hu/projects/sch-rnd/contact.html * mailing list: http://www.repo.hu/projects/sch-rnd/contact.html */ /* Low level operation implementations that are common to multiple objects */ #include "config.h" #include #include "event.h" #include "cnc_obj.h" #include "operation.h" #include "cnc_conn.h" #include "undo.h" #include "util_wirenet.h" #include "extobj.h" #include "op_common.h" static const char csch_operation_cookie[] = "libcschem/op_common.c"; /*** Remove ***/ static int undo_remove_undo(void *udata) { csch_undo_remove_t *u = udata; csch_chdr_t *obj = u->obj; const csch_ops_t *ops = csch_op_get(obj->type); assert(ops->remove_undo != NULL); ops->remove_undo(u); csch_sheet_set_changed(obj->sheet, 1); return 0; } static int undo_remove_redo(void *udata) { csch_undo_remove_t *u = udata; csch_chdr_t *obj = u->obj; const csch_ops_t *ops = csch_op_get(obj->type); assert(ops->remove_redo != NULL); ops->remove_redo(u); csch_sheet_set_changed(obj->sheet, 1); return 0; } static void undo_crem_print(void *udata, char *dst, size_t dst_len, const char *op) { csch_undo_remove_t *u = udata; csch_oidpath_t oidp = {0}; char *path; const char *st = ""; int len; csch_oidpath_from_obj(&oidp, u->obj); path = csch_oidpath_to_str(&oidp); if (u->obj->link.parent == &u->sheet->active) st = "active"; else if (u->obj->link.parent == &u->sheet->deleted) st = "deleted"; len = rnd_snprintf(dst, dst_len, "%s: %s %s (%s)", op, csch_ctype_name(u->obj->type), path, st); if (csch_obj_is_grp(u->obj)) { csch_cgrp_t *grp = (csch_cgrp_t *)u->obj; const char *role = csch_attrib_get_str(&grp->attr, "role"); const char *name = csch_attrib_get_str(&grp->attr, "name"); if (role != NULL) { dst_len -= len; dst += len; rnd_snprintf(dst, dst_len, " role=%s", role); } if (name != NULL) { dst_len -= len; dst += len; rnd_snprintf(dst, dst_len, " name=%s", name); } } csch_oidpath_free(&oidp); free(path); } static void undo_remove_print(void *udata, char *dst, size_t dst_len) { undo_crem_print(udata, dst, dst_len, "remove"); } static const uundo_oper_t undo_remove = { csch_operation_cookie, NULL, /* free */ undo_remove_undo, undo_remove_redo, undo_remove_print }; csch_undo_remove_t *csch_op_remove_alloc_undo(csch_sheet_t *sheet) { return uundo_append(&sheet->undo, &undo_remove, sizeof(csch_undo_remove_t)); } csch_chdr_t *csch_cnc_common_remove_redo(csch_undo_remove_t *u, csch_cnc_common_remove_t how) { csch_chdr_t *obj = u->obj; if (how & CSCH_REM_FROM_RTREE) csch_cobj_rtree_del(obj->sheet, obj); if ((how & CSCH_REM_FROM_PARENT) && (obj != &obj->sheet->direct.hdr) && (obj != &obj->sheet->indirect.hdr)) { assert(obj->parent != NULL); u->parent = obj->parent; htip_pop(&obj->parent->id2obj, obj->oid); gdl_remove(&u->sheet->active, obj, link); gdl_append(&u->sheet->deleted, obj, link); obj->parent = NULL; } csch_cobj_redraw(obj); return obj; } csch_chdr_t *csch_cnc_common_remove_undo(csch_undo_remove_t *u, csch_cnc_common_remove_t how) { csch_chdr_t *obj = u->obj; if (how & CSCH_REM_FROM_PARENT) { obj->parent = u->parent; assert(obj->parent != NULL); htip_insert(&obj->parent->id2obj, obj->oid, obj); gdl_remove(&u->sheet->deleted, obj, link); gdl_append(&u->sheet->active, obj, link); } if (how & CSCH_REM_FROM_RTREE) csch_cobj_rtree_add(obj->sheet, obj); csch_cobj_redraw(obj); return obj; } /*** Create ***/ static void undo_create_print(void *udata, char *dst, size_t dst_len) { undo_crem_print(udata, dst, dst_len, "create"); } static const uundo_oper_t undo_create = { csch_operation_cookie, NULL, /* free */ undo_remove_redo, /* swapped: create is reverse order remove */ undo_remove_undo, /* swapped: create is reverse order remove */ undo_create_print }; /*** MISC ***/ csch_chdr_t *csch_op_inserted(csch_sheet_t *sheet, csch_cgrp_t *parent, csch_chdr_t *obj) { csch_undo_create_t *u = uundo_append(&sheet->undo, &undo_create, sizeof(csch_undo_create_t)); u->sheet = sheet; u->obj = obj; u->parent = obj->parent; u->side_effects = 0; if (csch_obj_is_grp(obj)) /* e.g. terminal or symbol moved/added in user op */ csch_conn_auto_recalc(sheet, obj); if (obj->parent->role == CSCH_ROLE_WIRE_NET) /* new wire added in a wirenet */ csch_wirenet_recalc_obj_conn(sheet, obj); csch_undo_inc_serial(sheet); csch_cobj_redraw(obj); return obj; } void csch_op_geo_edited(csch_sheet_t *sheet, csch_chdr_t *obj) { if (obj->floater) csch_extrobj_floater_edit_post(obj->parent, obj); csch_sheet_set_changed(obj->sheet, 1); csch_cobj_redraw(obj); }