diff --git a/expr.c b/expr.c index abdd236..19aca0c 100644 --- a/expr.c +++ b/expr.c @@ -1,8 +1,8 @@ /* * expr.c - Expressions and values * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,39 +41,35 @@ void fail_expr(const struct expr *expr) /* ----- unit conversion --------------------------------------------------- */ +/* + * If an expression contains a typo, we may get large exponents. Thus, we just + * "sprintf" in order to be able to handle any integer. Since the number of + * different exponents in a session will still be small, we use "unique" to + * give us a constant string, so that we don't have to worry about memory + * allocation. + */ + const char *str_unit(struct num n) { + const char *unit; + char buf[20]; /* @@@ plenty */ + if (n.exponent == 0) - return ""; - if (n.type == nt_mm) { - switch (n.exponent) { - case -2: - return "mm^-2"; - case -1: - return "mm^-1"; - case 1: - return "mm"; - case 2: - return "mm^2"; - default: - abort(); - } + return stralloc(""); + switch (n.type) { + case nt_mm: + unit = "mm"; + break; + case nt_mil: + unit = "mil"; + break; + default: + abort(); } - if (n.type == nt_mil) { - switch (n.exponent) { - case -2: - return "mil^(-2)"; - case -1: - return "mil^(-1)"; - case 1: - return "mil"; - case 2: - return "mil^2"; - default: - abort(); - } - } - abort(); + if (n.exponent == 1) + return unit; + sprintf(buf, "%s^%d", unit, n.exponent); + return unique(buf); } @@ -115,6 +111,14 @@ struct num op_num(const struct expr *self, const struct frame *frame) } +/* + * We have two modes of operation: during instantiation and editing, after + * instantiation. During instantiation, we follow curr_row and curr_parent. + * These pointers are NULL when instantiation finishes, and we use this as a + * signal that we're now in editing mode. In editing mode, the "active" values + * are used instead of the "current" ones. + */ + struct num eval_var(const struct frame *frame, const char *name) { const struct table *table; @@ -124,7 +128,8 @@ struct num eval_var(const struct frame *frame, const char *name) struct num res; for (table = frame->tables; table; table = table->next) { - value = table->curr_row->values; + value = table->curr_row ? table->curr_row->values : + table->active_row->values; for (var = table->vars; var; var = var->next) { if (var->name == name) { if (var->visited) { @@ -143,6 +148,8 @@ struct num eval_var(const struct frame *frame, const char *name) } for (loop = frame->loops; loop; loop = loop->next) if (loop->var.name == name) { + if (loop->curr_value == UNDEF) + return make_num(loop->n+loop->active); if (!loop->initialized) { fail("uninitialized loop \"%s\"", name); return undef; @@ -151,6 +158,8 @@ struct num eval_var(const struct frame *frame, const char *name) } if (frame->curr_parent) return eval_var(frame->curr_parent, name); + if (frame->active_ref) + return eval_var(frame->active_ref->frame, name); return undef; } @@ -164,7 +173,8 @@ static const char *eval_string_var(const struct frame *frame, const char *name) const char *res; for (table = frame->tables; table; table = table->next) { - value = table->curr_row->values; + value = table->curr_row ? table->curr_row->values : + table->active_row->values; for (var = table->vars; var; var = var->next) { if (var->name == name) { if (var->visited) @@ -183,6 +193,8 @@ static const char *eval_string_var(const struct frame *frame, const char *name) return NULL; if (frame->curr_parent) return eval_string_var(frame->curr_parent, name); + if (frame->active_ref) + return eval_string_var(frame->active_ref->frame, name); return NULL; } diff --git a/gui_frame.c b/gui_frame.c index aeaecef..ca8ead6 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -535,6 +535,39 @@ static void unselect_var(void *data) } +static void show_value(const struct expr *expr, const struct frame *frame) +{ + const char *value_string; + struct num value; + + status_set_type_x(NULL, "value ="); + value_string = eval_str(expr, frame); + if (value_string) + status_set_x(NULL, "\"%s\"", value_string); + else { + value = eval_num(expr, frame); + if (is_undef(value)) + status_set_x(NULL, "undefined"); + else + status_set_x(NULL, "%lg%s", value.n, str_unit(value)); + } +} + + +static void show_var_value(const struct var *var, const struct frame *frame) +{ + const struct var *walk; + const struct value *value; + + if (!var->table) + return; + value = var->table->active_row->values; + for (walk = var->table->vars; walk != var; walk = walk->next) + value = value->next; + show_value(value->expr, frame); +} + + static void edit_var(struct var *var, void (*set_values)(void *user, const struct value *values, int n_values), void *user, int max_values) @@ -543,6 +576,7 @@ static void edit_var(struct var *var, label_in_box_bg(var->widget, COLOR_VAR_EDITING); status_set_type_entry(NULL, "name ="); status_set_name("Variable name", "%s", var->name); + show_var_value(var, var->frame); edit_nothing(); edit_unique_with_values(&var->name, validate_var_name, var, set_values, user, max_values, @@ -575,21 +609,23 @@ static void unselect_value(void *data) } -static void edit_value(struct value *value) +static void edit_value(struct value *value, const struct frame *frame) { inst_select_outside(value, unselect_value); label_in_box_bg(value->widget, COLOR_EXPR_EDITING); + show_value(value->expr, frame); edit_nothing(); edit_expr(&value->expr, "Value"); } -static void edit_value_list(struct value *value, +static void edit_value_list(struct value *value, const struct frame *frame, void (*set_values)(void *user, const struct value *values, int n_values), void *user) { inst_select_outside(value, unselect_value); label_in_box_bg(value->widget, COLOR_VAR_EDITING); + show_value(value->expr, frame); edit_nothing(); edit_expr_list(value->expr, set_values, user, "Value(s)"); } @@ -674,7 +710,7 @@ static gboolean assignment_value_select_event(GtkWidget *widget, switch (event->button) { case 1: edit_nothing(); - edit_value(value); + edit_value(value, value->row->table->vars->frame); break; } return TRUE; @@ -797,7 +833,8 @@ static gboolean table_value_select_event(GtkWidget *widget, if (!value->row || value->row->table->active_row == value->row) { edit_nothing(); - edit_value_list(value, set_row_values, value); + edit_value_list(value, value->row->table->vars->frame, + set_row_values, value); } else { select_row(value->row); change_world(); @@ -969,7 +1006,7 @@ static gboolean loop_from_select_event(GtkWidget *widget, switch (event->button) { case 1: edit_nothing(); - edit_value(&loop->from); + edit_value(&loop->from, loop->var.frame); break; } return TRUE; @@ -984,7 +1021,7 @@ static gboolean loop_to_select_event(GtkWidget *widget, switch (event->button) { case 1: edit_nothing(); - edit_value(&loop->to); + edit_value(&loop->to, loop->var.frame); break; } return TRUE; diff --git a/obj.c b/obj.c index abc70ff..88514f1 100644 --- a/obj.c +++ b/obj.c @@ -1,8 +1,8 @@ /* * obj.c - Object definition model * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -239,6 +239,7 @@ static int run_loops(struct frame *frame, struct loop *loop, n++; } loop->initialized = 0; + loop->curr_value = UNDEF; if (active) { loop->n = from.n; loop->iterations = n; @@ -279,6 +280,7 @@ static int generate_frame(struct frame *frame, struct coord base, frame->curr_parent = parent; ok = iterate_tables(frame, frame->tables, base, active); inst_end_frame(frame); + frame->curr_parent = NULL; return ok; }