/* * COPYRIGHT * * cschem - modular/flexible schematics editor - libcschem (core library) * Copyright (C) 2018, 2022, 2024 Tibor 'Igor2' Palinkas * * 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 */ #ifndef CSCH_CONCRETE_H #define CSCH_CONCRETE_H #include #include #include #include #include "libcschem/common_types.h" #include "libcschem/rtree.h" #include "libcschem/attrib.h" #include "libcschem/oidpath.h" #include #include #include #include #include #include #include #include GENGEO2D_TYPECFG #include /* the two top level sheet groups have hardwired OIDs by the spec */ #define CSCH_TOP_OID_INDIRECT 1 #define CSCH_TOP_OID_DIRECT 2 typedef enum csch_displayer_e { CSCH_DSPLY_BACKGROUND, /* bottom: decoration */ CSCH_DSPLY_WIRE, /* wiring: wires, hubs, anything non-bus */ CSCH_DSPLY_BUS, /* buses only */ CSCH_DSPLY_SYMBOL, /* symbol graphics that are not in HUBTERM */ CSCH_DSPLY_HUBTERM, /* non-in-symbol hubs, terminals (overrides symbol so symbol terminals are included) */ CSCH_DSPLY_DECORATION, /* text, annotations, titleblocks */ CSCH_DSPLY_SYMBOL_GRP, /* symbol groups and group refs */ CSCH_DSPLY_CONN, /* connections or missing connections */ CSCH_DSPLY_SYMBOL_META, /* symbol bbox and loclib info */ CSCH_DSPLY_TEXT_META, /* text bbox and orientation */ CSCH_DSPLY_max, CSCH_DSPLY_invalid = -1 } csch_displayer_t; extern int csch_layer_vis[CSCH_DSPLY_max]; extern int csch_export_layer_vis[CSCH_DSPLY_max]; typedef enum csch_ctype_s { CSCH_CTYPE_invalid = 0, CSCH_CTYPE_LINE, CSCH_CTYPE_ARC, CSCH_CTYPE_POLY, CSCH_CTYPE_TEXT, CSCH_CTYPE_BITMAP, CSCH_CTYPE_CONN, CSCH_CTYPE_GRP, CSCH_CTYPE_GRP_REF, CSCH_CTYPE_PEN, CSCH_CTYPE_max } csch_ctype_t; typedef enum csch_cmask_s { CSCH_CMASK_LINE = (1 << CSCH_CTYPE_LINE), CSCH_CMASK_ARC = (1 << CSCH_CTYPE_ARC), CSCH_CMASK_POLY = (1 << CSCH_CTYPE_POLY), CSCH_CMASK_TEXT = (1 << CSCH_CTYPE_TEXT), CSCH_CMASK_BITMAP = (1 << CSCH_CTYPE_BITMAP), CSCH_CMASK_CONN = (1 << CSCH_CTYPE_CONN), CSCH_CMASK_GRP = (1 << CSCH_CTYPE_GRP), CSCH_CMASK_GRP_REF = (1 << CSCH_CTYPE_GRP_REF), CSCH_CMASK_PEN = (1 << CSCH_CTYPE_PEN), /* composites */ CSCH_CMASK_ANY_GRP = CSCH_CMASK_GRP | CSCH_CMASK_GRP_REF, CSCH_CMASK_ANY_ATOM = CSCH_CMASK_LINE | CSCH_CMASK_ARC | CSCH_CMASK_POLY | CSCH_CMASK_TEXT | CSCH_CMASK_BITMAP, CSCH_CMASK_ANY = 65535 } csch_cmask_t; typedef enum csch_role_s { CSCH_ROLE_invalid, CSCH_ROLE_empty, CSCH_ROLE_BUS_NET, CSCH_ROLE_BUS_TERMINAL, CSCH_ROLE_HUB_POINT, CSCH_ROLE_SYMBOL, CSCH_ROLE_TERMINAL, CSCH_ROLE_WIRE_NET, CSCH_ROLE_JUNCTION, /* extensions: not in the data model */ CSCH_ROLE_EXTOBJ_GFX } csch_role_t; typedef struct csch_comm_str_s { const char *str; /* sheet comm_str hash key */ } csch_comm_str_t; struct csch_chdr_s { csch_rtree_box_t bbox; /* CACHE: first field to easy rtree handling */ csch_oid_t oid; csch_ctype_t type; csch_cgrp_t *parent; csch_comm_str_t stroke_name, fill_name; /* used to resolve pen */ gdl_elem_t link; /* sheet's active or removed list */ /* common properties (as per {des3:81}) */ unsigned int lock:1; /* deduced from the lock attribute */ unsigned int floater:1; /* deduced from the floater attribute */ /*** cached ***/ csch_cpen_t *stroke, *fill; csch_sheet_t *sheet; csch_displayer_t dsply; vtp0_t conn; /* in which connections the current object participates */ struct { csch_cgrp_t *g; /* grp_ref that hosts transformations for this object */ long idx; /* transformation index within grpref's child_xform array */ } grp_ref_xform; unsigned int indirect:1; /*** gui states (not saved) ***/ unsigned int selected:1; unsigned int hilight:1; /** for integrity check and other sync plugins ***/ unsigned mark:1; unsigned visit:1; void *mark_ptr; }; typedef struct csch_extobj_impl_s csch_extobj_impl_t; struct csch_cgrp_s { /* type=CSCH_CTYPE_GRP || CSCH_CTYPE_GRP_REF */ csch_chdr_t hdr; minuid_bin_t uuid; /* instance (changes on dup/copy) */ htsp_t attr; htip_t id2obj; /* members (memb): id -> object pointer (primary storage); also acts as a list of active children objects */ htsp_t name2pen; /* all pen directly under this group; key: pen->name; value: pen */ char *loclib_name; /* name used in the local library only */ union { struct { /* type=CSCH_CTYPE_GRP */ csch_oid_t next_id; minuid_bin_t src_uuid; /* initial/source uuid (filled in on initial allocation, preserved on dup/copy) */ } grp; struct { /* type=CSCH_CTYPE_GRP_REF */ char *ref_str; /* xorcache: will be NULL once ->grp is resolved */ csch_cgrp_t *grp; /* xorcache: NULL only when ref_str is not NULL */ vtp0_t child_xform; /* an array of child transformations (csch_child_xform_t) */ } ref; } data; double spec_rot; csch_coord_t x, y; unsigned mirx:1, miry:1; /* cache */ const char *srole; /* string version of the role: points into the attributes */ csch_role_t role; /* symbolic version, resolved once when the string is changed */ struct { /* accumulated transformations: parent's + local offset/rot/mirror */ g2d_xform_t mx; /* resulting matrix for quick coord transformations */ double rot; csch_coord_t x, y; unsigned mirx:1, miry:1; } xform; unsigned wirenet_recalc_lock:1; unsigned wirenet_split_lock:1; unsigned sym_prefer_loclib:1; /* this group is a symbol that should be put in the local lib and converted to a group ref if global config permits */ vtl0_t aid; /* link to the abstract objects compiled from this group; zero or one in flat design but can be more in hierarchic */ char *file_name; /* hint: trace file name from which the group was loaded, if available */ csch_rtree_box_t bbox_flt; /* bounding box with floaters included (e.g. for sheet size) */ const csch_extobj_impl_t *extobj; /* handler; not NULL if extobj attrib is set, but if implementation no found, all fields are NULL */ long extobj_inhibit; /* if >0 do not call extobj hooks */ }; typedef enum csch_sheet_type_e { CSCH_SHTY_unknown, CSCH_SHTY_UNLISTED, /* not explicitly listen in the project file, just happens to be in the same dir */ CSCH_SHTY_ROOT, /* explicitly listed in project file as a root sheet */ CSCH_SHTY_AUX, /* explicitly listed in project file as an aux sheet */ CSCH_SHTY_EXTERNAL /* not explicitly listen in the project file, loaded during compilation, for hierarchy */ } csch_sheet_type_t; struct csch_sheet_s { rnd_design_t hidlib; long uid; csch_rtree_t dsply[CSCH_DSPLY_max]; /* object strokes to draw per display layer */ csch_rtree_t dsply_fill[CSCH_DSPLY_max]; /* fills to draw per display layer */ csch_cgrp_t direct, indirect; /* a sheet is really made of groups to keep the code simple */ /* (sheet attributes are in the direct, the indirect group is for the "local library") */ char *newname; /* special case: if a new sheet is created, loadname will be NULL but we need to remember what we loaded for new sheet for revert to work; for non-new-sheets this is NULL but ->hidlib.loadname is non-NULL */ char *loadfmt; /* format request used at original load */ csch_rtree_box_t bbox; unsigned bbox_changed:1; /* set when bbox changed (bumped) by object editing; used and reset by the GUI */ unsigned non_graphical:1; /* sheet specified by data, not drawing */ void *non_graphical_data; /* filled in and used by the plugin dealing with the non-graphical format when ->non_graphical==1 */ csch_non_graphical_impl_t *non_graphical_impl; /* list of all objects ever allocated for the sheet */ gdl_list_t active, deleted; csch_comm_str_t junction_pen_name; /* the caller may change this; used whenever junction needs to be placed in wirenet recalc */ /* caches and temporary storage */ uundo_list_t undo; htsp_t comm_str; /* common strings, like pen names, stored only once; key=strdup(str), val=NULL; referenceed as csch_comm_str_t */ csch_oid_t auto_oid; /* negative oids for objects that have automatically assigned oid; decrease first, use after */ vtp0_t libs; /* indexed by csch_lib_master_t->uid, resolves to (csch_lib_root_t *); each sheet needs an own set because of local configuration may differ */ vtp0_t local_libs; /* same as libs but operates on sheet->indirect */ csch_chdr_t *currobj; /* for propset @ */ csch_rtree_box_t invbox; /* an application may keep track on redraw bbox here - maintained by libcschem*/ long redraw_inhibit; /* when >0 do not draw but collect invalidated box - maintained by libcschem */ unsigned invbox_valid:1; /* whether invbox is a valid box that could be drawn */ unsigned saving:1; /* set to 1 while the sheet is being saved (helps inhibiting some change indications on the UI) */ unsigned warned_too_large:1; /* whether a sheet-too-large warning has already been generated for this sheet */ struct { int recalc_inhibit; htpi_t recalc_wn; } util_wirenet; unsigned load_pending:1; /* when set, the sheet has not yet been loaded (but got referenced from the project file) */ unsigned loose_sym:1; /* allow editing symbol part objects, bypassing the symbol lock */ unsigned is_symbol:1; /* if 1: we are in symbol editing mode */ unsigned changed:1; /* whether data has been edited since last save */ csch_sheet_type_t stype; /* sheet type/role within the project */ char *design_dir; /* for rc.paths.desgin */ /* Autocomp timer */ long acp_remain; /* remaining time in milisec; 0 means not started */ long acp_starting; /* starting time in milisec; used to update the progress bar */ /* plugins */ double infobar_last_date; }; /* Standard low level object operations; when int, return 0 for success */ typedef struct csch_cop_s { csch_chdr_t *(*remove)(csch_sheet_t *dst, csch_chdr_t *obj); csch_chdr_t *(*dup)(csch_chdr_t *obj); csch_chdr_t *(*move)(csch_chdr_t *obj, csch_coord_t dx, csch_coord_t dy); csch_chdr_t *(*move_to)(csch_sheet_t *dst, csch_chdr_t *obj); csch_chdr_t *(*rotate90)(csch_chdr_t *obj, csch_coord_t dx, csch_coord_t dy, int steps); csch_chdr_t *(*rotate)(csch_chdr_t *obj, csch_coord_t dx, csch_coord_t dy, double ang, double cosx, double sinx); csch_chdr_t *(*mirrorx)(csch_chdr_t *obj, csch_coord_t ox); /* mirror x coordinates (around the y axis) */ csch_chdr_t *(*mirrory)(csch_chdr_t *obj, csch_coord_t oy); /* mirror y coordinates (around the x axis) */ } csch_cop_t; typedef enum csch_hash_ignore_u { /* bitfield: which properties to ignore in objects hashing */ CSCH_HIGN_FLOATER_GEO = 1, /* recursively ignore floater geometry (position, transformations) */ CSCH_HIGN_GRP_ATTRIB = 2, /* ignore root group's attributes */ CSCH_HIGN_GRP_PLACEMENT = 4 /* ignore root group's placement */ } csch_hash_ignore_t; csch_sheet_t *csch_sheet_init(csch_sheet_t *sheet, csch_project_t *parent); void csch_sheet_uninit(csch_sheet_t *sheet); csch_sheet_t *csch_sheet_alloc(csch_project_t *parent); void csch_sheet_free(csch_sheet_t *); RND_INLINE const csch_rtree_box_t *csch_sheet_bbox(csch_sheet_t *sheet); void csch_sheet_bbox_update(csch_sheet_t *sheet); csch_oid_t csch_oid_new(csch_sheet_t *sheet, csch_cgrp_t *grp); /* Return the human readable name of a display layer, or "" */ const char *csch_dsply_name(csch_displayer_t dsply); /* Return the sheet's rtree for a name; the name may be suffixed with -fill or -stroke for selecting the appropriate rtree. If not suffixed, the stroke rtree is returned. */ csch_rtree_t *csch_rtree_lookup_by_name(csch_sheet_t *sheet, const char *name); /* Return the human readable name of concrete object type, or "" */ const char *csch_ctype_name(csch_ctype_t typ); /* Copy header metadata (like display layer and pen OID) while dupping an object */ void csch_chdr_copy_meta4dup(csch_chdr_t *dst, const csch_chdr_t *src); /* Return the full oidpath of chdr renderd in text; caller needs to free the returned string */ char *csch_chdr_to_oidpath_str(const csch_chdr_t *chdr); /* An object is selected if it is ->selected or if any of its parents is ->selected */ RND_INLINE int csch_chdr_is_selected(csch_chdr_t *obj); /* An object is selected if it is ->selected or if any of its parents is ->selected */ RND_INLINE int csch_chdr_any_parent_selected(csch_chdr_t *obj); /* Return common string for str; if not already allocated and alloc != 0, strup and insert str to common strings. If str is NULL or not found/allocated, returns a comm_str with NULL str */ csch_comm_str_t csch_comm_str(csch_sheet_t *sheet, const char *str, int alloc); /*** implementation ***/ RND_INLINE const csch_rtree_box_t *csch_sheet_bbox(csch_sheet_t *sheet) { if (csch_bbox_is_invalid(&sheet->bbox)) csch_sheet_bbox_update(sheet); return &sheet->bbox; } RND_INLINE int csch_chdr_is_selected(csch_chdr_t *obj) { for(;obj != NULL; obj = &obj->parent->hdr) if (obj->selected) return 1; return 0; } RND_INLINE int csch_chdr_any_parent_selected(csch_chdr_t *obj) { return csch_chdr_is_selected(&obj->parent->hdr); } /* Returns 1 if obj is a group or group ref, 0 for other objects */ RND_INLINE int csch_obj_is_grp(const csch_chdr_t *obj) { return ((obj != NULL) && ((obj->type == CSCH_CTYPE_GRP) || (obj->type == CSCH_CTYPE_GRP_REF))); } /* Returns 1 if obj is deleted (not part of the active objects of the sheet) */ RND_INLINE int csch_obj_is_deleted(const csch_chdr_t *obj) { return (obj->link.parent == &obj->sheet->deleted); } #define csch_ctype_in_cmask(type, mask) (!!((1 << (type)) & (mask))) #define CSCH_ACT_SHEET ((csch_sheet_t *)argv[0].val.argv0.user_call_ctx) /* Call with new_val=1 after any sheet edit */ void csch_sheet_set_changed(csch_sheet_t *sheet, int new_val); #endif