diff --git a/README b/README index b042b20..45697a9 100644 --- a/README +++ b/README @@ -403,4 +403,5 @@ make the changes in the input area at the bottom. To delete an object, select it and press Delete. Deleted objects can be undeleted by pressing "u". If any other changes have been made -since deletion, fped may misbehave. +since deletion, fped may misbehave. If deleting a vector, all items +that reference it are deleted. diff --git a/delete.c b/delete.c index 92205f4..f114c93 100644 --- a/delete.c +++ b/delete.c @@ -41,9 +41,16 @@ static struct deletion { struct obj *prev; } obj; } u; + int group; struct deletion *next; } *deletions = NULL; +static int groups = 0; + + +static void do_delete_vec(struct vec *vec); +static void do_delete_obj(struct obj *obj); + static struct deletion *new_deletion(enum del_type type) { @@ -51,6 +58,7 @@ static struct deletion *new_deletion(enum del_type type) del = alloc_type(struct deletion); del->type = type; + del->group = groups; del->next = deletions; deletions = del; return del; @@ -60,38 +68,64 @@ static struct deletion *new_deletion(enum del_type type) /* ----- vectors ----------------------------------------------------------- */ -static void dereference_vec(struct vec *vec) -{ - assert(!vec->n_refs); - put_vec(vec->base); -} - - static void destroy_vec(struct vec *vec) { - assert(!vec->n_refs); free_expr(vec->x); free_expr(vec->y); free(vec); } -static void rereference_vec(struct vec *vec) +static void delete_vecs_by_ref(struct vec *vecs, const struct vec *ref) { - get_vec(vec->base); + while (vecs) { + if (vecs->base == ref) + do_delete_vec(vecs); + vecs = vecs->next; + } } -void delete_vec(struct vec *vec) +static int obj_has_ref(const struct obj *obj, const struct vec *ref) +{ + if (obj->base == ref) + return 1; + switch (obj->type) { + case ot_frame: + return 0; + case ot_line: + return obj->u.line.other == ref; + case ot_rect: + return obj->u.rect.other == ref; + case ot_pad: + return obj->u.pad.other == ref; + case ot_arc: + return obj->u.arc.start == ref || obj->u.arc.end == ref; + case ot_meas: + default: + abort(); + } +} + + +static void delete_objs_by_ref(struct obj **objs, const struct vec *ref) +{ + struct obj *obj; + + for (obj = *objs; obj; obj = obj->next) + if (obj_has_ref(obj, ref)) + do_delete_obj(obj); +} + + +static void do_delete_vec(struct vec *vec) { struct vec *walk, *prev; struct deletion *del; - if (vec->n_refs) { - fail("vector has %d reference%s", vec->n_refs, - vec->n_refs == 1 ? "" : "s"); - return; - } + delete_vecs_by_ref(vec->frame->vecs, vec); + delete_objs_by_ref(&vec->frame->objs, vec); + prev = NULL; for (walk = vec->frame->vecs; walk != vec; walk = walk->next) prev = walk; @@ -99,13 +133,19 @@ void delete_vec(struct vec *vec) prev->next = vec->next; else vec->frame->vecs = vec->next; - dereference_vec(vec); del = new_deletion(dt_vec); del->u.vec.ref = vec; del->u.vec.prev = prev; } +void delete_vec(struct vec *vec) +{ + groups++; + do_delete_vec(vec); +} + + static void undelete_vec(struct vec *vec, struct vec *prev) { if (prev) { @@ -115,42 +155,12 @@ static void undelete_vec(struct vec *vec, struct vec *prev) assert(vec->next == vec->frame->vecs); vec->frame->vecs = vec; } - rereference_vec(vec); } /* ----- objects ----------------------------------------------------------- */ -static void dereference_obj(struct obj *obj) -{ - switch (obj->type) { - case ot_frame: - /* nothing */ - break; - case ot_pad: - put_vec(obj->u.pad.other); - break; - case ot_line: - put_vec(obj->u.line.other); - break; - case ot_rect: - put_vec(obj->u.rect.other); - break; - case ot_arc: - put_vec(obj->u.arc.start); - put_vec(obj->u.arc.end); - break; - case ot_meas: - put_vec(obj->u.meas.other); - break; - default: - abort(); - } - put_vec(obj->base); -} - - static void destroy_obj(struct obj *obj) { switch (obj->type) { @@ -179,36 +189,7 @@ static void destroy_obj(struct obj *obj) } -static void rereference_obj(struct obj *obj) -{ - switch (obj->type) { - case ot_frame: - /* nothing */ - break; - case ot_pad: - get_vec(obj->u.pad.other); - break; - case ot_line: - get_vec(obj->u.line.other); - break; - case ot_rect: - get_vec(obj->u.rect.other); - break; - case ot_arc: - get_vec(obj->u.arc.start); - get_vec(obj->u.arc.end); - break; - case ot_meas: - get_vec(obj->u.meas.other); - break; - default: - abort(); - } - get_vec(obj->base); -} - - -void delete_obj(struct obj *obj) +static void do_delete_obj(struct obj *obj) { struct obj *walk, *prev; struct deletion *del; @@ -220,13 +201,19 @@ void delete_obj(struct obj *obj) prev->next = obj->next; else obj->frame->objs = obj->next; - dereference_obj(obj); del = new_deletion(dt_obj); del->u.obj.ref = obj; del->u.obj.prev = prev; } +void delete_obj(struct obj *obj) +{ + groups++; + do_delete_obj(obj); +} + + static void undelete_obj(struct obj *obj, struct obj *prev) { if (prev) { @@ -236,7 +223,6 @@ static void undelete_obj(struct obj *obj, struct obj *prev) assert(obj->next == obj->frame->objs); obj->frame->objs = obj; } - rereference_obj(obj); } @@ -260,6 +246,7 @@ void delete_frame(struct frame *frame) { struct deletion *del; + groups++; delete_references(frame); del = new_deletion(dt_frame); @@ -318,7 +305,7 @@ int destroy(void) } -int undelete(void) +static int undelete_one(void) { struct deletion *del; @@ -342,3 +329,16 @@ int undelete(void) free(del); return 1; } + + +int undelete(void) +{ + int group; + + if (!deletions) + return 0; + group = deletions->group; + while (deletions && deletions->group == group) + undelete_one(); + return 1; +} diff --git a/dump.c b/dump.c index 9e8195d..93496e8 100644 --- a/dump.c +++ b/dump.c @@ -114,8 +114,6 @@ static int n_vec_refs(const struct vec *vec) const struct vec *walk; int n; - if (!vec->n_refs) - return 0; n = 0; for (walk = vec->frame->vecs; walk; walk = walk->next) if (walk->base == vec) diff --git a/fpd.y b/fpd.y index cdc2338..9654955 100644 --- a/fpd.y +++ b/fpd.y @@ -345,7 +345,6 @@ vec: $$->base = $2; $$->x = $4; $$->y = $6; - $$->n_refs = 0; $$->frame = curr_frame; $$->next = NULL; last_vec = $$; @@ -366,7 +365,6 @@ base: yyerrorf(". without predecessor"); YYABORT; } - $$->n_refs++; } | ID { @@ -375,7 +373,6 @@ base: yyerrorf("unknown vector \"%s\"", $1); YYABORT; } - $$->n_refs++; } ; @@ -406,7 +403,7 @@ obj: $$ = new_obj(ot_arc); $$->base = $2; $$->u.arc.start = $3; - $$->u.arc.end = get_vec($3); + $$->u.arc.end = $3; $$->u.arc.width = $4; } | TOK_ARC base base base opt_expr diff --git a/fped.c b/fped.c index d1cd9f7..b9e20b1 100644 --- a/fped.c +++ b/fped.c @@ -54,7 +54,7 @@ int main(int argc, char **argv) if (error) return error; -// dump(stdout); + dump(stdout); return 0; } diff --git a/gui_tools.c b/gui_tools.c index 44bd964..d175e26 100644 --- a/gui_tools.c +++ b/gui_tools.c @@ -80,8 +80,7 @@ static struct vec *new_vec(struct inst *base) vec = alloc_type(struct vec); vec->name = NULL; - vec->base = inst_get_ref(base); - vec->n_refs = 0; + vec->base = inst_get_vec(base); vec->next = NULL; vec->frame = active_frame; for (walk = &active_frame->vecs; *walk; walk = &(*walk)->next); @@ -97,7 +96,7 @@ static struct obj *new_obj(enum obj_type type, struct inst *base) obj = alloc_type(struct obj); obj->type = type; obj->frame = active_frame; - obj->base = inst_get_ref(base); + obj->base = inst_get_vec(base); obj->next = NULL; obj->lineno = 0; for (walk = &active_frame->objs; *walk; walk = &(*walk)->next); @@ -164,10 +163,20 @@ static struct pix_buf *draw_move_rect_common(struct inst *inst, /* ----- vec --------------------------------------------------------------- */ -static void gridify(struct coord base, struct coord *pos) +static struct coord gridify(struct coord base, struct coord pos) { - pos->x -= fmod(pos->x-base.x, mm_to_units(0.1)); - pos->y -= fmod(pos->y-base.y, mm_to_units(0.1)); + struct coord new; + unit_type unit = mm_to_units(0.1); + + new.x = pos.x-(pos.x-base.x % unit); + new.y = pos.y-(pos.y-base.y % unit); + if (new.x != base.x || new.y != base.y) + return new; + if (fabs(pos.x-base.x) > fabs(pos.y-base.y)) + new.x += pos.x > base.x ? unit : -unit; + else + new.y += pos.y > base.y ? unit : -unit; + return new; } @@ -178,7 +187,7 @@ static struct pix_buf *drag_new_vec(struct draw_ctx *ctx, struct pix_buf *buf; pos = inst_get_point(from); - gridify(pos, &to); + to = gridify(pos, to); status_set_type_x("dX ="); status_set_type_y("dX ="); status_set_x("%lg mm", units_to_mm(to.x-pos.x)); @@ -207,7 +216,7 @@ static int end_new_raw_vec(struct draw_ctx *ctx, vec = new_vec(from); pos = inst_get_point(from); - gridify(pos, &to); + to = gridify(pos, to); vec->x = new_num(make_mm(units_to_mm(to.x-pos.x))); vec->y = new_num(make_mm(units_to_mm(to.y-pos.y))); return 1; @@ -252,7 +261,7 @@ static int end_new_line(struct draw_ctx *ctx, if (from == to) return 0; obj = new_obj(ot_line, from); - obj->u.line.other = inst_get_ref(to); + obj->u.line.other = inst_get_vec(to); obj->u.line.width = NULL; return 1; } @@ -298,7 +307,7 @@ static int end_new_rect(struct draw_ctx *ctx, if (from == to) return 0; obj = new_obj(ot_rect, from); - obj->u.rect.other = inst_get_ref(to); + obj->u.rect.other = inst_get_vec(to); obj->u.rect.width = NULL; return 1; } @@ -321,7 +330,7 @@ static int end_new_pad(struct draw_ctx *ctx, if (from == to) return 0; obj = new_obj(ot_pad, from); - obj->u.pad.other = inst_get_ref(to); + obj->u.pad.other = inst_get_vec(to); obj->u.pad.name = stralloc("?"); return 1; } @@ -367,8 +376,8 @@ static int end_new_circ(struct draw_ctx *ctx, if (from == to) return 0; obj = new_obj(ot_arc, from); - obj->u.arc.start = inst_get_ref(to); - obj->u.arc.end = inst_get_ref(to); + obj->u.arc.start = inst_get_vec(to); + obj->u.arc.end = inst_get_vec(to); obj->u.arc.width = NULL; return 1; } @@ -417,16 +426,6 @@ struct pix_buf *draw_move_arc(struct inst *inst, struct draw_ctx *ctx, } -static void replace(struct vec **anchor, struct vec *new) -{ - if (*anchor) - (*anchor)->n_refs--; - *anchor = new; - if (new) - new->n_refs++; -} - - void do_move_to_arc(struct inst *inst, struct vec *vec, int i) { struct obj *obj = inst->obj; @@ -435,15 +434,15 @@ void do_move_to_arc(struct inst *inst, struct vec *vec, int i) is_circle = obj->u.arc.start == obj->u.arc.end; switch (i) { case 0: - replace(&obj->base, vec); + obj->base = vec; break; case 1: - replace(&obj->u.arc.start, vec); + obj->u.arc.start = vec; if (!is_circle) break; /* fall through */ case 2: - replace(&obj->u.arc.end, vec); + obj->u.arc.end = vec; break; default: abort(); @@ -475,7 +474,7 @@ static int end_new_meas(struct draw_ctx *ctx, if (from == to) return 0; obj = new_obj(ot_meas, from); - obj->u.meas.other = inst_get_ref(to); + obj->u.meas.other = inst_get_vec(to); obj->u.meas.offset = parse_expr("0mm"); return 1; } @@ -643,13 +642,8 @@ static int may_move_to(const struct drag_state *state, struct inst *curr) static void do_move_to(struct drag_state *state, struct inst *curr) { - struct vec *old; - assert(may_move_to(state, curr)); - old = *state->anchors[state->anchor_i]; - if (old) - old->n_refs--; - *state->anchors[state->anchor_i] = inst_get_ref(curr); + *state->anchors[state->anchor_i] = inst_get_vec(curr); } diff --git a/inst.c b/inst.c index b36ccb2..86fe4bc 100644 --- a/inst.c +++ b/inst.c @@ -219,18 +219,6 @@ struct coord inst_get_point(const struct inst *inst) } -struct vec *inst_get_ref(const struct inst *inst) -{ - if (inst->ops == &vec_ops) { - inst->vec->n_refs++; - return inst->vec; - } - if (inst->ops == &frame_ops) - return NULL; - abort(); -} - - struct vec *inst_get_vec(const struct inst *inst) { if (inst->ops == &vec_ops) diff --git a/inst.h b/inst.h index 0267dc6..24ec873 100644 --- a/inst.h +++ b/inst.h @@ -87,7 +87,6 @@ void inst_deselect(void); struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos); struct coord inst_get_point(const struct inst *inst); int inst_anchors(struct inst *inst, struct vec ***anchors); -struct vec *inst_get_ref(const struct inst *inst); struct vec *inst_get_vec(const struct inst *inst); int inst_vec(struct vec *vec, struct coord base); diff --git a/obj.h b/obj.h index 19461d7..03d9a04 100644 --- a/obj.h +++ b/obj.h @@ -88,7 +88,6 @@ struct vec { struct expr *x; struct expr *y; struct vec *base; /* NULL if frame */ - int n_refs; struct vec *next; /* used during generation */ @@ -174,23 +173,6 @@ extern struct frame *root_frame; extern struct frame *active_frame; -static inline struct vec *get_vec(struct vec *vec) -{ - if (vec) - vec->n_refs++; - return vec; -} - - -static inline void put_vec(struct vec *vec) -{ - if (vec) { - assert(vec->n_refs); - vec->n_refs--; - } -} - - int instantiate(void); #endif /* !OBJ_H */