Index: propedit.c =================================================================== --- propedit.c (revision 31101) +++ propedit.c (revision 31102) @@ -201,6 +201,31 @@ return 0; } +static const char pcb_acts_proptoggle[] = "proptoggle([scope], name, value)"; +static const char pcb_acth_proptoggle[] = "Toggle the named property of scope or all selected objects, assuming the property is boolean. Scope is documented at PropEdit()."; +fgw_error_t pcb_act_proptoggle(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *first, *name; + pcb_propedit_t ctx; + + pcb_props_init(&ctx, PCB); + + RND_ACT_CONVARG(1, FGW_STR, propset, first = argv[1].val.str); + if (prop_scope_add(&ctx, first, 1) == 0) { + RND_ACT_CONVARG(2, FGW_STR, propset, name = argv[2].val.str); + } + else { + name = first; + ctx.selection = 1; + } + + RND_ACT_IRES(pcb_propsel_toggle(&ctx, name)); + + prop_scope_finish(&ctx); + pcb_props_uninit(&ctx); + return 0; +} + static const char pcb_acts_propget[] = "propget([scope], name, [stattype])"; static const char pcb_acth_propget[] = "Return the named property of scope or all selected objects to/by value. Scope is documented at PropEdit()."; fgw_error_t pcb_act_propget(fgw_arg_t *res, int argc, fgw_arg_t *argv) @@ -339,6 +364,7 @@ {"propedit", pcb_act_propedit, pcb_acth_propedit, pcb_acts_propedit}, {"propprint", pcb_act_propprint, pcb_acth_propprint, pcb_acts_propprint}, {"propset", pcb_act_propset, pcb_acth_propset, pcb_acts_propset}, + {"proptoggle", pcb_act_proptoggle, pcb_acth_proptoggle, pcb_acts_proptoggle}, {"propget", pcb_act_propget, pcb_acth_propget, pcb_acts_propget} }; Index: propsel.c =================================================================== --- propsel.c (revision 31101) +++ propsel.c (revision 31102) @@ -355,6 +355,20 @@ const char *key = st->name+2; const char *orig = rnd_attribute_get(list, key); + if (st->toggle) { + if (orig == NULL) /* do not create non-existing attributes */ + return; + if (rnd_istrue(orig)) { + rnd_attribute_put(list, key, "false"); + st->set_cnt++; + } + else if (rnd_isfalse(orig)) { + rnd_attribute_put(list, key, "true"); + st->set_cnt++; + } + return; + } + if ((orig != NULL) && (strcmp(orig, st->s) == 0)) return; @@ -366,6 +380,11 @@ { const char *key = st->name+2; + if (st->toggle) { + set_attr_raw(st, &obj->Attributes); + return; + } + if (pcb_uchg_attr(st->pcb, obj, key, st->s) != 0) return; @@ -383,7 +402,11 @@ if (i != NULL) { if (i->mask & PCB_FLAG_CLEARLINE) pcb_obj_pre(obj); - pcb_flag_change(st->pcb, st->c ? PCB_CHGFLG_SET : PCB_CHGFLG_CLEAR, i->mask, obj->type, obj->parent.any, obj, obj); + + if (st->toggle) + pcb_flag_change(st->pcb, PCB_CHGFLG_TOGGLE, i->mask, obj->type, obj->parent.any, obj, obj); + else + pcb_flag_change(st->pcb, st->c ? PCB_CHGFLG_SET : PCB_CHGFLG_CLEAR, i->mask, obj->type, obj->parent.any, obj, obj); if (i->mask & PCB_FLAG_CLEARLINE) pcb_obj_post(obj); DONE1; @@ -407,6 +430,9 @@ return; } + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/board/", 8) == 0) { if ((strcmp(pn, "name") == 0) && (pcb_board_change_name(rnd_strdup(st->s)))) DONE; @@ -442,6 +468,9 @@ return 0; } + if (st->toggle) + return 0; /* can't toggle anything else */ + if (strncmp(st->name, "p/layer/", 8) == 0) { if ((strcmp(pn, "name") == 0) && (pcb_layer_rename_(layer, rnd_strdup(st->s), 1) == 0)) DONE0; @@ -463,6 +492,9 @@ return; } + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/layer_group/", 14) == 0) { if ((strcmp(pn, "name") == 0) && (pcb_layergrp_rename_(grp, rnd_strdup(st->s), 1) == 0)) DONE; @@ -478,6 +510,9 @@ if (net == NULL) return; + if (st->toggle) + return; /* can't toggle anything else */ + if (st->is_attr) { const char *key = st->name+2; const char *orig = rnd_attribute_get(&net->Attributes, key); @@ -502,6 +537,9 @@ if (set_common(st, (pcb_any_obj_t *)line)) return; + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/trace/", 8) == 0) { if (st->is_trace && st->c_valid && (strcmp(pn, "thickness") == 0) && pcb_chg_obj_1st_size(PCB_OBJ_LINE, line->parent.layer, line, NULL, st->c, st->c_absolute)) DONE; @@ -553,6 +591,9 @@ if (set_common(st, (pcb_any_obj_t *)arc)) return; + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/trace/", 8) == 0) { if (st->is_trace && st->c_valid && (strcmp(pn, "thickness") == 0) && pcb_chg_obj_1st_size(PCB_OBJ_ARC, arc->parent.layer, arc, NULL, st->c, st->c_absolute)) DONE; @@ -607,6 +648,8 @@ if (set_common(st, (pcb_any_obj_t *)gfx)) return; + if (st->toggle) + return; /* can't toggle anything else */ if (strncmp(st->name, "p/gfx/", 6) == 0) { if (st->c_valid && (strcmp(pn, "sx") == 0)) { @@ -633,6 +676,9 @@ if (set_common(st, (pcb_any_obj_t *)text)) return; + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/text/", 7) == 0) { pcb_opctx_t op; @@ -677,8 +723,16 @@ { const char *pn = st->name + 8; + if (st->is_attr) { + set_attr_obj(st, (pcb_any_obj_t *)poly); + return; + } + if (set_common(st, (pcb_any_obj_t *)poly)) return; + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/trace/", 8) == 0) { if (st->is_trace && st->c_valid && (strcmp(pn, "clearance") == 0) && pcb_chg_obj_clear_size(PCB_OBJ_POLY, poly->parent.layer, poly, NULL, st->c*2, st->c_absolute)) DONE; @@ -685,11 +739,6 @@ if (st->is_trace && st->c_valid && (strcmp(pn, "enforce_clearance") == 0) && pcb_chg_obj_enforce_clear_size(PCB_OBJ_POLY, poly->parent.layer, poly, NULL, st->c, st->c_absolute)) DONE; } - - if (st->is_attr) { - set_attr_obj(st, (pcb_any_obj_t *)poly); - return; - } } static void set_pstk(pcb_propset_ctx_t *st, pcb_pstk_t *ps) @@ -706,6 +755,9 @@ if (set_common(st, (pcb_any_obj_t *)ps)) return; + if (st->toggle) + return; /* can't toggle anything else */ + ca = st->c; i = (st->c != 0); proto = pcb_pstk_get_proto(ps); @@ -793,6 +845,9 @@ return; } + if (st->toggle) + return; /* can't toggle anything else */ + if (strncmp(st->name, "p/subcircuit/", 13) == 0) { pcb_opctx_t op; rnd_coord_t x = 0, y = 0; @@ -898,6 +953,8 @@ if ((prop[0] != 'a') && (prop[0] != 'p')) return 0; + memset(&sctx, 0, sizeof(sctx)); + if (value == NULL) value = ""; sctx.s = value; @@ -909,6 +966,7 @@ } else sctx.d_absolute = ((*start != '-') && (*start != '+')); + sctx.toggle = 0; sctx.c = rnd_get_value_ex(start, NULL, &sctx.c_absolute, NULL, NULL, &sctx.c_valid); sctx.d = strtod(start, &end); sctx.d_valid = (*end == '\0'); @@ -917,6 +975,24 @@ return pcb_propsel_set(ctx, prop, &sctx); } +int pcb_propsel_toggle(pcb_propedit_t *ctx, const char *prop) +{ + pcb_propset_ctx_t sctx; + + /* sanity checks for invalid props */ + if (prop[1] != '/') + return 0; + if ((prop[0] != 'a') && (prop[0] != 'p')) + return 0; + + memset(&sctx, 0, sizeof(sctx)); + + sctx.toggle = 1; + sctx.set_cnt = 0; + + return pcb_propsel_set(ctx, prop, &sctx); +} + /*******************/ static long del_attr(void *ctx, rnd_attribute_list_t *list, const char *key) Index: propsel.h =================================================================== --- propsel.h (revision 31101) +++ propsel.h (revision 31102) @@ -33,6 +33,7 @@ double d; rnd_color_t color; rnd_bool c_absolute, d_absolute, c_valid, d_valid, clr_valid; + unsigned toggle:1; /* when 1, ignore value and attempt to toggle */ /* private */ unsigned is_trace:1; @@ -46,6 +47,7 @@ int pcb_propsel_set_str(pcb_propedit_t *ctx, const char *prop, const char *value); int pcb_propsel_set(pcb_propedit_t *ctx, const char *prop, pcb_propset_ctx_t *sctx); +int pcb_propsel_toggle(pcb_propedit_t *ctx, const char *prop); int pcb_propsel_del(pcb_propedit_t *ctx, const char *attr_name); /* Allocate new string and print the value using current unit */