Index: trunk/src/netlist.c =================================================================== --- trunk/src/netlist.c (revision 29117) +++ trunk/src/netlist.c (revision 29118) @@ -951,7 +951,7 @@ new_len = pcb_termlist_length(&target_net->conns); if (new_len != old_len) { id = pcb_concat(sc1->refdes, "-", o1->term, NULL); - pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL); + pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL, 1); free(id); } @@ -960,7 +960,7 @@ new_len = pcb_termlist_length(&target_net->conns); if (new_len != old_len) { id = pcb_concat(sc2->refdes, "-", o2->term, NULL); - pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL); + pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL, 1); free(id); } Index: trunk/src/rats_patch.c =================================================================== --- trunk/src/rats_patch.c (revision 29117) +++ trunk/src/rats_patch.c (revision 29118) @@ -48,7 +48,17 @@ "edited" }; -void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2) +/*** undoable ratspatch append */ + +typedef struct { + pcb_board_t *pcb; + pcb_rats_patch_op_t op; + char *id; + char *a1; + char *a2; +} pcb_ratspatch_append_t; + +static void pcb_ratspatch_append_(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2) { pcb_ratspatch_line_t *n; @@ -73,6 +83,11 @@ n->next = NULL; } +void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2, int undoable) +{ + pcb_ratspatch_append_(pcb, op, id, a1, a2); +} + static void rats_patch_free_fields(pcb_ratspatch_line_t *n) { if (n->id != NULL) @@ -131,7 +146,7 @@ } quit:; - pcb_ratspatch_append(pcb, op, id, a1, a2); + pcb_ratspatch_append(pcb, op, id, a1, a2, 0); } /* Unlink n from the list; if do_free is non-zero, also free fields and n */ Index: trunk/src/rats_patch.h =================================================================== --- trunk/src/rats_patch.h (revision 29117) +++ trunk/src/rats_patch.h (revision 29118) @@ -56,7 +56,7 @@ const char *pcb_netlist_names[PCB_NUM_NETLISTS]; /* Allocate and append a patch line to the patch list */ -void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2); +void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2, int undoable); /* Free the patch list and all memory claimed by patch list items */ void pcb_ratspatch_destroy(pcb_board_t *pcb); Index: trunk/src_plugins/io_lihata/read.c =================================================================== --- trunk/src_plugins/io_lihata/read.c (revision 29117) +++ trunk/src_plugins/io_lihata/read.c (revision 29118) @@ -2175,13 +2175,13 @@ nval = lht_dom_hash_get(np, "term"); if ((nval == NULL) || (nval->type != LHT_TEXT) || (*nval->data.text.value == '\0')) return iolht_error(nval, "netlist patch terminal ID must be a non-empty string (del_conn)\n"); - pcb_ratspatch_append(pcb, RATP_DEL_CONN, nval->data.text.value, nnet->data.text.value, NULL); + pcb_ratspatch_append(pcb, RATP_DEL_CONN, nval->data.text.value, nnet->data.text.value, NULL, 0); } else if (strcmp(np->name, "add_conn") == 0) { nval = lht_dom_hash_get(np, "term"); if ((nval == NULL) || (nval->type != LHT_TEXT) || (*nval->data.text.value == '\0')) return iolht_error(nval, "netlist patch terminal ID must be a non-empty string (add_conn)\n"); - pcb_ratspatch_append(pcb, RATP_ADD_CONN, nval->data.text.value, nnet->data.text.value, NULL); + pcb_ratspatch_append(pcb, RATP_ADD_CONN, nval->data.text.value, nnet->data.text.value, NULL, 0); } else if (strcmp(np->name, "change_attrib") == 0) { nkey = lht_dom_hash_get(np, "key"); @@ -2190,7 +2190,7 @@ nval = lht_dom_hash_get(np, "val"); if ((nval == NULL) || (nval->type != LHT_TEXT)) return iolht_error(nval, "netlist patch attrib value must be a non-empty string (change_attrib)\n"); - pcb_ratspatch_append(pcb, RATP_CHANGE_ATTRIB, nnet->data.text.value, nkey->data.text.value, nval->data.text.value); + pcb_ratspatch_append(pcb, RATP_CHANGE_ATTRIB, nnet->data.text.value, nkey->data.text.value, nval->data.text.value, 0); } } return 0; Index: trunk/src_plugins/io_pcb/parse_y.c =================================================================== --- trunk/src_plugins/io_pcb/parse_y.c (revision 29117) +++ trunk/src_plugins/io_pcb/parse_y.c (revision 29118) @@ -2910,19 +2910,19 @@ case 197: #line 1315 "parse_y.y" /* yacc.c:1652 */ - { pcb_ratspatch_append(yyPCB, RATP_ADD_CONN, (yyvsp[-2].string), (yyvsp[-1].string), NULL); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } + { pcb_ratspatch_append(yyPCB, RATP_ADD_CONN, (yyvsp[-2].string), (yyvsp[-1].string), NULL, 0); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } #line 2915 "parse_y.c" /* yacc.c:1652 */ break; case 198: #line 1316 "parse_y.y" /* yacc.c:1652 */ - { pcb_ratspatch_append(yyPCB, RATP_DEL_CONN, (yyvsp[-2].string), (yyvsp[-1].string), NULL); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } + { pcb_ratspatch_append(yyPCB, RATP_DEL_CONN, (yyvsp[-2].string), (yyvsp[-1].string), NULL, 0); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } #line 2921 "parse_y.c" /* yacc.c:1652 */ break; case 199: #line 1317 "parse_y.y" /* yacc.c:1652 */ - { pcb_ratspatch_append(yyPCB, RATP_CHANGE_ATTRIB, (yyvsp[-3].string), (yyvsp[-2].string), (yyvsp[-1].string)); free((yyvsp[-3].string)); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } + { pcb_ratspatch_append(yyPCB, RATP_CHANGE_ATTRIB, (yyvsp[-3].string), (yyvsp[-2].string), (yyvsp[-1].string), 0); free((yyvsp[-3].string)); free((yyvsp[-2].string)); free((yyvsp[-1].string)); } #line 2927 "parse_y.c" /* yacc.c:1652 */ break; Index: trunk/src_plugins/io_pcb/parse_y.y =================================================================== --- trunk/src_plugins/io_pcb/parse_y.y (revision 29117) +++ trunk/src_plugins/io_pcb/parse_y.y (revision 29118) @@ -1312,9 +1312,9 @@ netpatch /* name style pin pin ... */ - : T_ADD_CONN '(' STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_ADD_CONN, $3, $4, NULL); free($3); free($4); } - | T_DEL_CONN '(' STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_DEL_CONN, $3, $4, NULL); free($3); free($4); } - | T_CHANGE_ATTRIB '(' STRING STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_CHANGE_ATTRIB, $3, $4, $5); free($3); free($4); free($5); } + : T_ADD_CONN '(' STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_ADD_CONN, $3, $4, NULL, 0); free($3); free($4); } + | T_DEL_CONN '(' STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_DEL_CONN, $3, $4, NULL, 0); free($3); free($4); } + | T_CHANGE_ATTRIB '(' STRING STRING STRING ')' { pcb_ratspatch_append(yyPCB, RATP_CHANGE_ATTRIB, $3, $4, $5, 0); free($3); free($4); free($5); } ; attribute