diff --git a/README b/README index a43c211..038fc9d 100644 --- a/README +++ b/README @@ -13,6 +13,14 @@ that can be performed through the GUI. Building -------- +Prerequisites: + +- flex +- bison +- fig2dev +- ImageMagick +- Gtk+ 2.x development package (libgtk2.0-dev or similar) + Check out the repository: svn co http://svn.openmoko.org/trunk/eda/fped @@ -79,7 +87,7 @@ The file has the following structure: frame definitions ... -part name +package name objects ... @@ -234,18 +242,21 @@ b: vec @(1mm, 1mm) meas a b 0.2 mm -Part name -- - - - - +Package name +- - - - - - -The part name is a string of alphanumerical characters. Underscores are -allowed in the part name as well. +The package name is a string of printable ASCII characters, including +spaces. -part "" +package "" Examples: -part "SSOP_48" -part "0603" +package "48-SSOP" +package "0603" + +Like in pad names, variables are expanded in package names. This allows +the generation of multiple packages from a single definition. Frames diff --git a/TODO b/TODO index 5039336..62c34b5 100644 --- a/TODO +++ b/TODO @@ -25,12 +25,19 @@ Style: excessively large. - pango_layout_get_size doesn't seem to consider rotation, so we currently don't properly size rotated text. +- when changing the part, we should automatically switch to a configuration + that generates any of its (non-global) elements Bugs: - default silk width has no business being hard-coded in obj.c - undelete only works if not much has changed since the deletion - focus should return to canvas if nobody else wants it - whenever we call parse_* for input parsing, we may leak lots of expressions +- can't edit measurement labels through the GUI +- r of rpads is misleading, particularly if we have a circle +- we can't enter an arc through the GUI / can't convert a circle to an arc +- using variables in a measurement offset causes a crash because evaluation + takes place after all table entries have been visited Code cleanup: - merge edit_unique with edit_name @@ -68,7 +75,4 @@ Future directions: - advanced: non-standard solder mask - advanced: solder paste exceptions (subtractive, additive) - advanced: silk line width -- future: when encountering an error after a change, we could try to find the - same element in the old instance, and select it - future: consider editing non-canvas items in place -- near future: treat part name as pattern diff --git a/dump.c b/dump.c index d5e981a..ef3576b 100644 --- a/dump.c +++ b/dump.c @@ -485,7 +485,7 @@ int dump(FILE *file) fprintf(file, "/* MACHINE-GENERATED ! */\n\n"); for (frame = frames; frame; frame = frame->next) { if (!frame->name) { - fprintf(file, "part \"%s\"\n", part_name); + fprintf(file, "package \"%s\"\n", pkg_name); dump_frame(file, frame, ""); } else { fprintf(file, "frame %s {\n", frame->name); diff --git a/fpd.l b/fpd.l index edfd6d0..5d6f200 100644 --- a/fpd.l +++ b/fpd.l @@ -89,7 +89,9 @@ SP [\t ]* "loop" { BEGIN(NOKEYWORD); return TOK_LOOP; } "part" { BEGIN(NOKEYWORD); - return TOK_PART; } + return TOK_PACKAGE; } +"package" { BEGIN(NOKEYWORD); + return TOK_PACKAGE; } "frame" { BEGIN(NOKEYWORD); is_table = 0; return TOK_FRAME; } diff --git a/fpd.y b/fpd.y index 0464c9b..8648d4f 100644 --- a/fpd.y +++ b/fpd.y @@ -154,7 +154,7 @@ static struct obj *new_obj(enum obj_type type) %token START_FPD START_EXPR START_VAR START_VALUES -%token TOK_SET TOK_LOOP TOK_PART TOK_FRAME TOK_TABLE TOK_VEC +%token TOK_SET TOK_LOOP TOK_PACKAGE TOK_FRAME TOK_TABLE TOK_VEC %token TOK_PAD TOK_RPAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC %token TOK_MEAS TOK_MEASX TOK_MEASY %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED @@ -210,20 +210,20 @@ fpd: ; part_name: - TOK_PART STRING + TOK_PACKAGE STRING { const char *p; if (!*$2) { - yyerrorf("invalid part name"); + yyerrorf("invalid package name"); YYABORT; } for (p = $2; *p; *p++) if (*p < 32 || *p > 126) { - yyerrorf("invalid part name"); + yyerrorf("invalid package name"); YYABORT; } - part_name = $2; + pkg_name = $2; } ; @@ -394,7 +394,6 @@ vec: $$->y = $6; $$->frame = curr_frame; $$->next = NULL; - $$->samples = NULL; last_vec = $$; *next_vec = $$; next_vec = &$$->next; diff --git a/fped.c b/fped.c index 79afb99..7c277bc 100644 --- a/fped.c +++ b/fped.c @@ -91,8 +91,8 @@ int main(int argc, char **argv) usage(name); } - if (!part_name) - part_name = stralloc("_"); + if (!pkg_name) + pkg_name = stralloc("_"); reporter = report_to_stderr; if (!instantiate()) diff --git a/gui_frame.c b/gui_frame.c index a3c5175..a8a6d1d 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -1236,10 +1236,10 @@ static void dont_build_items(struct frame *frame) } -/* ----- part name --------------------------------------------------------- */ +/* ----- package name ------------------------------------------------------ */ -static int validate_part_name(const char *s, void *ctx) +static int validate_pkg_name(const char *s, void *ctx) { if (!*s) return 0; @@ -1251,7 +1251,7 @@ static int validate_part_name(const char *s, void *ctx) return 1; } -static void unselect_part_name(void *data) +static void unselect_pkg_name(void *data) { GtkWidget *widget = data; @@ -1259,40 +1259,107 @@ static void unselect_part_name(void *data) } -static gboolean part_name_edit_event(GtkWidget *widget, GdkEventButton *event, +static gboolean pkg_name_edit_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { switch (event->button) { case 1: - inst_select_outside(widget, unselect_part_name); + inst_select_outside(widget, unselect_pkg_name); label_in_box_bg(widget, COLOR_PART_NAME_EDITING); - status_set_type_entry("part ="); - status_set_name("%s", part_name); + status_set_type_entry("package ="); + status_set_name("%s", pkg_name); edit_nothing(); - edit_name(&part_name, validate_part_name, NULL); + edit_name(&pkg_name, validate_pkg_name, NULL); break; } return TRUE; } -static GtkWidget *build_part_name(void) +static GtkWidget *build_pkg_name(void) { GtkWidget *label; - label = label_in_box_new(part_name); + label = label_in_box_new(pkg_name); gtk_misc_set_padding(GTK_MISC(label), 2, 2); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); label_in_box_bg(label, COLOR_PART_NAME); g_signal_connect(G_OBJECT(box_of_label(label)), - "button_press_event", G_CALLBACK(part_name_edit_event), NULL); + "button_press_event", G_CALLBACK(pkg_name_edit_event), NULL); return box_of_label(label); } +/* ----- packages ---------------------------------------------------------- */ + + +static gboolean pkg_scroll_event(GtkWidget *widget, GdkEventScroll *event, + gpointer data) +{ + struct pkg *pkg, *last; + + switch (event->direction) { + case GDK_SCROLL_UP: + if (active_pkg->next) + active_pkg = active_pkg->next; + else + active_pkg = pkgs->next; + change_world(); + break; + case GDK_SCROLL_DOWN: + last = NULL; + for (pkg = pkgs->next; pkg && (!last || pkg != active_pkg); + pkg = pkg->next) + last = pkg; + active_pkg = last; + change_world(); + break; + default: + /* ignore */; + } + return TRUE; +} + + +static gboolean pkg_select_event(GtkWidget *widget, GdkEventButton *event, + gpointer data) +{ + struct pkg *pkg = data; + + switch (event->button) { + case 1: + active_pkg = pkg; + /* @@@ we could actually skip instantiation here */ + change_world(); + break; + } + return TRUE; +} + + +static GtkWidget *build_pkg_names(void) +{ + GtkWidget *hbox; + struct pkg *pkg; + GtkWidget *field; + + hbox = gtk_hbox_new(FALSE, 0); + for (pkg = pkgs; pkg; pkg = pkg->next) + if (pkg->name) { + field = add_activator(hbox, pkg == active_pkg, + pkg_select_event, pkg, + "%s", pkg->name); + g_signal_connect(G_OBJECT(box_of_label(field)), + "scroll_event", + G_CALLBACK(pkg_scroll_event), NULL); + } + return hbox; +} + + /* ----- frame labels ------------------------------------------------------ */ @@ -1428,7 +1495,7 @@ static GtkWidget *build_frame_refs(const struct frame *frame) void build_frames(GtkWidget *vbox) { struct frame *frame; - GtkWidget *hbox, *tab, *label, *refs, *vars, *items, *meas; + GtkWidget *hbox, *tab, *label, *packages, *refs, *vars, *items, *meas; int n = 0; destroy_all_children(GTK_CONTAINER(vbox)); @@ -1444,9 +1511,12 @@ void build_frames(GtkWidget *vbox) gtk_box_pack_start(GTK_BOX(hbox), tab, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - label = build_part_name(); + label = build_pkg_name(); gtk_table_attach_defaults(GTK_TABLE(tab), label, 0, 1, 0, 1); + packages = build_pkg_names(); + gtk_table_attach_defaults(GTK_TABLE(tab), packages, 1, 2, 0, 1); + n = 0; for (frame = root_frame; frame; frame = frame->prev) { label = build_frame_label(frame); diff --git a/gui_meas.c b/gui_meas.c index 6a90640..5c4254a 100644 --- a/gui_meas.c +++ b/gui_meas.c @@ -63,7 +63,7 @@ static int is_min(lt_op_type lt, const struct inst *inst) { struct coord min; - min = meas_find_min(lt, inst->vec->samples); + min = meas_find_min(lt, active_pkg->samples[inst->vec->n]); return coord_eq(inst->u.rect.end, min); } @@ -73,7 +73,8 @@ static int is_next(lt_op_type lt, { struct coord next; - next = meas_find_next(lt, inst->vec->samples, ref->u.rect.end); + next = meas_find_next(lt, active_pkg->samples[inst->vec->n], + ref->u.rect.end); return coord_eq(inst->u.rect.end, next); } @@ -82,7 +83,7 @@ static int is_max(lt_op_type lt, const struct inst *inst) { struct coord max; - max = meas_find_max(lt, inst->vec->samples); + max = meas_find_max(lt, active_pkg->samples[inst->vec->n]); return coord_eq(inst->u.rect.end, max); } @@ -93,8 +94,9 @@ static int is_a_next(lt_op_type lt, struct inst *inst) struct coord min, next; for (a = insts_ip_vec(); a; a = a->next) { - min = meas_find_min(lt, a->vec->samples); - next = meas_find_next(lt, inst->vec->samples, min); + min = meas_find_min(lt, active_pkg->samples[a->vec->n]); + next = meas_find_next(lt, active_pkg->samples[inst->vec->n], + min); if (coord_eq(next, inst->u.rect.end)) return 1; } @@ -122,7 +124,7 @@ static int meas_pick_vec_a(struct inst *inst, void *ctx) { struct vec *vec = inst->vec; - if (!vec->samples) + if (!active_pkg->samples[vec->n]) return 0; if (is_min(meas_dsc->lt, inst)) { mode = min_to_next_or_max; @@ -145,7 +147,7 @@ static int meas_pick_vec_b(struct inst *inst, void *ctx) struct vec *vec = inst->vec; struct inst *a = ctx; - if (!vec->samples) + if (!active_pkg->samples[vec->n]) return 0; switch (mode) { case min_to_next_or_max: @@ -337,7 +339,7 @@ static struct inst *vec_at(const struct vec *vec, struct coord pos) for (inst = insts_ip_vec(); inst; inst = inst->next) if (inst->vec == vec) - for (s = vec->samples; s; s = s->next) + for (s = active_pkg->samples[vec->n]; s; s = s->next) if (coord_eq(s->pos, pos)) return inst; abort(); diff --git a/gui_tool.c b/gui_tool.c index 9c2a4a8..6fc2470 100644 --- a/gui_tool.c +++ b/gui_tool.c @@ -77,7 +77,6 @@ static struct vec *new_vec(struct inst *base) vec->base = inst_get_vec(base); vec->next = NULL; vec->frame = active_frame; - vec->samples = NULL; for (walk = &active_frame->vecs; *walk; walk = &(*walk)->next); *walk = vec; return vec; diff --git a/inst.c b/inst.c index 2ee8d51..5695cf2 100644 --- a/inst.c +++ b/inst.c @@ -31,12 +31,11 @@ struct inst *selected_inst = NULL; -struct inst *insts[ip_n]; struct bbox active_frame_bbox; +struct pkg *pkgs, *active_pkg, *curr_pkg; +struct inst *curr_frame = NULL; -static struct inst *curr_frame = NULL; -static struct inst **next_inst[ip_n]; -static struct inst *prev_insts[ip_n]; +static struct pkg *prev_pkgs; static unsigned long active_set = 0; @@ -171,7 +170,7 @@ int inst_select(struct coord pos) FOR_INST_PRIOS_DOWN(prio) { if (!show(prio)) continue; - for (inst = insts[prio]; inst; inst = inst->next) { + for (inst = active_pkg->insts[prio]; inst; inst = inst->next) { if (!inst->active || !inst->ops->distance) continue; if (!inst_connected(inst)) @@ -191,7 +190,7 @@ int inst_select(struct coord pos) /* give vectors a second chance */ - for (inst = insts[ip_vec]; inst; inst = inst->next) { + for (inst = active_pkg->insts[ip_vec]; inst; inst = inst->next) { if (!inst->active) continue; if (!inst_connected(inst)) @@ -219,7 +218,7 @@ struct inst *inst_find_point(struct coord pos) int dist; found = NULL; - for (inst = insts[ip_frame]; inst; inst = inst->next) { + for (inst = active_pkg->insts[ip_frame]; inst; inst = inst->next) { if (!inst->u.frame.active) continue; dist = gui_dist_frame_eye(inst, pos, draw_ctx.scale); @@ -231,7 +230,7 @@ struct inst *inst_find_point(struct coord pos) if (found) return found; - for (inst = insts[ip_vec]; inst; inst = inst->next) { + for (inst = active_pkg->insts[ip_vec]; inst; inst = inst->next) { if (!inst->active || !inst->ops->distance) continue; dist = inst->ops->distance(inst, pos, draw_ctx.scale); @@ -256,7 +255,8 @@ int inst_find_point_selected(struct coord pos, struct inst **res) n = inst_anchors(selected_inst, anchors); for (i = 0; i != n; i++) { if (*anchors[i]) { - for (inst = insts[ip_vec]; inst; inst = inst->next) { + for (inst = active_pkg->insts[ip_vec]; inst; + inst = inst->next) { if (inst->vec != *anchors[i]) continue; d = gui_dist_vec(inst, pos, draw_ctx.scale); @@ -267,7 +267,8 @@ int inst_find_point_selected(struct coord pos, struct inst **res) } } } else { - for (inst = insts[ip_frame]; inst; inst = inst->next) { + for (inst = active_pkg->insts[ip_frame]; inst; + inst = inst->next) { if (inst != selected_inst->outer) continue; d = gui_dist_frame(inst, pos, draw_ctx.scale); @@ -347,7 +348,7 @@ void inst_select_vec(struct vec *vec) if (vec->frame != active_frame) select_frame(vec->frame); - for (inst = insts[ip_vec]; inst; inst = inst->next) + for (inst = active_pkg->insts[ip_vec]; inst; inst = inst->next) if (inst->vec == vec && inst->active) { inst_deselect(); inst_select_inst(inst); @@ -364,13 +365,20 @@ void inst_select_obj(struct obj *obj) if (obj->frame != active_frame) select_frame(obj->frame); - FOR_INSTS_DOWN(prio, inst) - if (inst->obj && inst->obj == obj && inst->active) { - inst_deselect(); - inst_select_inst(inst); - return; - } + FOR_INST_PRIOS_DOWN(prio) { + FOR_GLOBAL_INSTS(prio, inst) + if (inst->obj && inst->obj == obj && inst->active) + goto found; + FOR_PKG_INSTS(prio, inst) + if (inst->obj && inst->obj == obj && inst->active) + goto found; + } obj_edit(obj); + return; + +found: + inst_deselect(); + inst_select_inst(inst); } @@ -415,7 +423,8 @@ static void update_bbox(struct bbox *bbox, struct coord coord) static void propagate_bbox(const struct inst *inst) { - struct inst *frame = curr_frame ? curr_frame : insts[ip_frame]; + struct inst *frame = + curr_frame ? curr_frame : curr_pkg->insts[ip_frame]; update_bbox(&frame->bbox, inst->bbox.min); update_bbox(&frame->bbox, inst->bbox.max); @@ -445,8 +454,8 @@ static struct inst *add_inst(const struct inst_ops *ops, enum inst_prio prio, inst->active = IS_ACTIVE; inst->in_path = 0; inst->next = NULL; - *next_inst[prio] = inst; - next_inst[prio] = &inst->next; + *curr_pkg->next_inst[prio] = inst; + curr_pkg->next_inst[prio] = &inst->next; return inst; } @@ -454,14 +463,6 @@ static struct inst *add_inst(const struct inst_ops *ops, enum inst_prio prio, /* ----- vec --------------------------------------------------------------- */ -static void vec_op_debug(struct inst *self) -{ - printf("vec %lg, %lg -> %lg, %lg\n", - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.rect.end.x), units_to_mm(self->u.rect.end.y)); -} - - static int validate_vec_name(const char *s, void *ctx) { struct vec *vec = ctx; @@ -525,7 +526,6 @@ static int vec_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops vec_ops = { - .debug = vec_op_debug, .draw = gui_draw_vec, .hover = gui_hover_vec, .distance = gui_dist_vec, @@ -552,14 +552,6 @@ int inst_vec(struct vec *vec, struct coord base) /* ----- line -------------------------------------------------------------- */ -static void line_op_debug(struct inst *self) -{ - printf("line %lg, %lg / %lg, %lg\n", - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.rect.end.x), units_to_mm(self->u.rect.end.y)); -} - - static void obj_line_edit(struct obj *obj) { edit_expr(&obj->u.line.width); @@ -584,7 +576,6 @@ static int line_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops line_ops = { - .debug = line_op_debug, .draw = gui_draw_line, .distance = gui_dist_line, .select = line_op_select, @@ -611,14 +602,6 @@ int inst_line(struct obj *obj, struct coord a, struct coord b, unit_type width) /* ----- rect -------------------------------------------------------------- */ -static void rect_op_debug(struct inst *self) -{ - printf("rect %lg, %lg / %lg, %lg\n", - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.rect.end.x), units_to_mm(self->u.rect.end.y)); -} - - static void obj_rect_edit(struct obj *obj) { edit_expr(&obj->u.rect.width); @@ -633,7 +616,6 @@ static void rect_op_select(struct inst *self) static struct inst_ops rect_ops = { - .debug = rect_op_debug, .draw = gui_draw_rect, .distance = gui_dist_rect, .select = rect_op_select, @@ -660,21 +642,6 @@ int inst_rect(struct obj *obj, struct coord a, struct coord b, unit_type width) /* ----- pad / rpad -------------------------------------------------------- */ -static void pad_op_debug(struct inst *self) -{ - printf("pad \"%s\" %lg, %lg / %lg, %lg\n", self->u.name, - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.pad.other.x), units_to_mm(self->u.pad.other.y)); -} - - -static void rpad_op_debug(struct inst *self) -{ - printf("r"); - pad_op_debug(self); -} - - static int validate_pad_name(const char *s, void *ctx) { char *tmp; @@ -713,7 +680,6 @@ static int pad_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops pad_ops = { - .debug = pad_op_debug, .draw = gui_draw_pad, .distance = gui_dist_pad, .select = pad_op_select, @@ -723,7 +689,6 @@ static struct inst_ops pad_ops = { static struct inst_ops rpad_ops = { - .debug = rpad_op_debug, .draw = gui_draw_rpad, .distance = gui_dist_pad, /* @@@ */ .select = pad_op_select, @@ -749,14 +714,6 @@ int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b) /* ----- arc --------------------------------------------------------------- */ -static void arc_op_debug(struct inst *self) -{ - printf("arc %lg, %lg radius %lg %lg ... %lg\n", - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.arc.r), self->u.arc.a1, self->u.arc.a2); -} - - static void obj_arc_edit(struct obj *obj) { edit_expr(&obj->u.arc.width); @@ -788,7 +745,6 @@ static int arc_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops arc_ops = { - .debug = arc_op_debug, .draw = gui_draw_arc, .distance = gui_dist_arc, .select = arc_op_select, @@ -827,15 +783,6 @@ int inst_arc(struct obj *obj, struct coord center, struct coord start, /* ----- measurement ------------------------------------------------------- */ -static void meas_op_debug(struct inst *self) -{ - printf("meas %lg, %lg / %lg, %lg offset %lg\n", - units_to_mm(self->base.x), units_to_mm(self->base.y), - units_to_mm(self->u.meas.end.x), units_to_mm(self->u.meas.end.y), - units_to_mm(self->u.meas.offset)); -} - - static void obj_meas_edit(struct obj *obj) { edit_expr(&obj->u.meas.offset); @@ -862,7 +809,6 @@ static int meas_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops meas_ops = { - .debug = meas_op_debug, .draw = gui_draw_meas, .distance = gui_dist_meas, .select = meas_op_select, @@ -943,14 +889,6 @@ void inst_end_active(void) /* ----- frame ------------------------------------------------------------- */ -static void frame_op_debug(struct inst *self) -{ - printf("frame %s @ %lg, %lg\n", - self->u.frame.ref->name ? self->u.frame.ref->name : "(root)", - units_to_mm(self->base.x), units_to_mm(self->base.y)); -} - - static void frame_op_select(struct inst *self) { rect_status(self->bbox.min, self->bbox.max, -1); @@ -967,7 +905,6 @@ static int frame_op_anchors(struct inst *inst, struct vec ***anchors) static struct inst_ops frame_ops = { - .debug = frame_op_debug, .draw = gui_draw_frame, .hover = gui_hover_frame, .distance = gui_dist_frame, @@ -1003,56 +940,91 @@ void inst_end_frame(const struct frame *frame) } +/* ----- package ----------------------------------------------------------- */ + + +void inst_select_pkg(const char *name) +{ + struct pkg **pkg; + enum inst_prio prio; + + name = name ? unique(name) : NULL; + for (pkg = &pkgs; *pkg; pkg = &(*pkg)->next) + if ((*pkg)->name == name) + break; + if (!*pkg) { + *pkg = zalloc_type(struct pkg); + (*pkg)->name = name; + FOR_INST_PRIOS_UP(prio) + (*pkg)->next_inst[prio] = &(*pkg)->insts[prio]; + (*pkg)->samples = + zalloc_size(sizeof(struct sample *)*n_samples); + } + curr_pkg = *pkg; +} + + /* ----- misc. ------------------------------------------------------------- */ struct bbox inst_get_bbox(void) { - return insts[ip_frame]->bbox; + return pkgs->insts[ip_frame]->bbox; } -static void inst_free(struct inst *list[ip_n]) +static void free_pkgs(struct pkg *pkg) { enum inst_prio prio; - struct inst *next; + struct pkg *next_pkg; + struct inst *inst, *next; - FOR_INST_PRIOS_UP(prio) - while (list[prio]) { - next = list[prio]->next; - free(list[prio]); - list[prio] = next; - } + while (pkg) { + next_pkg = pkg->next; + FOR_INST_PRIOS_UP(prio) + for (inst = pkg->insts[prio]; inst; inst = next) { + next = inst->next; + free(inst); + } + reset_samples(pkg->samples); + free(pkg->samples); + free(pkg); + pkg = next_pkg; + } } void inst_start(void) { static struct bbox bbox_zero = { { 0, 0 }, { 0, 0 }}; - enum inst_prio prio; active_frame_bbox = bbox_zero; - FOR_INST_PRIOS_UP(prio) { - prev_insts[prio] = insts[prio]; - insts[prio] = NULL; - next_inst[prio] = &insts[prio]; - } + prev_pkgs = pkgs; + pkgs = NULL; + inst_select_pkg(NULL); + curr_pkg = pkgs; } void inst_commit(void) { - inst_free(prev_insts); + struct pkg *pkg; + + if (active_pkg) { + for (pkg = pkgs; pkgs && pkg->name != active_pkg->name; + pkg = pkg->next); + active_pkg = pkg; + } + if (!active_pkg) + active_pkg = pkgs->next; + free_pkgs(prev_pkgs); } void inst_revert(void) { - enum inst_prio prio; - - inst_free(insts); - FOR_INST_PRIOS_UP(prio) - insts[prio] = prev_insts[prio]; + free_pkgs(pkgs); + pkgs = prev_pkgs; } @@ -1061,18 +1033,34 @@ void inst_draw(void) enum inst_prio prio; struct inst *inst; - FOR_INSTS_UP(prio, inst) - if (show(prio) && !inst->active && inst->ops->draw) - inst->ops->draw(inst); - FOR_INSTS_UP(prio, inst) - if (show(prio) && prio != ip_frame && inst->active && - inst != selected_inst && inst->ops->draw) - inst->ops->draw(inst); - if (show_stuff) - for (inst = insts[ip_frame]; inst; inst = inst->next) + FOR_INST_PRIOS_UP(prio) { + FOR_GLOBAL_INSTS(prio, inst) + if (show(prio) && !inst->active && inst->ops->draw) + inst->ops->draw(inst); + FOR_PKG_INSTS(prio, inst) + if (show(prio) && !inst->active && inst->ops->draw) + inst->ops->draw(inst); + } + FOR_INST_PRIOS_UP(prio) { + FOR_GLOBAL_INSTS(prio, inst) + if (show(prio) && prio != ip_frame && inst->active && + inst != selected_inst && inst->ops->draw) + inst->ops->draw(inst); + FOR_PKG_INSTS(prio, inst) + if (show(prio) && prio != ip_frame && inst->active && + inst != selected_inst && inst->ops->draw) + inst->ops->draw(inst); + } + if (show_stuff) { + FOR_GLOBAL_INSTS(ip_frame, inst) if (inst->active && inst != selected_inst && inst->ops->draw) inst->ops->draw(inst); + FOR_PKG_INSTS(ip_frame, inst) + if (inst->active && inst != selected_inst && + inst->ops->draw) + inst->ops->draw(inst); + } if (selected_inst && selected_inst->ops->draw) selected_inst->ops->draw(selected_inst); } @@ -1082,7 +1070,10 @@ void inst_highlight_vecs(int (*pick)(struct inst *inst, void *user), void *user) { struct inst *inst; - for (inst = insts[ip_vec]; inst; inst = inst->next) + FOR_GLOBAL_INSTS(ip_vec, inst) + if (pick(inst, user)) + gui_highlight_vec(inst); + FOR_PKG_INSTS(ip_vec, inst) if (pick(inst, user)) gui_highlight_vec(inst); } @@ -1096,7 +1087,18 @@ struct inst *inst_find_vec(struct coord pos, int dist; found = NULL; - for (inst = insts[ip_vec]; inst; inst = inst->next) { + FOR_GLOBAL_INSTS(ip_vec, inst) { + if (!inst->ops->distance) + continue; + dist = inst->ops->distance(inst, pos, draw_ctx.scale); + if (dist < 0 || (found && best_dist <= dist)) + continue; + if (!pick(inst, user)) + continue; + found = inst; + best_dist = dist; + } + FOR_PKG_INSTS(ip_vec, inst) { if (!inst->ops->distance) continue; dist = inst->ops->distance(inst, pos, draw_ctx.scale); @@ -1113,7 +1115,7 @@ struct inst *inst_find_vec(struct coord pos, struct inst *insts_ip_vec(void) { - return insts[ip_vec]; + return active_pkg->insts[ip_vec]; } @@ -1154,13 +1156,3 @@ void inst_delete(struct inst *inst) else delete_obj(inst->obj); } - - -void inst_debug(void) -{ - enum inst_prio prio; - struct inst *inst; - - FOR_INSTS_UP(prio, inst) - inst->ops->debug(inst); -} diff --git a/inst.h b/inst.h index 8f79284..b929769 100644 --- a/inst.h +++ b/inst.h @@ -109,10 +109,32 @@ struct inst { }; +struct pkg { + const char *name; /* NULL if global package */ + struct inst *insts[ip_n]; + struct inst **next_inst[ip_n]; + struct sample **samples; + struct pkg *next; +}; + + extern struct inst *selected_inst; -extern struct inst *insts[ip_n]; +extern struct pkg *pkgs; /* list of packages */ +extern struct pkg *active_pkg; /* package selected in GUI */ +extern struct pkg *curr_pkg; /* package currently being instantiated */ extern struct bbox active_frame_bbox; +/* + * frame being instantiated - we need to export this one for meas.c, so that + * measurement scan update the root frame's bounding box. + */ +extern struct inst *curr_frame; + +/* + * @@@ Note that we over-generalize a bit here: the only item that ever ends up + * in the global package is currently the root frame. However, we may later + * allow other items shared by all packages be there as well. + */ #define FOR_INST_PRIOS_UP(prio) \ for (prio = 0; prio != ip_n; prio++) @@ -120,13 +142,11 @@ extern struct bbox active_frame_bbox; #define FOR_INST_PRIOS_DOWN(prio) \ for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--) -#define FOR_INSTS_UP(prio, inst) \ - FOR_INST_PRIOS_UP(prio) \ - for (inst = insts[prio]; inst; inst = inst->next) +#define FOR_GLOBAL_INSTS(prio, inst) \ + for (inst = pkgs->insts[prio]; inst; inst = inst->next) -#define FOR_INSTS_DOWN(prio, inst) \ - FOR_INST_PRIOS_DOWN(prio) \ - for (inst = insts[prio]; inst; inst = inst->next) +#define FOR_PKG_INSTS(prio, inst) \ + for (inst = active_pkg->insts[prio]; inst; inst = inst->next) void inst_select_outside(void *item, void (*deselect)(void *item)); @@ -158,6 +178,8 @@ void inst_begin_frame(struct obj *obj, const struct frame *frame, struct coord base, int active, int is_active_frame); void inst_end_frame(const struct frame *frame); +void inst_select_pkg(const char *name); + struct bbox inst_get_bbox(void); void inst_start(void); @@ -176,6 +198,5 @@ int inst_do_move_to(struct inst *inst, struct inst *to, int i); struct pix_buf *inst_hover(struct inst *inst); void inst_begin_drag_move(struct inst *inst, int i); void inst_delete(struct inst *inst); -void inst_debug(void); #endif /* !INST_H */ diff --git a/kicad.c b/kicad.c index 38e4349..f889cea 100644 --- a/kicad.c +++ b/kicad.c @@ -208,7 +208,7 @@ static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst) } -static void kicad_module(FILE *file, const char *name, time_t now) +static void kicad_module(FILE *file, const struct pkg *pkg, time_t now) { enum inst_prio prio; const struct inst *inst; @@ -216,7 +216,7 @@ static void kicad_module(FILE *file, const char *name, time_t now) /* * Module library name */ - fprintf(file, "$MODULE %s\n", name); + fprintf(file, "$MODULE %s\n", pkg->name); /* * Xpos = 0, Ypos = 0, 15 layers, last modification, timestamp, @@ -227,13 +227,13 @@ static void kicad_module(FILE *file, const char *name, time_t now) /* * Module library name again */ - fprintf(file, "Li %s\n", name); + fprintf(file, "Li %s\n", pkg->name); #if 0 /* optional */ /* * Description */ - fprintf(file, "Cd %s\n", name); + fprintf(file, "Cd %s\n", pkg->name); #endif /* @@ -258,28 +258,37 @@ static void kicad_module(FILE *file, const char *name, time_t now) */ fprintf(file, "T0 0 -150 200 200 0 40 N V %d \"%s\"\n", - layer_comment, name); + layer_comment, pkg->name); fprintf(file, "T1 0 150 200 200 0 40 N I %d \"Val*\"\n", layer_comment); - FOR_INSTS_UP(prio, inst) - kicad_inst(file, prio, inst); + FOR_INST_PRIOS_UP(prio) { + for (inst = pkgs->insts[prio]; inst; inst = inst->next) + kicad_inst(file, prio, inst); + for (inst = pkg->insts[prio]; inst; inst = inst->next) + kicad_inst(file, prio, inst); + } - fprintf(file, "$EndMODULE %s\n", name); + fprintf(file, "$EndMODULE %s\n", pkg->name); } int kicad(FILE *file) { + const struct pkg *pkg; time_t now = time(NULL); fprintf(file, "PCBNEW-LibModule-V1 %s", ctime(&now)); fprintf(file, "$INDEX\n"); - fprintf(file, "%s\n", part_name); + for (pkg = pkgs; pkg; pkg = pkg->next) + if (pkg->name) + fprintf(file, "%s\n", pkg->name); fprintf(file, "$EndINDEX\n"); - kicad_module(file, part_name, now); + for (pkg = pkgs; pkg; pkg = pkg->next) + if (pkg->name) + kicad_module(file, pkg, now); fprintf(file, "$EndLIBRARY\n"); diff --git a/meas.c b/meas.c index d2232fa..7c70327 100644 --- a/meas.c +++ b/meas.c @@ -21,37 +21,43 @@ #include "meas.h" +int n_samples; + + struct num eval_unit(const struct expr *expr, const struct frame *frame); -static void reset_samples(struct sample **samples) +void reset_samples(struct sample **samples) { struct sample *next; + int i; - while (*samples) { - next = (*samples)->next; - free(*samples); - *samples = next; - } + for (i = 0; i != n_samples; i++) + while (samples[i]) { + next = samples[i]->next; + free(samples[i]); + samples[i] = next; + } } void meas_start(void) { - struct frame *frame; + const struct frame *frame; struct vec *vec; + n_samples = 0; for (frame = frames; frame; frame = frame->next) for (vec = frame->vecs; vec; vec = vec->next) - reset_samples(&vec->samples); + vec->n = n_samples++; } -void meas_post(struct vec *vec, struct coord pos) +void meas_post(const struct vec *vec, struct coord pos) { struct sample **walk, *new; - for (walk = &vec->samples; *walk; walk = &(*walk)->next) { + for (walk = &curr_pkg->samples[vec->n]; *walk; walk = &(*walk)->next) { if (pos.y < (*walk)->pos.y) break; if (pos.y > (*walk)->pos.y) @@ -219,7 +225,7 @@ struct coord meas_find_max(lt_op_type lt, const struct sample *s) /* ----- instantiation ----------------------------------------------------- */ -int instantiate_meas(void) +static int instantiate_meas_pkg(void) { struct obj *obj; const struct meas *meas; @@ -231,15 +237,18 @@ int instantiate_meas(void) if (obj->type != ot_meas) continue; meas = &obj->u.meas; - if (!obj->base->samples || !meas->high->samples) + if (!curr_pkg->samples[obj->base->n] || + !curr_pkg->samples[meas->high->n]) continue; lt = lt_op[meas->type]; - a0 = meas_find_min(lt, obj->base->samples); + a0 = meas_find_min(lt, curr_pkg->samples[obj->base->n]); if (is_next[meas->type]) - b0 = meas_find_next(lt, meas->high->samples, a0); + b0 = meas_find_next(lt, + curr_pkg->samples[meas->high->n], a0); else - b0 = meas_find_max(lt, meas->high->samples); + b0 = meas_find_max(lt, + curr_pkg->samples[meas->high->n]); if (!meas->offset) offset.n = 0; @@ -256,3 +265,18 @@ int instantiate_meas(void) } return 1; } + + +int instantiate_meas(void) +{ + struct pkg *pkg; + + curr_frame = pkgs->insts[ip_frame]; + for (pkg = pkgs; pkg; pkg = pkg->next) + if (pkg->name) { + inst_select_pkg(pkg->name); + if (!instantiate_meas_pkg()) + return 0; + } + return 1; +} diff --git a/meas.h b/meas.h index 5ff7913..1d42341 100644 --- a/meas.h +++ b/meas.h @@ -47,6 +47,9 @@ struct sample { }; +extern int n_samples; + + int lt_x(struct coord a, struct coord b); int lt_y(struct coord a, struct coord b); int lt_xy(struct coord a, struct coord b); @@ -56,8 +59,10 @@ struct coord meas_find_next(lt_op_type lt, const struct sample *s, struct coord ref); struct coord meas_find_max(lt_op_type lt, const struct sample *s); + +void reset_samples(struct sample **samples); void meas_start(void); -void meas_post(struct vec *vec, struct coord pos); +void meas_post(const struct vec *vec, struct coord pos); int instantiate_meas(void); #endif /* !MEAS_H */ diff --git a/obj.c b/obj.c index 58ca1e4..be04432 100644 --- a/obj.c +++ b/obj.c @@ -28,7 +28,7 @@ #define MAX_ITERATIONS 1000 /* abort "loop"s at this limit */ -char *part_name = NULL; +char *pkg_name = NULL; struct frame *frames = NULL; struct frame *root_frame = NULL; struct frame *active_frame = NULL; @@ -163,8 +163,14 @@ error: static int generate_items(struct frame *frame, struct coord base, int active) { + char *s; int ok; + if (!frame->name) { + s = expand(pkg_name, frame); + inst_select_pkg(s); + free(s); + } inst_begin_active(active && frame == active_frame); ok = generate_vecs(frame, base) && generate_objs(frame, base, active); inst_end_active(); @@ -270,8 +276,8 @@ int instantiate(void) struct coord zero = { 0, 0 }; int ok; - inst_start(); meas_start(); + inst_start(); instantiation_error = NULL; ok = generate_frame(root_frame, zero, NULL, NULL, 1); if (ok) diff --git a/obj.h b/obj.h index e272f8c..e637ec3 100644 --- a/obj.h +++ b/obj.h @@ -100,8 +100,8 @@ struct vec { /* used when editing */ struct frame *frame; - /* samples for measurements */ - struct sample *samples; + /* index into table of samples */ + int n; /* for the GUI */ GtkWidget *list_widget; /* NULL if items aren't shown */ @@ -180,7 +180,7 @@ struct obj { }; -extern char *part_name; +extern char *pkg_name; extern struct frame *frames; extern struct frame *root_frame; extern struct frame *active_frame; diff --git a/postscript.c b/postscript.c index 6285abb..3574715 100644 --- a/postscript.c +++ b/postscript.c @@ -373,10 +373,18 @@ fprintf(file, " dup false charpath stroke grestore\n" " show } def\n"); - FOR_INSTS_UP(prio, inst) - ps_background(file, prio, inst); - FOR_INSTS_UP(prio, inst) - ps_foreground(file, prio, inst); + FOR_INST_PRIOS_UP(prio) { + FOR_GLOBAL_INSTS(prio, inst) + ps_background(file, prio, inst); + FOR_PKG_INSTS(prio, inst) + ps_background(file, prio, inst); + } + FOR_INST_PRIOS_UP(prio) { + FOR_GLOBAL_INSTS(prio, inst) + ps_foreground(file, prio, inst); + FOR_PKG_INSTS(prio, inst) + ps_foreground(file, prio, inst); + } fprintf(file, "showpage\n"); fprintf(file, "%%%%EOF\n"); diff --git a/util.h b/util.h index 173b38f..feb1e59 100644 --- a/util.h +++ b/util.h @@ -27,6 +27,11 @@ #define alloc_type(t) ((t *) alloc_size(sizeof(t))) +#define zalloc_size(s) \ + ({ void *zalloc_size_tmp = alloc_size(s); \ + memset(zalloc_size_tmp, 0, (s)); \ + zalloc_size_tmp; }) + #define zalloc_type(t) \ ({ t *zalloc_type_tmp = alloc_type(t); \ memset(zalloc_type_tmp, 0, sizeof(t)); \