diff --git a/expr.c b/expr.c index f81ce1a..f9a6333 100644 --- a/expr.c +++ b/expr.c @@ -483,7 +483,7 @@ void free_expr(struct expr *expr) } -/* ----- var = value, ... shortcut ----------------------------------------- */ +/* ----- [var =] value, ... shortcuts -------------------------------------- */ int parse_var(const char *s, const char **id, struct value **values, @@ -497,8 +497,7 @@ int parse_var(const char *s, const char **id, struct value **values, return -1; if (id) *id = var_id; - if (values) - *values = var_value_list; + *values = var_value_list; n = 0; for (value = var_value_list; value; value = value->next) n++; @@ -509,6 +508,22 @@ int parse_var(const char *s, const char **id, struct value **values, } +int parse_values(const char *s, struct value **values) +{ + const struct value *value; + int n; + + scan_values(s); + if (yyparse()) + return -1; + *values = var_value_list; + n = 0; + for (value = var_value_list; value; value = value->next) + n++; + return n; +} + + void free_values(struct value *values, int keep_expr) { struct value *next; diff --git a/expr.h b/expr.h index a8a704c..f40b95d 100644 --- a/expr.h +++ b/expr.h @@ -140,6 +140,7 @@ void free_expr(struct expr *expr); int parse_var(const char *s, const char **id, struct value **values, int max_values); +int parse_values(const char *s, struct value **values); void free_values(struct value *values, int keep_expr); #endif /* !EXPR_H */ diff --git a/fpd.h b/fpd.h index c2c7a87..74f61c7 100644 --- a/fpd.h +++ b/fpd.h @@ -26,6 +26,7 @@ extern struct value *var_value_list; void scan_empty(void); void scan_expr(const char *s); void scan_var(const char *s); +void scan_values(const char *s); int yyparse(void); diff --git a/fpd.l b/fpd.l index e6d4857..edfd6d0 100644 --- a/fpd.l +++ b/fpd.l @@ -49,6 +49,13 @@ void scan_var(const char *s) yy_scan_string(s); } + +void scan_values(const char *s) +{ + start_token = START_VALUES; + yy_scan_string(s); +} + %} diff --git a/fpd.y b/fpd.y index b55f9ea..0464c9b 100644 --- a/fpd.y +++ b/fpd.y @@ -153,7 +153,7 @@ static struct obj *new_obj(enum obj_type type) }; -%token START_FPD START_EXPR START_VAR +%token START_FPD START_EXPR START_VAR START_VALUES %token TOK_SET TOK_LOOP TOK_PART 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 @@ -199,6 +199,10 @@ all: var_id = $2; var_value_list = $3; } + | START_VALUES row + { + var_value_list = $2; + } ; fpd: diff --git a/gui_frame.c b/gui_frame.c index 079ad06..7722774 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -523,6 +523,17 @@ static void edit_value(struct value *value) } +static void edit_value_list(struct value *value, + 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); + edit_nothing(); + edit_expr_list(value->expr, set_values, user); +} + + /* ----- activator --------------------------------------------------------- */ @@ -569,6 +580,7 @@ static void set_col_values(void *user, const struct value *values, value = (*row)->values; for (walk = table->vars; walk != var; walk = walk->next) value = value->next; + free_expr(value->expr); value->expr = values->expr; values = values->next; row = &(*row)->next; @@ -661,6 +673,35 @@ static void select_row(struct row *row) } +static void set_row_values(void *user, const struct value *values, + int n_values) +{ + struct value *value = user; + struct row *row = value->row; + struct table *table = row->table; + struct var **var; + const struct value *walk; + int first = 1; + + var = &table->vars; + for (walk = row->values; walk != value; walk = walk->next) + var = &(*var)->next; + + while (values) { + if (!*var) + add_column_here(table, var); + if (first) + first = 0; + else + value = value->next; + free_expr(value->expr); + value->expr = values->expr; + values = values->next; + var = &(*var)->next; + } +} + + static gboolean table_var_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -688,7 +729,7 @@ static gboolean table_value_select_event(GtkWidget *widget, if (!value->row || value->row->table->active_row == value->row) { edit_nothing(); - edit_value(value); + edit_value_list(value, set_row_values, value); } else { select_row(value->row); change_world(); diff --git a/gui_status.c b/gui_status.c index 016cbeb..9ce94f5 100644 --- a/gui_status.c +++ b/gui_status.c @@ -360,14 +360,16 @@ static enum edit_status unique_with_values_status(const char *s, void *ctx) { const struct edit_unique_with_values_ctx *unique_ctx = ctx; const char *id; + struct value *values; int n; if (!strcmp(s, *unique_ctx->s)) return es_unchanged; status_begin_reporting(); - n = parse_var(s, &id, NULL, unique_ctx->max_values); + n = parse_var(s, &id, &values, unique_ctx->max_values); if (n < 0) return es_bad; + free_values(values, 0); return !unique_ctx->validate || unique_ctx->validate(id, unique_ctx->ctx) ? es_good : es_bad; } @@ -544,6 +546,73 @@ void edit_y(struct expr **expr) } +/* ----- expression list --------------------------------------------------- */ + + +struct edit_expr_list_ctx { + struct expr *expr; + void (*set_values)(void *user, const struct value *values, + int n_values); + void *user; +}; + + +static char *expr_list_retrieve(void *ctx) +{ + struct edit_expr_list_ctx *expr_list_ctx = ctx; + + return unparse(expr_list_ctx->expr); +} + + +static enum edit_status expr_list_status(const char *s, void *ctx) +{ + struct value *values; + int n; + + status_begin_reporting(); + n = parse_values(s, &values); + if (n < 0) + return es_bad; + free_values(values, 0); + return es_good; +} + + +static void expr_list_store(const char *s, void *ctx) +{ + struct edit_expr_list_ctx *expr_list_ctx = ctx; + struct value *values; + int n; + + status_begin_reporting(); + n = parse_values(s, &values); + assert(n >= 0); + expr_list_ctx->set_values(expr_list_ctx->user, values, n); + free_values(values, 1); +} + + +static struct edit_ops edit_ops_expr_list = { + .retrieve = expr_list_retrieve, + .status = expr_list_status, + .store = expr_list_store, +}; + + +void edit_expr_list(struct expr *expr, + void (*set_values)(void *user, const struct value *values, int n_values), + void *user) +{ + static struct edit_expr_list_ctx expr_list_ctx; + + expr_list_ctx.expr = expr; + expr_list_ctx.set_values = set_values; + expr_list_ctx.user = user; + setup_edit(status_entry, &edit_ops_expr_list, &expr_list_ctx); +} + + /* ----- text entry -------------------------------------------------------- */ diff --git a/gui_status.h b/gui_status.h index bffb218..325cd38 100644 --- a/gui_status.h +++ b/gui_status.h @@ -30,6 +30,9 @@ void edit_unique_with_values(const char **s, void *user, int max_values); void edit_name(char **s, int (*validate)(const char *s, void *ctx), void *ctx); void edit_expr(struct expr **expr); +void edit_expr_list(struct expr *expr, + void (*set_values)(void *user, const struct value *values, int n_values), + void *user); void edit_x(struct expr **expr); void edit_y(struct expr **expr); void edit_nothing(void);