/* * COPYRIGHT * * cschem - modular/flexible schematics editor - sch-rnd (executable) * Copyright (C) 2020 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 */ #include "config.h" #include "operation.h" #include "search.h" #include "cnc_obj.h" typedef struct { csch_rtree_box_t *query; csch_rtree_cb_t *found_obj; void *found_ctx; int find_grp_bbox; /* when 1 any overlap with the group's bbox is enough for a match, else require an object overlap */ } search_ctx_t; static csch_rtree_dir_t search_obj(void *ctx_, void *obj_, const csch_rtree_box_t *box) { search_ctx_t *ctx = ctx_; /* csch_chdr_t *obj = obj_;*/ TODO("detailed check for intersection"); return ctx->found_obj(ctx->found_ctx, obj_, box); return csch_RTREE_DIR_NOT_FOUND_CONT; } csch_rtree_dir_t csch_search(csch_sheet_t *sheet, csch_rtree_box_t *query, csch_rtree_cb_t *found_obj, void *ctx) { int n; csch_rtree_dir_t res, state = 0; search_ctx_t sctx; sctx.query = query; sctx.found_obj = found_obj; sctx.found_ctx = ctx; for(n = CSCH_DSPLY_max-1; n >= 0; n--) { if (!csch_layer_vis[n]) continue; sctx.find_grp_bbox = (n >= CSCH_DSPLY_SYMBOL); res = csch_rtree_search_obj(&sheet->dsply[n], query, search_obj, &sctx); state |= res; if (res & csch_RTREE_DIR_STOP) break; } return state; } csch_rtree_dir_t csch_search_obj_first_cb(void *ctx_, void *obj_, const csch_rtree_box_t *box) { csch_chdr_t *obj = obj_; csch_search_obj_first_t *ctx = ctx_; long score = 1, locked; if (!csch_isc_with_box(obj, ctx->query)) return csch_RTREE_DIR_NOT_FOUND_CONT; if ((ctx->mask != 0) && !csch_ctype_in_cmask(obj->type, ctx->mask)) return csch_RTREE_DIR_NOT_FOUND_CONT; if (ctx->ignore_wirenet_grp && csch_obj_is_grp(obj)) { csch_cgrp_t *grp = (csch_cgrp_t *)obj; if (grp->role == CSCH_ROLE_WIRE_NET) return csch_RTREE_DIR_NOT_FOUND_CONT; } if ((ctx->ignore != NULL) && (ctx->ignore(ctx, obj))) return csch_RTREE_DIR_NOT_FOUND_CONT; switch(obj->type) { case CSCH_CTYPE_GRP: score = 1000; break; case CSCH_CTYPE_GRP_REF: score = 1000; break; case CSCH_CTYPE_POLY: score = 2000; break; case CSCH_CTYPE_BITMAP: score = 3000; break; case CSCH_CTYPE_TEXT: score = 4000; break; case CSCH_CTYPE_LINE: score = 5000*16; break; /* *16 means even a floater text won't win over a line, e.g. in a terminal */ case CSCH_CTYPE_ARC: score = 5000*16; break; case CSCH_CTYPE_CONN: case CSCH_CTYPE_PEN: case CSCH_CTYPE_invalid: case CSCH_CTYPE_max: return csch_RTREE_DIR_NOT_FOUND_CONT; } if (ctx->explicitly_locked_only) { locked = csch_cobj_is_explicit_locked(obj); if (!locked) return csch_RTREE_DIR_NOT_FOUND_CONT; obj = csch_cobj_first_explicit_locked(obj); if (obj == NULL) return csch_RTREE_DIR_NOT_FOUND_CONT; } else { locked = csch_cobj_is_locked(obj); if (!locked) score = score * 2; if (locked) { if (ctx->allow_term) { if (obj->parent->role == CSCH_ROLE_TERMINAL) { ctx->res = &obj->parent->hdr; ctx->score = score * 2; /* win over wirenet */ return csch_RTREE_DIR_FOUND_CONT; } } /* clicked on something locked, parent wants to find the first unlocked parent */ obj = csch_cobj_first_unlocked(obj); if (obj == NULL) return csch_RTREE_DIR_NOT_FOUND_CONT; } } if (obj->floater) score = score * 2; if (score > ctx->score) { ctx->res = obj; ctx->score = score; } return csch_RTREE_DIR_FOUND_CONT; } csch_chdr_t *csch_search_first_mask(csch_sheet_t *sheet, csch_rtree_box_t *query, csch_cmask_t mask) { csch_search_obj_first_t ctx = {0}; ctx.query = query; ctx.mask = mask; csch_search(sheet, query, csch_search_obj_first_cb, &ctx); return ctx.res; } csch_chdr_t *csch_search_first_gui_filter(csch_sheet_t *sheet, csch_rtree_box_t *query, csch_search_obj_ignore_cb_t ignore) { csch_search_obj_first_t ctx = {0}; ctx.query = query; ctx.ignore_wirenet_grp = 1; ctx.ignore = ignore; csch_search(sheet, query, csch_search_obj_first_cb, &ctx); return ctx.res; } csch_chdr_t *csch_search_first_gui(csch_sheet_t *sheet, csch_rtree_box_t *query) { return csch_search_first_gui_filter(sheet, query, NULL); } csch_chdr_t *csch_search_first_gui_inspect_filter(csch_sheet_t *sheet, csch_rtree_box_t *query, csch_search_obj_ignore_cb_t ignore) { csch_search_obj_first_t ctx = {0}; ctx.query = query; ctx.allow_term = 1; ctx.ignore_wirenet_grp = 1; ctx.ignore = ignore; csch_search(sheet, query, csch_search_obj_first_cb, &ctx); return ctx.res; } csch_chdr_t *csch_search_first_gui_inspect(csch_sheet_t *sheet, csch_rtree_box_t *query) { return csch_search_first_gui_inspect_filter(sheet, query, NULL); } csch_chdr_t *csch_search_first_locked(csch_sheet_t *sheet, csch_rtree_box_t *query) { csch_search_obj_first_t ctx = {0}; ctx.query = query; ctx.explicitly_locked_only = 1; csch_search(sheet, query, csch_search_obj_first_cb, &ctx); return ctx.res; } csch_chdr_t *csch_search_first_locked_gui(csch_sheet_t *sheet, csch_rtree_box_t *query) { csch_chdr_t *res = csch_search_first_locked(sheet, query); if (res != NULL) return res; return res; } long csch_search_all_selected(csch_sheet_t *sheet, csch_cgrp_t *src, vtp0_t *dst, int recursive) { htip_entry_t *e; long cnt = 0; if (src == NULL) src = &sheet->direct; for(e = htip_first(&src->id2obj); e != NULL; e = htip_next(&src->id2obj, e)) { csch_chdr_t *obj = e->value; if (obj->selected) { vtp0_append(dst, obj); cnt++; } if (csch_obj_is_grp(obj) && (recursive || !csch_grp_is_atomic(sheet, (csch_cgrp_t *)obj))) cnt += csch_search_all_selected(sheet, (csch_cgrp_t *)obj, dst, recursive); } return cnt; }