r5351 - developers/werner/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Fri Jul 31 17:52:32 CEST 2009


Author: werner
Date: 2009-07-31 17:52:32 +0200 (Fri, 31 Jul 2009)
New Revision: 5351

Modified:
   developers/werner/fped/expr.c
   developers/werner/fped/expr.h
   developers/werner/fped/gui.c
   developers/werner/fped/gui.h
   developers/werner/fped/gui_status.c
   developers/werner/fped/gui_status.h
   developers/werner/fped/gui_style.h
   developers/werner/fped/inst.c
   developers/werner/fped/obj.c
   developers/werner/fped/obj.h
Log:
- added infrastructure for editing values
- added editing of pad names
- moved "expand" from obj.c to expr.c and added syntax-check mode 
- "expand": reject $ not followed by identifier character or {



Modified: developers/werner/fped/expr.c
===================================================================
--- developers/werner/fped/expr.c	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/expr.c	2009-07-31 15:52:32 UTC (rev 5351)
@@ -257,6 +257,9 @@
 }
 
 
+/* ----- expression construction ------------------------------------------- */
+
+
 struct expr *new_op(op_type op)
 {
 	struct expr *expr;
@@ -289,3 +292,121 @@
 {
 	return expr->op(expr, frame);
 }
+
+
+/* ----- string expansion -------------------------------------------------- */
+
+
+static int is_id(char c, int first)
+{
+	if ((c >= 'A' && c <= 'Z') ||
+	    (c >= 'a' && c <= 'z') ||
+	    c == '_')
+		return 1;
+	if (first)
+		return 0;
+	return c >= '0' && c <= '9';
+}
+
+
+char *expand(const char *name, const struct frame *frame)
+{
+	int len = strlen(name);
+	char *buf = alloc_size(len+1);
+	char num_buf[100]; /* enough :-) */
+	const char *s, *s0;
+	char *var;
+	const char *var_unique;
+	struct num value;
+	int i, value_len;
+
+	i = 0;
+	for (s = name; *s; s++) {
+		if (*s != '$') {
+			buf[i++] = *s;
+			continue;
+		}
+		s0 = ++s;
+		if (*s != '{') {
+			while (is_id(*s, s == s0))
+				s++;
+			if (s == s0)
+				goto invalid;
+			var = strnalloc(s0, s-s0);
+			len -= s-s0+1;
+			s--;
+		} else {
+			s++;
+			while (*s != '}') {
+				if (!*s) {
+					fail("unfinished \"${...}\"");
+					goto fail;
+				}
+				if (!is_id(*s, s == s0+1))
+					goto invalid;
+				s++;
+			}
+			var = strnalloc(s0+1, s-s0-1);
+			len -= s-s0+2;
+		}
+		if (!frame)
+			continue;
+		var_unique = unique(var);
+		free(var);
+		value = eval_var(frame, var_unique);
+		if (is_undef(value)) {
+			fail("undefined variable \"%s\"", var_unique);
+			goto fail;
+		}
+		value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
+		    value.n, str_unit(value));
+		len += value_len;
+		buf = realloc(buf, len);
+		if (!buf)
+			abort();
+		strcpy(buf+i, num_buf);
+		i += value_len;
+	}
+	buf[i] = 0;
+	return buf;
+
+invalid:
+	fail("invalid character in variable name");
+fail:
+	free(buf);
+	return NULL;
+}
+
+
+/* ----- expression-only parser -------------------------------------------- */
+
+
+struct expr *parse_expr(const char *s)
+{
+	return NULL;
+}
+
+
+static void vacate_op(struct expr *expr)
+{
+	if (expr->op == &op_num || expr->op == &op_var)
+		return;
+	if (expr->op == &op_minus) {
+		free_expr(expr->u.op.a);
+		return;
+	}
+	if (expr->op == &op_add || expr->op == &op_sub ||
+	    expr->op == &op_mult || expr->op == &op_div) {
+		free_expr(expr->u.op.a);
+		free_expr(expr->u.op.b);
+		return;
+	}
+	abort();
+}
+
+
+void free_expr(struct expr *expr)
+{
+	vacate_op(expr);
+	free(expr);
+}

Modified: developers/werner/fped/expr.h
===================================================================
--- developers/werner/fped/expr.h	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/expr.h	2009-07-31 15:52:32 UTC (rev 5351)
@@ -98,4 +98,10 @@
 char *eval_str(const struct frame *frame, const struct expr *expr);
 struct num eval_num(const struct expr *expr, const struct frame *frame);
 
+/* if frame == NULL, we only check the syntax without expanding */
+char *expand(const char *name, const struct frame *frame);
+
+struct expr *parse_expr(const char *s);
+void free_expr(struct expr *expr);
+
 #endif /* !EXPR_H */

Modified: developers/werner/fped/gui.c
===================================================================
--- developers/werner/fped/gui.c	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/gui.c	2009-07-31 15:52:32 UTC (rev 5351)
@@ -193,6 +193,15 @@
 /* ----- frame list -------------------------------------------------------- */
 
 
+void change_world(void)
+{
+	instantiate();
+	label_in_box_bg(active_frame->label, "pink");
+	build_vars(vars_box, active_frame);
+	redraw();
+}
+
+
 static void select_frame(struct frame *frame)
 {
 	if (active_frame) {
@@ -200,10 +209,7 @@
 		inst_deselect();
 	}
 	active_frame = frame;
-	instantiate();
-	label_in_box_bg(active_frame->label, "pink");
-	build_vars(vars_box, active_frame);
-	redraw();
+	change_world();
 }
 
 
@@ -327,6 +333,7 @@
 
 	gui_setup_style(root->window);
 	init_canvas();
+	edit_nothing();
 	select_frame(root_frame);
 
 	gtk_main();

Modified: developers/werner/fped/gui.h
===================================================================
--- developers/werner/fped/gui.h	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/gui.h	2009-07-31 15:52:32 UTC (rev 5351)
@@ -19,6 +19,10 @@
 
 extern GtkWidget *root;
 
+
+/* update everything after a model change */
+void change_world(void);
+
 int gui_init(int *argc, char ***argv);
 int gui_main(int argc, char **argv);
 

Modified: developers/werner/fped/gui_status.c
===================================================================
--- developers/werner/fped/gui_status.c	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/gui_status.c	2009-07-31 15:52:32 UTC (rev 5351)
@@ -12,14 +12,32 @@
 
 
 #include <stdarg.h>
+#include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <gtk/gtk.h>
 
+#include "util.h"
 #include "coord.h"
+#include "unparse.h"
 #include "gui_util.h"
+#include "gui_style.h"
+#include "gui.h"
 #include "gui_status.h"
 
 
+struct edit_ops {
+	int (*changed)(GtkWidget *widget, const char *s, void *ctx);
+	int (*activate)(GtkWidget *widget, const char *s, void *ctx);
+};
+
+static struct edit_ops *edit_ops = NULL;
+static void *edit_ctx;
+
+
+/* ----- setter functions -------------------------------------------------- */
+
+
 static GtkWidget *status_name, *status_entry;
 static GtkWidget *status_x, *status_y;
 static GtkWidget *status_r, *status_angle;
@@ -68,6 +86,160 @@
 }
 
 
+static void entry_color(const char *color)
+{
+	GdkColor col;
+
+	col = get_color(color);
+	gtk_widget_modify_base(GTK_WIDGET(status_entry), GTK_STATE_NORMAL, &col);
+}
+
+
+/* ----- string fields ----------------------------------------------------- */
+
+
+struct edit_name_ctx {
+	char **s;
+	int (*validate)(const char *s, void *ctx);
+	void *ctx;
+};
+
+
+static int name_changed(GtkWidget *widget, const char *s, void *ctx)
+{
+	const struct edit_name_ctx *name_ctx = ctx;
+	int ok;
+
+	if (!strcmp(s, *name_ctx->s)) {
+		entry_color(COLOR_EDIT_ASIS);
+		return 1;
+	}
+	ok = !name_ctx->validate || name_ctx->validate(s, name_ctx->ctx);
+	entry_color(ok ? COLOR_EDIT_GOOD : COLOR_EDIT_BAD);
+	return ok;
+}
+
+
+static int name_activate(GtkWidget *widget, const char *s, void *ctx)
+{
+	const struct edit_name_ctx *name_ctx = ctx;
+
+	if (name_ctx->validate && !name_ctx->validate(s, name_ctx->ctx))
+		return 0;
+	free(*name_ctx->s);
+	*name_ctx->s = stralloc(s);
+	entry_color(COLOR_EDIT_ASIS);
+	return 1;
+}
+
+
+static struct edit_ops edit_ops_name = {
+	.changed	= name_changed,
+	.activate	= name_activate,
+};
+
+
+void edit_name(char **s, int (*validate)(const char *s, void *ctx), void *ctx)
+{
+	static struct edit_name_ctx name_ctx;
+
+	name_ctx.s = s;
+	name_ctx.validate = validate;
+	name_ctx.ctx = ctx;
+	edit_ops = &edit_ops_name;
+	edit_ctx = &name_ctx;
+	gtk_entry_set_text(GTK_ENTRY(status_entry), *s);
+	entry_color(COLOR_EDIT_ASIS);
+	gtk_widget_show(status_entry);
+}
+
+
+/* ----- expression fields ------------------------------------------------- */
+
+
+static int expr_changed(GtkWidget *widget, const char *s, void *ctx)
+{
+	struct expr *expr;
+
+	expr = parse_expr(s);
+	if (!expr) {
+		entry_color(COLOR_EDIT_BAD);
+		return 0;
+	}
+	entry_color(COLOR_EDIT_BAD);
+	free_expr(expr);
+	return 1;
+}
+
+
+static int expr_activate(GtkWidget *widget, const char *s, void *ctx)
+{
+	struct expr **anchor = ctx;
+	struct expr *expr;
+
+	expr = parse_expr(s);
+	if (!expr)
+		return 0;
+	free_expr(*anchor);
+	*anchor = expr;
+	entry_color(COLOR_EDIT_ASIS);
+	return 1;
+}
+
+
+static struct edit_ops edit_ops_expr = {
+	.changed	= expr_changed,
+	.activate	= expr_activate,
+};
+
+
+void edit_expression(struct expr **expr)
+{
+	char *s;
+
+	edit_ops = &edit_ops_expr;
+	edit_ctx = expr;
+	s = unparse(*expr);
+	gtk_entry_set_text(GTK_ENTRY(status_entry), s);
+	free(s);
+	entry_color(COLOR_EDIT_ASIS);
+	gtk_widget_show(status_entry);
+}
+
+
+/* ----- text entry -------------------------------------------------------- */
+
+
+static gboolean changed(GtkWidget *widget, GdkEventMotion *event,
+     gpointer data)
+{
+	if (edit_ops && edit_ops->changed)
+		edit_ops->changed(widget,
+		    gtk_entry_get_text(GTK_ENTRY(widget)), edit_ctx);
+	return TRUE;
+}
+
+
+static gboolean activate(GtkWidget *widget, GdkEventMotion *event,
+     gpointer data)
+{
+	if (edit_ops && edit_ops->activate)
+		if (edit_ops->activate(widget,
+		    gtk_entry_get_text(GTK_ENTRY(widget)), edit_ctx)) {
+			inst_deselect();
+			change_world();
+		}
+	return TRUE;
+}
+
+
+void edit_nothing(void)
+{
+	edit_ops = NULL;
+	gtk_widget_hide(status_entry);
+}
+
+
 /* ----- setup ------------------------------------------------------------- */
 
 
@@ -106,6 +278,13 @@
 	status_entry = gtk_entry_new();
 	gtk_box_pack_start(GTK_BOX(hbox), status_entry, TRUE, TRUE, 0);
 
+	gtk_entry_set_has_frame(GTK_ENTRY(status_entry), FALSE);
+
+	g_signal_connect(G_OBJECT(status_entry), "changed",
+            G_CALLBACK(changed), status_entry);
+	g_signal_connect(G_OBJECT(status_entry), "activate",
+            G_CALLBACK(activate), status_entry);
+
 	/* x / y */
 
 	status_x = add_label(tab, 1, 0);

Modified: developers/werner/fped/gui_status.h
===================================================================
--- developers/werner/fped/gui_status.h	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/gui_status.h	2009-07-31 15:52:32 UTC (rev 5351)
@@ -14,10 +14,15 @@
 #ifndef GUI_STATUS_H
 #define GUI_STATUS_H
 
+#include <gtk/gtk.h>
+
 #include "coord.h"
+#include "expr.h"
 
-#include <gtk/gtk.h>
 
+void edit_name(char **s, int (*validate)(const char *s, void *ctx), void *ctx);
+void edit_expression(struct expr **expr);
+void edit_nothing(void);
 
 void status_set_name(const char *fmt, ...);
 void status_set_x(const char *fmt, ...);

Modified: developers/werner/fped/gui_style.h
===================================================================
--- developers/werner/fped/gui_style.h	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/gui_style.h	2009-07-31 15:52:32 UTC (rev 5351)
@@ -19,6 +19,9 @@
 #include "inst.h"
 
 
+/* ----- screen distances -------------------------------------------------- */
+
+
 #define	CANVAS_CLEARANCE	10
 
 #define	VEC_ARROW_LEN		10
@@ -32,6 +35,17 @@
 #define	SELECT_R		6	/* pixels within which we select */
 
 
+/* ----- assorted colors --------------------------------------------------- */
+
+
+#define COLOR_EDIT_ASIS	"#ffffff"
+#define COLOR_EDIT_GOOD	"#a0ffa0"
+#define COLOR_EDIT_BAD	"#ffa0a0"
+
+
+/* ----- canvas drawing styles --------------------------------------------- */
+
+
 GdkGC *gc_bg;
 GdkGC *gc_vec[mode_n];
 GdkGC *gc_obj[mode_n];

Modified: developers/werner/fped/inst.c
===================================================================
--- developers/werner/fped/inst.c	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/inst.c	2009-07-31 15:52:32 UTC (rev 5351)
@@ -17,6 +17,7 @@
 
 #include "util.h"
 #include "coord.h"
+#include "expr.h"
 #include "obj.h"
 #include "gui_status.h"
 #include "gui_inst.h"
@@ -63,6 +64,7 @@
 	int best_dist, dist;
 
 	selected_inst = NULL;
+	edit_nothing();
 	for (inst = insts; inst; inst = inst->next) {
 		if (!inst->active || !inst->ops->distance)
 			continue;
@@ -91,6 +93,7 @@
 	status_set_r("");
 	status_set_angle("");
 	selected_inst = NULL;
+	edit_nothing();
 }
 
 
@@ -277,10 +280,23 @@
 }
 
 
+static int validate_pad_name(const char *s, void *ctx)
+{
+	char *tmp;
+
+	tmp = expand(s, NULL);
+	if (!tmp)
+		return 0;
+	free(tmp);
+	return 1;
+}
+
+
 static void pad_op_select(struct inst *self)
 {
 	status_set_name(self->u.name);
 	rect_status(self->bbox.min, self->bbox.max);
+	edit_name(&self->obj->u.pad.name, validate_pad_name, NULL);
 }
 
 

Modified: developers/werner/fped/obj.c
===================================================================
--- developers/werner/fped/obj.c	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/obj.c	2009-07-31 15:52:32 UTC (rev 5351)
@@ -33,79 +33,6 @@
     const struct frame *parent, int active);
 
 
-static int is_id(char c, int first)
-{
-	if ((c >= 'A' && c <= 'Z') ||
-	    (c >= 'a' && c <= 'z') ||
-	    c == '_')
-		return 1;
-	if (first)
-		return 0;
-	return c >= '0' && c <= '9';
-}
-
-
-static char *expand(const char *name, const struct frame *frame)
-{
-	int len = strlen(name);
-	char *buf = alloc_size(len+1);
-	char num_buf[100]; /* enough :-) */
-	const char *s, *s0;
-	char *var;
-	const char *var_unique;
-	struct num value;
-	int i, value_len;
-
-	i = 0;
-	for (s = name; *s; s++) {
-		if (*s != '$') {
-			buf[i++] = *s;
-			continue;
-		}
-		s0 = ++s;
-		if (*s != '{') {
-			while (is_id(*s, s == s0))
-				s++;
-			var = strnalloc(s0, s-s0);
-			len -= s-s0+1;
-			s--;
-		} else {
-			s++;
-			while (*s != '}') {
-				if (!is_id(*s, s == s0+1))
-					goto invalid;
-				s++;
-			}
-			var = strnalloc(s0+1, s-s0-1);
-			len -= s-s0+2;
-		}
-		var_unique = unique(var);
-		free(var);
-		value = eval_var(frame, var_unique);
-		if (is_undef(value)) {
-			fail("undefined variable \"%s\"", var_unique);
-			goto fail;
-		}
-		value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
-		    value.n, str_unit(value));
-		len += value_len;
-		buf = realloc(buf, len);
-		if (!buf)
-			abort();
-		strcpy(buf+i, num_buf);
-		i += value_len;
-	}
-	buf[i] = 0;
-	return buf;
-
-invalid:
-	fail("invalid character in variable name");
-fail:
-	free(buf);
-	return NULL;
-}
-
-
 static int generate_vecs(struct frame *frame, struct coord base)
 {
 	struct coord vec_base;

Modified: developers/werner/fped/obj.h
===================================================================
--- developers/werner/fped/obj.h	2009-07-31 09:00:51 UTC (rev 5350)
+++ developers/werner/fped/obj.h	2009-07-31 15:52:32 UTC (rev 5351)
@@ -101,7 +101,7 @@
 };
 
 struct pad {
-	const char *name;
+	char *name;
 	struct vec *other; /* NULL if frame origin */
 };
 




More information about the commitlog mailing list