/* * COPYRIGHT * * pcb-rnd, interactive printed circuit board design * Copyright (C) 2019,2020 Tibor 'Igor2' Palinkas * * 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. * * Contact: * Project page: http://repo.hu/projects/pcb-rnd * lead developer: http://repo.hu/projects/pcb-rnd/contact.html * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") */ /* fungw type extensions for pcb-rnd-only actions (not part of the hidlib) */ #include "config.h" #include #include #include #include "board.h" #include "data.h" #include #include "layer.h" #include "layer_addr.h" #include "undo.h" #include "change.h" #include #include "conf_core.h" const char *PCB_PTR_DOMAIN_LAYER = "pcb_fgw_ptr_domain_layer"; const char *PCB_PTR_DOMAIN_LAYERGRP = "pcb_fgw_ptr_domain_layergrp"; const char *PCB_PTR_DOMAIN_VIEWLIST = "pcb_fgw_ptr_domain_viewlist"; #define conv_str2layerid(dst, src) \ do { \ rnd_layer_id_t lid = pcb_layer_str2id(PCB->Data, src); \ if (lid < 0) \ return -1; \ dst = lid; \ } while(0) static int layerid_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_LAYERID) { /* convert to layer id */ rnd_layer_id_t tmp; switch(FGW_BASE_TYPE(arg->type)) { ARG_CONV_CASE_LONG(tmp, conv_assign) ARG_CONV_CASE_LLONG(tmp, conv_assign) ARG_CONV_CASE_DOUBLE(tmp, conv_assign) ARG_CONV_CASE_LDOUBLE(tmp, conv_assign) ARG_CONV_CASE_STR(tmp, conv_str2layerid) ARG_CONV_CASE_PTR(tmp, conv_err) ARG_CONV_CASE_CLASS(tmp, conv_err) ARG_CONV_CASE_INVALID(tmp, conv_err) } arg->type = FGW_LAYERID; fgw_layerid(arg) = tmp; return 0; } if (arg->type == FGW_LAYERID) { /* convert from layer id */ rnd_layer_id_t tmp = fgw_layerid(arg); switch(target) { ARG_CONV_CASE_LONG(tmp, conv_rev_assign) ARG_CONV_CASE_LLONG(tmp, conv_rev_assign) ARG_CONV_CASE_DOUBLE(tmp, conv_rev_assign) ARG_CONV_CASE_LDOUBLE(tmp, conv_rev_assign) ARG_CONV_CASE_PTR(tmp, conv_err) ARG_CONV_CASE_CLASS(tmp, conv_err) ARG_CONV_CASE_INVALID(tmp, conv_err) case FGW_AUTO: case FGW_STR: arg->val.str = (char *)rnd_strdup_printf("#%ld", (long)tmp); arg->type = FGW_STR | FGW_DYN; return 0; } arg->type = target; return 0; } fprintf(stderr, "Neither side of the conversion is layer id\n"); abort(); } static int layer_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_LAYER) { /* convert to layer */ rnd_layer_id_t lid; if (layerid_arg_conv(ctx, arg, FGW_LAYERID) != 0) return -1; lid = fgw_layerid(arg); arg->val.ptr_void = pcb_get_layer(PCB->Data, lid); if (arg->val.ptr_void == NULL) { arg->type = FGW_INVALID; return -1; } arg->type = FGW_LAYER; return 0; } if (arg->type == FGW_LAYER) { /* convert from layer */ rnd_layer_id_t lid; pcb_layer_t *ly = arg->val.ptr_void; pcb_data_t *data; if (ly == NULL) return -1; data = ly->parent.data; lid = ly - data->Layer; if ((lid >= 0) && (lid < data->LayerN)) { arg->type = FGW_LAYERID; arg->val.nat_long = lid; if (layerid_arg_conv(ctx, arg, target) != 0) return -1; return 0; } return -1; } fprintf(stderr, "Neither side of the conversion is layer\n"); abort(); } #define conv_str2layergrpid(dst, src) \ do { \ rnd_layergrp_id_t gid = pcb_layergrp_str2id(PCB, src); \ if (gid < 0) \ return -1; \ dst = gid; \ } while(0) static int layergrpid_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_LAYERGRPID) { /* convert to layergrp id */ rnd_layergrp_id_t tmp; switch(FGW_BASE_TYPE(arg->type)) { ARG_CONV_CASE_LONG(tmp, conv_assign) ARG_CONV_CASE_LLONG(tmp, conv_assign) ARG_CONV_CASE_DOUBLE(tmp, conv_assign) ARG_CONV_CASE_LDOUBLE(tmp, conv_assign) ARG_CONV_CASE_STR(tmp, conv_str2layergrpid) ARG_CONV_CASE_PTR(tmp, conv_err) ARG_CONV_CASE_CLASS(tmp, conv_err) ARG_CONV_CASE_INVALID(tmp, conv_err) } arg->type = FGW_LAYERGRPID; fgw_layergrpid(arg) = tmp; return 0; } if (arg->type == FGW_LAYERGRPID) { /* convert from layergrp id */ rnd_layergrp_id_t tmp = fgw_layergrpid(arg); switch(target) { ARG_CONV_CASE_LONG(tmp, conv_rev_assign) ARG_CONV_CASE_LLONG(tmp, conv_rev_assign) ARG_CONV_CASE_DOUBLE(tmp, conv_rev_assign) ARG_CONV_CASE_LDOUBLE(tmp, conv_rev_assign) ARG_CONV_CASE_PTR(tmp, conv_err) ARG_CONV_CASE_CLASS(tmp, conv_err) ARG_CONV_CASE_INVALID(tmp, conv_err) case FGW_AUTO: case FGW_STR: arg->val.str = (char *)rnd_strdup_printf("#%ld", (long)tmp); arg->type = FGW_STR | FGW_DYN; return 0; } arg->type = target; return 0; } fprintf(stderr, "Neither side of the conversion is layer group id\n"); abort(); } static int layergrp_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_LAYERGRP) { /* convert to layer group */ rnd_layergrp_id_t gid; if (layergrpid_arg_conv(ctx, arg, FGW_LAYERGRPID) != 0) return -1; gid = fgw_layergrpid(arg); arg->val.ptr_void = pcb_get_layergrp(PCB, gid); if (arg->val.ptr_void == NULL) { arg->type = FGW_INVALID; return -1; } arg->type = FGW_LAYERGRP; return 0; } if (arg->type == FGW_LAYERGRP) { /* convert from layer group */ rnd_layer_id_t gid; pcb_layergrp_t *grp = arg->val.ptr_void; pcb_board_t *pcb; if (grp == NULL) return -1; pcb = grp->parent.board; gid = grp - pcb->LayerGroups.grp; if ((gid >= 0) && (gid < pcb->LayerGroups.len)) { arg->type = FGW_LAYERGRPID; arg->val.nat_long = gid; if (layergrpid_arg_conv(ctx, arg, target) != 0) return -1; return 0; } return -1; } fprintf(stderr, "Neither side of the conversion is layer group\n"); abort(); } static int data_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_DATA) { /* convert to data */ if (FGW_BASE_TYPE(arg->type) == FGW_STR) { const char *str = arg->val.str; pcb_data_t *data = pcb_data_by_name(PCB, &str); if (data != NULL) { arg->val.ptr_void = data; arg->type = FGW_DATA; return 0; } } if (FGW_BASE_TYPE(arg->type) == (FGW_PTR | FGW_STRUCT)) { TODO("Dangerous: rather support subc's data with IDPATH"); arg->val.ptr_void = arg->val.ptr_void; arg->type = FGW_DATA; return 0; } arg->type = FGW_INVALID; return -1; } if (arg->type == FGW_DATA) { /* convert from data */ char buf[32]; const char *name = pcb_data_to_name(PCB, arg->val.ptr_void, buf, sizeof(buf)); if (name != NULL) { if (name == buf) { arg->val.str = rnd_strdup(name); arg->type = FGW_STR | FGW_DYN; } else { /* static string */ arg->val.cstr = name; arg->type = FGW_STR; } return 0; } TODO("Dangerous: rather support subc's data with IDPATH"); arg->type = FGW_PTR | FGW_DYN; return 0; } fprintf(stderr, "Neither side of the conversion is data\n"); abort(); } #define conv_struct_from_str(str, DOMAIN, TYPE) \ if ((str[0] == '0') && (str[1] == 'x')) { \ fgw_arg_conv(&rnd_fgw, arg, FGW_PTR); \ if (fgw_ptr_in_domain(&rnd_fgw, arg, DOMAIN)) { \ arg->type = TYPE | FGW_PTR; \ return 0; \ } \ arg->type = FGW_INVALID; \ return -1; \ } static int idpath_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) { if (target == FGW_IDPATH) { /* convert to idpath */ if (FGW_BASE_TYPE(arg->type) == FGW_STR) { const char *str = arg->val.str; pcb_idpath_t *idp; conv_struct_from_str(str, RND_PTR_DOMAIN_IDPATH, FGW_IDPATH); idp = pcb_str2idpath(PCB, str); if (idp != NULL) { fgw_ptr_reg(&rnd_fgw, arg, RND_PTR_DOMAIN_IDPATH, FGW_IDPATH, idp); return 0; } } if (FGW_BASE_TYPE(arg->type) == (FGW_PTR | FGW_STRUCT) && fgw_ptr_in_domain(&rnd_fgw, arg, RND_PTR_DOMAIN_IDPATH)) return 0; arg->type = FGW_INVALID; return -1; } if (arg->type == FGW_IDPATH) { /* convert from idpath */ if (fgw_ptr_in_domain(&rnd_fgw, arg, RND_PTR_DOMAIN_IDPATH)) { char *name = pcb_idpath2str(arg->val.ptr_void, 0); if (name != NULL) { arg->val.str = name; arg->type = FGW_STR | FGW_DYN; } return 0; } return -1; } fprintf(stderr, "Neither side of the conversion is idpath\n"); abort(); } void pcb_actions_init_pcb_only(void) { if (fgw_reg_custom_type(&rnd_fgw, FGW_LAYERID, "layerid", layerid_arg_conv, NULL) != FGW_LAYERID) { fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYERID\n"); abort(); } if (fgw_reg_custom_type(&rnd_fgw, FGW_LAYER, "layer", layer_arg_conv, NULL) != FGW_LAYER) { fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYER\n"); abort(); } if (fgw_reg_custom_type(&rnd_fgw, FGW_LAYERGRPID, "layergrpid", layergrpid_arg_conv, NULL) != FGW_LAYERGRPID) { fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYERGRPID\n"); abort(); } if (fgw_reg_custom_type(&rnd_fgw, FGW_LAYERGRP, "layergrp", layergrp_arg_conv, NULL) != FGW_LAYERGRP) { fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYERGRP\n"); abort(); } if (fgw_reg_custom_type(&rnd_fgw, FGW_DATA, "data", data_arg_conv, NULL) != FGW_DATA) { fprintf(stderr, "pcb_actions_init: failed to register FGW_DATA\n"); abort(); } if (fgw_reg_custom_type(&rnd_fgw, FGW_IDPATH, "idpath", idpath_arg_conv, NULL) != FGW_IDPATH) { fprintf(stderr, "pcb_actions_init: failed to register FGW_IDPATH\n"); abort(); } } int pcb_act_execute_file(rnd_design_t *hidlib, const char *fn) { int res; defer_updates = 1; defer_needs_update = 0; res = rnd_act_execute_file(hidlib, fn); defer_updates = 0; if (defer_needs_update) { pcb_undo_inc_serial(); rnd_gui->invalidate_all(rnd_gui); } return res; }