From edd64aa1323740eb4047836bfed88266d622fa79 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch 
Date: Sat, 8 Jan 2011 12:09:45 +0100
Subject: Read terminals from Lua scripts and export them.
Also add a missing part of LdSymbol API.
---
 src/ld-lua-symbol-private.h |  2 ++
 src/ld-lua-symbol.c         | 16 ++++++++++++
 src/ld-lua.c                | 59 +++++++++++++++++++++++++++++++++++++++++++--
 src/ld-symbol.c             | 36 ++++++++++++++++++++++++++-
 src/ld-symbol.h             |  7 +++---
 5 files changed, 113 insertions(+), 7 deletions(-)
(limited to 'src')
diff --git a/src/ld-lua-symbol-private.h b/src/ld-lua-symbol-private.h
index 0e8800e..83bc646 100644
--- a/src/ld-lua-symbol-private.h
+++ b/src/ld-lua-symbol-private.h
@@ -22,6 +22,7 @@ G_BEGIN_DECLS
  * @name: Name of this symbol.
  * @human_name: Localized human name of this symbol.
  * @area: Area of this symbol.
+ * @terminals: Terminals of this symbol.
  */
 struct _LdLuaSymbolPrivate
 {
@@ -29,6 +30,7 @@ struct _LdLuaSymbolPrivate
 	gchar *name;
 	gchar *human_name;
 	LdRectangle area;
+	LdPointArray *terminals;
 };
 
 
diff --git a/src/ld-lua-symbol.c b/src/ld-lua-symbol.c
index a481cff..955bd97 100644
--- a/src/ld-lua-symbol.c
+++ b/src/ld-lua-symbol.c
@@ -37,6 +37,7 @@ static void ld_lua_symbol_finalize (GObject *gobject);
 static const gchar *ld_lua_symbol_real_get_name (LdSymbol *symbol);
 static const gchar *ld_lua_symbol_real_get_human_name (LdSymbol *symbol);
 static void ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area);
+static const LdPointArray *ld_lua_symbol_real_get_terminals (LdSymbol *symbol);
 static void ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr);
 
 
@@ -53,6 +54,7 @@ ld_lua_symbol_class_init (LdLuaSymbolClass *klass)
 	klass->parent_class.get_name = ld_lua_symbol_real_get_name;
 	klass->parent_class.get_human_name = ld_lua_symbol_real_get_human_name;
 	klass->parent_class.get_area = ld_lua_symbol_real_get_area;
+	klass->parent_class.get_terminals = ld_lua_symbol_real_get_terminals;
 	klass->parent_class.draw = ld_lua_symbol_real_draw;
 
 	g_type_class_add_private (klass, sizeof (LdLuaSymbolPrivate));
@@ -83,6 +85,9 @@ ld_lua_symbol_finalize (GObject *gobject)
 	if (self->priv->human_name)
 		g_free (self->priv->human_name);
 
+	if (self->priv->terminals)
+		ld_point_array_free (self->priv->terminals);
+
 	/* Chain up to the parent class. */
 	G_OBJECT_CLASS (ld_lua_symbol_parent_class)->finalize (gobject);
 }
@@ -114,6 +119,17 @@ ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area)
 	*area = self->priv->area;
 }
 
+static const LdPointArray *
+ld_lua_symbol_real_get_terminals (LdSymbol *symbol)
+{
+	LdLuaSymbol *self;
+
+	g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
+
+	self = LD_LUA_SYMBOL (symbol);
+	return self->priv->terminals;
+}
+
 static void
 ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr)
 {
diff --git a/src/ld-lua.c b/src/ld-lua.c
index 746d2f9..47f2a40 100644
--- a/src/ld-lua.c
+++ b/src/ld-lua.c
@@ -92,6 +92,8 @@ static int ld_lua_logdiag_register (lua_State *L);
 static int process_registration (lua_State *L);
 static gchar *get_translation (lua_State *L, int index);
 static gboolean read_symbol_area (lua_State *L, int index, LdRectangle *area);
+static gboolean read_terminals (lua_State *L, int index,
+	LdPointArray **terminals);
 
 static void push_cairo_object (lua_State *L, LdLuaDrawData *draw_data);
 static gdouble get_cairo_scale (cairo_t *cr);
@@ -474,8 +476,8 @@ process_registration (lua_State *L)
 
 	if (!read_symbol_area (L, 3, &symbol->priv->area))
 		return luaL_error (L, "Malformed symbol area array.");
-
-	/* TODO: Read and set the terminals. */
+	if (!read_terminals (L, 4, &symbol->priv->terminals))
+		return luaL_error (L, "Malformed terminals array.");
 
 	lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
 	lua_pushlightuserdata (L, symbol);
@@ -561,9 +563,62 @@ read_symbol_area (lua_State *L, int index, LdRectangle *area)
 	area->width = ABS (x2 - x1);
 	area->height = ABS (y2 - y1);
 
+	lua_pop (L, 4);
+	return TRUE;
+}
+
+/*
+ * read_terminals:
+ * @L: A Lua state.
+ * @index: Stack index of the table.
+ * @area: Where the point array will be returned.
+ *
+ * Read symbol terminals from a Lua table.
+ *
+ * Return value: TRUE on success, FALSE on failure.
+ */
+static gboolean
+read_terminals (lua_State *L, int index, LdPointArray **terminals)
+{
+	LdPointArray *points;
+	size_t num_points;
+	unsigned i = 0;
+
+	num_points = lua_objlen (L, index);
+	points = ld_point_array_new (num_points);
+
+	lua_pushnil (L);
+	while (lua_next (L, index) != 0)
+	{
+		g_assert (i < num_points);
+
+		if (!lua_istable (L, -1) || lua_objlen (L, -1) != 2)
+			goto read_terminals_fail;
+
+		lua_rawgeti (L, -1, 1);
+		if (!lua_isnumber (L, -1))
+			goto read_terminals_fail;
+		points->points[i].x = lua_tonumber (L, -1);
+		lua_pop (L, 1);
+
+		lua_rawgeti (L, -1, 2);
+		if (!lua_isnumber (L, -1))
+			goto read_terminals_fail;
+		points->points[i].y = lua_tonumber (L, -1);
+
+		lua_pop (L, 2);
+		i++;
+	}
+	*terminals = points;
 	return TRUE;
+
+read_terminals_fail:
+	ld_point_array_free (points);
+	*terminals = NULL;
+	return FALSE;
 }
 
+
 /* ===== Cairo ============================================================= */
 
 static void
diff --git a/src/ld-symbol.c b/src/ld-symbol.c
index 24a7ab9..cdc59f5 100644
--- a/src/ld-symbol.c
+++ b/src/ld-symbol.c
@@ -35,7 +35,8 @@ enum
 	PROP_0,
 	PROP_NAME,
 	PROP_HUMAN_NAME,
-	PROP_AREA
+	PROP_AREA,
+	PROP_TERMINALS
 };
 
 static void ld_symbol_get_property (GObject *object, guint property_id,
@@ -85,6 +86,16 @@ ld_symbol_class_init (LdSymbolClass *klass)
 		"The area of this symbol.",
 		LD_TYPE_RECTANGLE, G_PARAM_READABLE);
 	g_object_class_install_property (object_class, PROP_AREA, pspec);
+
+/**
+ * LdSymbol:terminals:
+ *
+ * A point array that specifies terminals of this symbol.
+ */
+	pspec = g_param_spec_boxed ("terminals", "Terminals",
+		"A point array that specifies terminals of this symbol.",
+		LD_TYPE_POINT_ARRAY, G_PARAM_READABLE);
+	g_object_class_install_property (object_class, PROP_TERMINALS, pspec);
 }
 
 static void
@@ -115,6 +126,9 @@ ld_symbol_get_property (GObject *object, guint property_id,
 			g_value_set_boxed (value, &area);
 		}
 		break;
+	case PROP_TERMINALS:
+		g_value_set_boxed (value, ld_symbol_get_terminals (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -184,6 +198,26 @@ ld_symbol_get_area (LdSymbol *self, LdRectangle *area)
 	klass->get_area (self, area);
 }
 
+/**
+ * ld_symbol_get_terminals:
+ * @self: A symbol object.
+ *
+ * Get a list of symbol terminals.
+ *
+ * Return value: An #LdPointArray structure.
+ */
+const LdPointArray *
+ld_symbol_get_terminals (LdSymbol *self)
+{
+	LdSymbolClass *klass;
+
+	g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
+
+	klass = LD_SYMBOL_GET_CLASS (self);
+	g_return_val_if_fail (klass->get_terminals != NULL, NULL);
+	return klass->get_terminals (self);
+}
+
 /**
  * ld_symbol_draw:
  * @self: A symbol object.
diff --git a/src/ld-symbol.h b/src/ld-symbol.h
index 43ab4df..409eba5 100644
--- a/src/ld-symbol.h
+++ b/src/ld-symbol.h
@@ -44,6 +44,7 @@ struct _LdSymbol
  * @get_name: Get the name of the symbol.
  * @get_human_name: Get the localized human name of the symbol.
  * @get_area: Get the area of the symbol.
+ * @get_terminals: Get a list of symbol terminals.
  * @draw: Draw the symbol on a Cairo surface.
  */
 struct _LdSymbolClass
@@ -53,6 +54,7 @@ struct _LdSymbolClass
 	const gchar *(*get_name) (LdSymbol *self);
 	const gchar *(*get_human_name) (LdSymbol *self);
 	void (*get_area) (LdSymbol *self, LdRectangle *area);
+	const LdPointArray *(*get_terminals) (LdSymbol *self);
 	void (*draw) (LdSymbol *self, cairo_t *cr);
 };
 
@@ -62,12 +64,9 @@ GType ld_symbol_get_type (void) G_GNUC_CONST;
 const gchar *ld_symbol_get_name (LdSymbol *self);
 const gchar *ld_symbol_get_human_name (LdSymbol *self);
 void ld_symbol_get_area (LdSymbol *self, LdRectangle *area);
+const LdPointArray *ld_symbol_get_terminals (LdSymbol *self);
 void ld_symbol_draw (LdSymbol *self, cairo_t *cr);
 
-/* TODO: Interface for terminals.
- *       Something like a list of gdouble pairs (-> a new structure).
- */
-
 
 G_END_DECLS
 
-- 
cgit v1.2.3-70-g09d2