Index: trunk/src_plugins/propedit/propedit.c =================================================================== --- trunk/src_plugins/propedit/propedit.c (revision 37264) +++ trunk/src_plugins/propedit/propedit.c (revision 37265) @@ -176,7 +176,7 @@ extern rnd_layergrp_id_t pcb_actd_EditGroup_gid; static const char pcb_acts_propset[] = "propset([scope], name, value)"; -static const char pcb_acth_propset[] = "Change the named property of scope or all selected objects to/by value. Scope is documented at PropEdit()."; +static const char pcb_acth_propset[] = "Change the named property of scope or all selected objects to/by value. Scope is documented at PropEdit(). Existing attributes can be renamed to value by using a name rename/a/old_name, where old_name is the current name of the attribute."; fgw_error_t pcb_act_propset(fgw_arg_t *res, int argc, fgw_arg_t *argv) { const char *first, *name, *val; Index: trunk/src_plugins/propedit/propsel.c =================================================================== --- trunk/src_plugins/propedit/propsel.c (revision 37264) +++ trunk/src_plugins/propedit/propsel.c (revision 37265) @@ -457,10 +457,17 @@ } orig = pcb_attribute_get(list, key); - if ((orig != NULL) && (strcmp(orig, st->s) == 0)) - return; - - pcb_attribute_put(list, key, st->s); + if (st->arename) { + if (strcmp(st->s, key) == 0) + return; + pcb_attribute_put(list, st->s, orig); + pcb_attribute_remove(list, key); + } + else { + if ((orig != NULL) && (strcmp(orig, st->s) == 0)) + return; + pcb_attribute_put(list, key, st->s); + } st->set_cnt++; } @@ -469,6 +476,9 @@ const char *key = st->name+2; int side_effect, res; + if (st->arename && (strcmp(st->s, key) == 0)) + return; + if (st->toggle) { toggle_attr(st, &obj->Attributes, 1, obj); return; @@ -478,7 +488,20 @@ if (side_effect) pcb_obj_pre(obj); - res = pcb_uchg_attr(st->pcb, obj, key, st->s); + + if (st->arename) { + const char *orig = pcb_attribute_get(&obj->Attributes, key); + if (orig != NULL) { + res = pcb_uchg_attr(st->pcb, obj, st->s, orig); + if (res == 0) + res = pcb_uchg_attr(st->pcb, obj, key, NULL); + } + else + res = -1; + } + else + res = pcb_uchg_attr(st->pcb, obj, key, st->s); + if (side_effect) { pcb_obj_update_bbox(st->pcb, obj); pcb_obj_post(obj); @@ -1086,10 +1109,15 @@ int pcb_propsel_set_str(pcb_propedit_t *ctx, const char *prop, const char *value) { - pcb_propset_ctx_t sctx; + pcb_propset_ctx_t sctx = {0}; char *end; const char *start; + if ((prop[0] == 'r') && (strncmp(prop, "rename/a/", 9)) == 0) { + sctx.arename = 1; + prop += 7; + } + /* sanity checks for invalid props */ if ((prop[1] != '/') || ((prop[0] != 'a') && (prop[0] != 'p'))) { rnd_message(RND_MSG_ERROR, "Invalid property path: '%s':\n must start with p/ for property or a/ for attribute\n", prop); @@ -1096,8 +1124,6 @@ return 0; } - memset(&sctx, 0, sizeof(sctx)); - if (value == NULL) value = ""; sctx.s = value; Index: trunk/src_plugins/propedit/propsel.h =================================================================== --- trunk/src_plugins/propedit/propsel.h (revision 37264) +++ trunk/src_plugins/propedit/propsel.h (revision 37265) @@ -35,6 +35,7 @@ rnd_bool c_absolute, d_absolute, c_valid, d_valid, clr_valid; unsigned toggle:1; /* when 1, ignore value and attempt to toggle */ unsigned toggle_create:1; /* when 1, create non-existing attribute on toggle, with value true */ + unsigned arename:1; /* when 1, attribute is renamed to s; must not be used for anything else but a/ */ /* private */ unsigned is_trace:1;