Finish XML layout engine.
This commit is contained in:
@ -133,7 +133,6 @@ eek_key_real_get_keysyms (EekKey *self,
|
|||||||
if (num_levels)
|
if (num_levels)
|
||||||
*num_levels = priv->keysyms.num_levels;
|
*num_levels = priv->keysyms.num_levels;
|
||||||
if (keysyms && num_keysyms > 0) {
|
if (keysyms && num_keysyms > 0) {
|
||||||
*keysyms = g_slice_alloc (num_keysyms * sizeof(guint));
|
|
||||||
memcpy (*keysyms, priv->keysyms.data, num_keysyms * sizeof(guint));
|
memcpy (*keysyms, priv->keysyms.data, num_keysyms * sizeof(guint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -290,6 +290,19 @@ eek_keyboard_real_key_released (EekKeyboard *self,
|
|||||||
set_level_from_modifiers (self);
|
set_level_from_modifiers (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_keyboard_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
|
||||||
|
|
||||||
|
if (priv->layout) {
|
||||||
|
g_object_unref (priv->layout);
|
||||||
|
priv->layout = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_keyboard_class_init (EekKeyboardClass *klass)
|
eek_keyboard_class_init (EekKeyboardClass *klass)
|
||||||
{
|
{
|
||||||
@ -311,6 +324,7 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
|
|||||||
|
|
||||||
gobject_class->get_property = eek_keyboard_get_property;
|
gobject_class->get_property = eek_keyboard_get_property;
|
||||||
gobject_class->set_property = eek_keyboard_set_property;
|
gobject_class->set_property = eek_keyboard_set_property;
|
||||||
|
gobject_class->dispose = eek_keyboard_dispose;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EekKeyboard:group:
|
* EekKeyboard:group:
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#include "eek-xml-layout.h"
|
#include "eek-xml-layout.h"
|
||||||
#include "eek-keyboard.h"
|
#include "eek-keyboard.h"
|
||||||
#include "eek-section.h"
|
#include "eek-section.h"
|
||||||
|
#include "eek-key.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -27,6 +29,7 @@ G_DEFINE_TYPE (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT);
|
|||||||
struct _EekXmlLayoutPrivate
|
struct _EekXmlLayoutPrivate
|
||||||
{
|
{
|
||||||
GInputStream *source;
|
GInputStream *source;
|
||||||
|
GHashTable *outline_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BUFSIZE 8192
|
#define BUFSIZE 8192
|
||||||
@ -35,43 +38,57 @@ struct _ParseCallbackData {
|
|||||||
GSList *element_stack;
|
GSList *element_stack;
|
||||||
GString *text;
|
GString *text;
|
||||||
EekLayout *layout;
|
EekLayout *layout;
|
||||||
|
|
||||||
EekKeyboard *keyboard;
|
EekKeyboard *keyboard;
|
||||||
EekSection *section;
|
EekSection *section;
|
||||||
EekKey *key;
|
EekKey *key;
|
||||||
|
gint num_columns;
|
||||||
|
EekOrientation orientation;
|
||||||
|
GSList *points;
|
||||||
|
guint keycode;
|
||||||
|
GSList *keysyms;
|
||||||
|
gint groups, levels;
|
||||||
|
EekOutline outline;
|
||||||
|
gchar *oref;
|
||||||
|
GHashTable *key_oref_hash;
|
||||||
|
GHashTable *oref_outline_hash;
|
||||||
};
|
};
|
||||||
typedef struct _ParseCallbackData ParseCallbackData;
|
typedef struct _ParseCallbackData ParseCallbackData;
|
||||||
|
|
||||||
static const gchar *valid_path_list[] = {
|
static const gchar *valid_path_list[] = {
|
||||||
"keyboard",
|
"keyboard",
|
||||||
"keyboard/bounds",
|
"bounds/keyboard",
|
||||||
"keyboard/section",
|
"section/keyboard",
|
||||||
"keyboard/outline",
|
"outline/keyboard",
|
||||||
"section/bounds",
|
"bounds/section/keyboard",
|
||||||
"section/angle",
|
"angle/section/keyboard",
|
||||||
"section/key",
|
"row/section/keyboard",
|
||||||
"bounds/key",
|
"columns/row/section/keyboard",
|
||||||
"outline/key",
|
"orientation/row/section/keyboard",
|
||||||
"keysyms/key",
|
"key/section/keyboard",
|
||||||
"keycode/key",
|
"bounds/key/section/keyboard",
|
||||||
"index/key",
|
"outline-ref/key/section/keyboard",
|
||||||
"groups/keysyms",
|
"keysyms/key/section/keyboard",
|
||||||
"levels/keysyms",
|
"keycode/key/section/keyboard",
|
||||||
"keysym/keysyms",
|
"index/key/section/keyboard",
|
||||||
|
"groups/keysyms/key/section/keyboard",
|
||||||
|
"levels/keysyms/key/section/keyboard",
|
||||||
|
"keysym/keysyms/key/section/keyboard",
|
||||||
"point/outline/keyboard"
|
"point/outline/keyboard"
|
||||||
};
|
};
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
join_element_names (GSList *element_names)
|
strjoin_slist (GSList *slist, const gchar *delimiter)
|
||||||
{
|
{
|
||||||
GString *string = g_string_sized_new (64);
|
GString *string = g_string_sized_new (64);
|
||||||
|
|
||||||
if (element_names == NULL)
|
if (slist == NULL)
|
||||||
return g_strdup ("");
|
return g_strdup ("");
|
||||||
else
|
else
|
||||||
for (; element_names; element_names = g_slist_next (element_names)) {
|
for (; slist; slist = g_slist_next (slist)) {
|
||||||
g_string_append (string, element_names->data);
|
g_string_append (string, slist->data);
|
||||||
if (g_slist_next (element_names))
|
if (g_slist_next (slist))
|
||||||
g_string_append (string, "/");
|
g_string_append (string, delimiter);
|
||||||
}
|
}
|
||||||
return g_string_free (string, FALSE);
|
return g_string_free (string, FALSE);
|
||||||
}
|
}
|
||||||
@ -86,7 +103,7 @@ validate (const gchar *element_name,
|
|||||||
GSList *head;
|
GSList *head;
|
||||||
|
|
||||||
head = g_slist_prepend (element_stack, element_name);
|
head = g_slist_prepend (element_stack, element_name);
|
||||||
element_path = join_element_names (head);
|
element_path = strjoin_slist (head, "/");
|
||||||
g_slist_free1 (head);
|
g_slist_free1 (head);
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(valid_path_list); i++) {
|
for (i = 0; i < G_N_ELEMENTS(valid_path_list); i++) {
|
||||||
@ -120,8 +137,8 @@ start_element_callback (GMarkupParseContext *pcontext,
|
|||||||
ParseCallbackData *data = user_data;
|
ParseCallbackData *data = user_data;
|
||||||
const gchar **names = attribute_names;
|
const gchar **names = attribute_names;
|
||||||
const gchar **values = attribute_values;
|
const gchar **values = attribute_values;
|
||||||
gint column = -1, row = -1;
|
gint column = -1, row = -1, groups = -1, levels = -1;
|
||||||
gchar *name = NULL;
|
gchar *name = NULL, *id = NULL;
|
||||||
|
|
||||||
validate (element_name, data->element_stack, error);
|
validate (element_name, data->element_stack, error);
|
||||||
if (error && *error)
|
if (error && *error)
|
||||||
@ -134,6 +151,12 @@ start_element_callback (GMarkupParseContext *pcontext,
|
|||||||
row = strtol (*values, NULL, 10);
|
row = strtol (*values, NULL, 10);
|
||||||
else if (g_strcmp0 (*names, "name") == 0)
|
else if (g_strcmp0 (*names, "name") == 0)
|
||||||
name = g_strdup (*values);
|
name = g_strdup (*values);
|
||||||
|
else if (g_strcmp0 (*names, "id") == 0)
|
||||||
|
id = g_strdup (*values);
|
||||||
|
else if (g_strcmp0 (*names, "groups") == 0)
|
||||||
|
groups = strtol (*values, NULL, 10);
|
||||||
|
else if (g_strcmp0 (*names, "levels") == 0)
|
||||||
|
levels = strtol (*values, NULL, 10);
|
||||||
names++;
|
names++;
|
||||||
values++;
|
values++;
|
||||||
}
|
}
|
||||||
@ -144,19 +167,41 @@ start_element_callback (GMarkupParseContext *pcontext,
|
|||||||
NULL);
|
NULL);
|
||||||
if (name)
|
if (name)
|
||||||
eek_element_set_name (EEK_ELEMENT(data->keyboard), name);
|
eek_element_set_name (EEK_ELEMENT(data->keyboard), name);
|
||||||
} else if (g_strcmp0 (element_name, "section") == 0) {
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "section") == 0) {
|
||||||
data->section = eek_keyboard_create_section (data->keyboard);
|
data->section = eek_keyboard_create_section (data->keyboard);
|
||||||
if (name)
|
if (name)
|
||||||
eek_element_set_name (EEK_ELEMENT(data->section), name);
|
eek_element_set_name (EEK_ELEMENT(data->section), name);
|
||||||
} else if (g_strcmp0 (element_name, "key") == 0) {
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "key") == 0) {
|
||||||
data->key = eek_section_create_key (data->section, column, row);
|
data->key = eek_section_create_key (data->section, column, row);
|
||||||
if (name)
|
if (name)
|
||||||
eek_element_set_name (EEK_ELEMENT(data->key), name);
|
eek_element_set_name (EEK_ELEMENT(data->key), name);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "keysyms") == 0) {
|
||||||
|
data->groups = groups;
|
||||||
|
data->levels = levels;
|
||||||
|
data->keysyms = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "outline") == 0) {
|
||||||
|
data->oref = g_strdup (id);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
g_free (name);
|
g_free (name);
|
||||||
|
g_free (id);
|
||||||
|
|
||||||
data->element_stack = g_slist_prepend (data->element_stack,
|
data->element_stack = g_slist_prepend (data->element_stack,
|
||||||
g_strdup (element_name));
|
g_strdup (element_name));
|
||||||
|
data->text->len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -167,10 +212,161 @@ end_element_callback (GMarkupParseContext *pcontext,
|
|||||||
{
|
{
|
||||||
ParseCallbackData *data = user_data;
|
ParseCallbackData *data = user_data;
|
||||||
GSList *head = data->element_stack;
|
GSList *head = data->element_stack;
|
||||||
|
gchar *text, **strv;
|
||||||
|
gint i;
|
||||||
|
|
||||||
g_free (head->data);
|
g_free (head->data);
|
||||||
data->element_stack = g_slist_next (data->element_stack);
|
data->element_stack = g_slist_next (data->element_stack);
|
||||||
g_slist_free1 (head);
|
g_slist_free1 (head);
|
||||||
|
|
||||||
|
text = g_strndup (data->text->str, data->text->len);
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "section") == 0) {
|
||||||
|
data->section = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "key") == 0) {
|
||||||
|
data->key = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "keysyms") == 0) {
|
||||||
|
gint num_keysyms = data->groups * data->levels;
|
||||||
|
guint *keysyms = g_slice_alloc0 (sizeof(guint) * num_keysyms);
|
||||||
|
|
||||||
|
head = data->keysyms = g_slist_reverse (data->keysyms);
|
||||||
|
for (i = 0; i < num_keysyms; i++) {
|
||||||
|
if (head) {
|
||||||
|
keysyms[i] = (guint)head->data;
|
||||||
|
head = g_slist_next (head);
|
||||||
|
} else
|
||||||
|
keysyms[i] = EEK_INVALID_KEYSYM;
|
||||||
|
}
|
||||||
|
|
||||||
|
eek_key_set_keysyms (data->key, keysyms, data->groups, data->levels);
|
||||||
|
g_slice_free1 (sizeof(guint) * num_keysyms, keysyms);
|
||||||
|
g_slist_free (data->keysyms);
|
||||||
|
data->keysyms = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "outline") == 0) {
|
||||||
|
EekOutline *outline = g_slice_new (EekOutline);
|
||||||
|
|
||||||
|
outline->num_points = g_slist_length (data->points);
|
||||||
|
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
|
||||||
|
outline->num_points);
|
||||||
|
for (head = data->points = g_slist_reverse (data->points), i = 0;
|
||||||
|
head;
|
||||||
|
head = g_slist_next (head), i++) {
|
||||||
|
memcpy (&outline->points[i], head->data, sizeof (EekPoint));
|
||||||
|
g_slice_free1 (sizeof (EekPoint), head->data);
|
||||||
|
}
|
||||||
|
g_slist_free (data->points);
|
||||||
|
data->points = NULL;
|
||||||
|
|
||||||
|
g_hash_table_insert (data->oref_outline_hash,
|
||||||
|
g_strdup (data->oref),
|
||||||
|
outline);
|
||||||
|
g_free (data->oref);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "point") == 0) {
|
||||||
|
EekPoint *point;
|
||||||
|
|
||||||
|
strv = g_strsplit (text, ",", -1);
|
||||||
|
|
||||||
|
if (g_strv_length (strv) != 2) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||||||
|
"invalid format for %s \"%s\"",
|
||||||
|
element_name,
|
||||||
|
text);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
point = g_slice_new (EekPoint);
|
||||||
|
point->x = g_strtod (strv[0], NULL);
|
||||||
|
point->y = g_strtod (strv[1], NULL);
|
||||||
|
|
||||||
|
g_strfreev (strv);
|
||||||
|
|
||||||
|
data->points = g_slist_prepend (data->points, point);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "bounds") == 0) {
|
||||||
|
EekBounds bounds;
|
||||||
|
|
||||||
|
strv = g_strsplit (text, ",", -1);
|
||||||
|
|
||||||
|
if (g_strv_length (strv) != 4) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||||||
|
"invalid format for %s \"%s\"",
|
||||||
|
element_name,
|
||||||
|
text);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds.x = g_strtod (strv[0], NULL);
|
||||||
|
bounds.y = g_strtod (strv[1], NULL);
|
||||||
|
bounds.width = g_strtod (strv[2], NULL);
|
||||||
|
bounds.height = g_strtod (strv[3], NULL);
|
||||||
|
|
||||||
|
g_strfreev (strv);
|
||||||
|
|
||||||
|
if (g_strcmp0 (data->element_stack->data, "keyboard") == 0)
|
||||||
|
eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
|
||||||
|
else if (g_strcmp0 (data->element_stack->data, "section") == 0)
|
||||||
|
eek_element_set_bounds (EEK_ELEMENT(data->section), &bounds);
|
||||||
|
else if (g_strcmp0 (data->element_stack->data, "key") == 0)
|
||||||
|
eek_element_set_bounds (EEK_ELEMENT(data->key), &bounds);
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "columns") == 0) {
|
||||||
|
data->num_columns = strtol (text, NULL, 10);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "orientation") == 0) {
|
||||||
|
data->orientation = strtol (text, NULL, 10);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "row") == 0) {
|
||||||
|
eek_section_add_row (data->section,
|
||||||
|
data->num_columns,
|
||||||
|
data->orientation);
|
||||||
|
data->num_columns = 0;
|
||||||
|
data->orientation = EEK_ORIENTATION_HORIZONTAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "keycode") == 0) {
|
||||||
|
eek_key_set_keycode (data->key, strtoul (text, NULL, 10));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "keysym") == 0) {
|
||||||
|
guint keysym = strtoul (text, NULL, 10);
|
||||||
|
data->keysyms = g_slist_prepend (data->keysyms, (gpointer)keysym);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "outline-ref") == 0) {
|
||||||
|
g_hash_table_insert (data->key_oref_hash, data->key, g_strdup (text));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free (text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -180,6 +376,8 @@ text_callback (GMarkupParseContext *pcontext,
|
|||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
ParseCallbackData *data = user_data;
|
||||||
|
g_string_append_len (data->text, text, text_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GMarkupParser parser = {
|
static const GMarkupParser parser = {
|
||||||
@ -190,6 +388,42 @@ static const GMarkupParser parser = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
outline_free (gpointer data)
|
||||||
|
{
|
||||||
|
EekOutline *outline = data;
|
||||||
|
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
|
||||||
|
g_boxed_free (EEK_TYPE_OUTLINE, outline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scale_bounds_callback (EekElement *element,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
scale_bounds (EekElement *element,
|
||||||
|
gdouble scale)
|
||||||
|
{
|
||||||
|
EekBounds bounds;
|
||||||
|
|
||||||
|
eek_element_get_bounds (element, &bounds);
|
||||||
|
bounds.x *= scale;
|
||||||
|
bounds.y *= scale;
|
||||||
|
bounds.width *= scale;
|
||||||
|
bounds.height *= scale;
|
||||||
|
|
||||||
|
if (EEK_IS_CONTAINER(element))
|
||||||
|
eek_container_foreach_child (EEK_CONTAINER(element),
|
||||||
|
scale_bounds_callback,
|
||||||
|
&scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scale_bounds_callback (EekElement *element,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
scale_bounds (element, *(gdouble *)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
static EekKeyboard *
|
static EekKeyboard *
|
||||||
eek_xml_layout_real_create_keyboard (EekLayout *self,
|
eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||||
gdouble initial_width,
|
gdouble initial_width,
|
||||||
@ -200,12 +434,25 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
|||||||
GError *error;
|
GError *error;
|
||||||
gchar buffer[BUFSIZE];
|
gchar buffer[BUFSIZE];
|
||||||
ParseCallbackData data;
|
ParseCallbackData data;
|
||||||
|
EekBounds bounds;
|
||||||
|
gdouble scale;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer k, v;
|
||||||
|
|
||||||
g_return_val_if_fail (priv->source, NULL);
|
g_return_val_if_fail (priv->source, NULL);
|
||||||
|
|
||||||
data.element_stack = NULL;
|
memset (&data, 0, sizeof data);
|
||||||
|
data.layout = self;
|
||||||
data.text = g_string_sized_new (BUFSIZE);
|
data.text = g_string_sized_new (BUFSIZE);
|
||||||
data.keyboard = NULL;
|
data.key_oref_hash = g_hash_table_new_full (g_direct_hash,
|
||||||
|
g_direct_equal,
|
||||||
|
NULL,
|
||||||
|
g_free);
|
||||||
|
data.oref_outline_hash = g_hash_table_new_full (g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
outline_free);
|
||||||
|
|
||||||
pcontext = g_markup_parse_context_new (&parser, 0, &data, NULL);
|
pcontext = g_markup_parse_context_new (&parser, 0, &data, NULL);
|
||||||
while (1) {
|
while (1) {
|
||||||
gssize nread;
|
gssize nread;
|
||||||
@ -221,11 +468,50 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
|||||||
if (!g_markup_parse_context_parse (pcontext, buffer, nread, &error))
|
if (!g_markup_parse_context_parse (pcontext, buffer, nread, &error))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
g_warning ("%s", error->message);
|
||||||
|
|
||||||
error = NULL;
|
error = NULL;
|
||||||
g_markup_parse_context_end_parse (pcontext, &error);
|
g_markup_parse_context_end_parse (pcontext, &error);
|
||||||
|
if (error)
|
||||||
|
g_warning ("%s", error->message);
|
||||||
|
|
||||||
g_markup_parse_context_free (pcontext);
|
g_markup_parse_context_free (pcontext);
|
||||||
|
|
||||||
|
if (!data.keyboard)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
eek_element_get_bounds (EEK_ELEMENT(data.keyboard), &bounds);
|
||||||
|
scale = initial_width < initial_height ? bounds.width / initial_width :
|
||||||
|
bounds.height / initial_height;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, data.key_oref_hash);
|
||||||
|
while (g_hash_table_iter_next (&iter, &k, &v)) {
|
||||||
|
EekOutline *outline = g_hash_table_lookup (data.oref_outline_hash, v);
|
||||||
|
g_assert (outline);
|
||||||
|
eek_key_set_outline (EEK_KEY(k), outline);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_hash_table_iter_init (&iter, data.oref_outline_hash);
|
||||||
|
while (g_hash_table_iter_next (&iter, &k, &v)) {
|
||||||
|
EekOutline *outline = v;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < outline->num_points; i++) {
|
||||||
|
outline->points[i].x *= scale;
|
||||||
|
outline->points[i].y *= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scale_bounds (EEK_ELEMENT(data.keyboard), scale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
g_string_free (data.text, TRUE);
|
g_string_free (data.text, TRUE);
|
||||||
|
if (data.key_oref_hash)
|
||||||
|
g_hash_table_destroy (data.key_oref_hash);
|
||||||
|
priv->outline_hash = data.oref_outline_hash;
|
||||||
|
|
||||||
return data.keyboard;
|
return data.keyboard;
|
||||||
}
|
}
|
||||||
@ -277,6 +563,18 @@ eek_xml_layout_dispose (GObject *object)
|
|||||||
g_object_unref (priv->source);
|
g_object_unref (priv->source);
|
||||||
priv->source = NULL;
|
priv->source = NULL;
|
||||||
}
|
}
|
||||||
|
G_OBJECT_CLASS (eek_xml_layout_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_xml_layout_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
EekXmlLayoutPrivate *priv = EEK_XML_LAYOUT_GET_PRIVATE (object);
|
||||||
|
|
||||||
|
if (priv->outline_hash)
|
||||||
|
g_hash_table_unref (priv->outline_hash);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (eek_xml_layout_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -293,6 +591,7 @@ eek_xml_layout_class_init (EekXmlLayoutClass *klass)
|
|||||||
gobject_class->set_property = eek_xml_layout_set_property;
|
gobject_class->set_property = eek_xml_layout_set_property;
|
||||||
gobject_class->get_property = eek_xml_layout_get_property;
|
gobject_class->get_property = eek_xml_layout_get_property;
|
||||||
gobject_class->dispose = eek_xml_layout_dispose;
|
gobject_class->dispose = eek_xml_layout_dispose;
|
||||||
|
gobject_class->finalize = eek_xml_layout_finalize;
|
||||||
|
|
||||||
pspec = g_param_spec_object ("source",
|
pspec = g_param_spec_object ("source",
|
||||||
"Source",
|
"Source",
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
G_INLINE_FUNC void
|
void
|
||||||
g_string_markup_printf (GString *output, const gchar *format, ...)
|
g_string_markup_printf (GString *output, const gchar *format, ...)
|
||||||
{
|
{
|
||||||
gchar *escaped_text;
|
gchar *escaped_text;
|
||||||
@ -56,7 +56,7 @@ output_key_callback (EekElement *element, gpointer user_data)
|
|||||||
OutputCallbackData *data = user_data;
|
OutputCallbackData *data = user_data;
|
||||||
EekBounds bounds;
|
EekBounds bounds;
|
||||||
EekOutline *outline;
|
EekOutline *outline;
|
||||||
gint i, num_groups, num_levels;
|
gint i, num_groups, num_levels, num_keysyms;
|
||||||
guint *keysyms;
|
guint *keysyms;
|
||||||
gint column, row;
|
gint column, row;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ output_key_callback (EekElement *element, gpointer user_data)
|
|||||||
g_array_append_val (data->outline_array, outline);
|
g_array_append_val (data->outline_array, outline);
|
||||||
g_string_append_indent (data->output, data->indent + 1);
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
g_string_markup_printf (data->output,
|
g_string_markup_printf (data->output,
|
||||||
"<outline>outline%d</outline>\n",
|
"<outline-ref>outline%d</outline-ref>\n",
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +94,11 @@ output_key_callback (EekElement *element, gpointer user_data)
|
|||||||
g_string_markup_printf (data->output, "<keycode>%u</keycode>\n",
|
g_string_markup_printf (data->output, "<keycode>%u</keycode>\n",
|
||||||
eek_key_get_keycode (EEK_KEY(element)));
|
eek_key_get_keycode (EEK_KEY(element)));
|
||||||
|
|
||||||
keysyms = NULL;
|
eek_key_get_keysyms (EEK_KEY(element), NULL, &num_groups, &num_levels);
|
||||||
eek_key_get_keysyms (EEK_KEY(element), &keysyms, &num_groups, &num_levels);
|
num_keysyms = num_groups * num_levels;
|
||||||
if (keysyms) {
|
if (num_keysyms > 0) {
|
||||||
|
keysyms = g_slice_alloc (num_keysyms * sizeof(guint));
|
||||||
|
eek_key_get_keysyms (EEK_KEY(element), &keysyms, NULL, NULL);
|
||||||
g_string_append_indent (data->output, data->indent + 1);
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
g_string_markup_printf (data->output,
|
g_string_markup_printf (data->output,
|
||||||
"<keysyms groups=\"%d\" levels=\"%d\">\n",
|
"<keysyms groups=\"%d\" levels=\"%d\">\n",
|
||||||
@ -118,6 +120,7 @@ output_key_callback (EekElement *element, gpointer user_data)
|
|||||||
}
|
}
|
||||||
g_string_append_indent (data->output, data->indent + 1);
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
g_string_markup_printf (data->output, "</keysyms>\n");
|
g_string_markup_printf (data->output, "</keysyms>\n");
|
||||||
|
g_slice_free1 (num_keysyms * sizeof(guint), keysyms);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_append_indent (data->output, data->indent);
|
g_string_append_indent (data->output, data->indent);
|
||||||
@ -129,7 +132,7 @@ output_section_callback (EekElement *element, gpointer user_data)
|
|||||||
{
|
{
|
||||||
OutputCallbackData *data = user_data;
|
OutputCallbackData *data = user_data;
|
||||||
EekBounds bounds;
|
EekBounds bounds;
|
||||||
gint angle;
|
gint angle, n_rows, i;
|
||||||
|
|
||||||
g_string_append_indent (data->output, data->indent);
|
g_string_append_indent (data->output, data->indent);
|
||||||
if (eek_element_get_name (element))
|
if (eek_element_get_name (element))
|
||||||
@ -145,6 +148,27 @@ output_section_callback (EekElement *element, gpointer user_data)
|
|||||||
angle = eek_section_get_angle (EEK_SECTION(element));
|
angle = eek_section_get_angle (EEK_SECTION(element));
|
||||||
g_string_append_indent (data->output, data->indent + 1);
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
g_string_markup_printf (data->output, "<angle>%d</angle>\n", angle);
|
g_string_markup_printf (data->output, "<angle>%d</angle>\n", angle);
|
||||||
|
|
||||||
|
n_rows = eek_section_get_n_rows (EEK_SECTION(element));
|
||||||
|
for (i = 0; i < n_rows; i++) {
|
||||||
|
gint num_columns;
|
||||||
|
EekOrientation orientation;
|
||||||
|
|
||||||
|
eek_section_get_row (EEK_SECTION(element),
|
||||||
|
i,
|
||||||
|
&num_columns,
|
||||||
|
&orientation);
|
||||||
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
|
g_string_markup_printf (data->output, "<row>\n");
|
||||||
|
g_string_append_indent (data->output, data->indent + 2);
|
||||||
|
g_string_markup_printf (data->output, "<columns>%d</columns>\n",
|
||||||
|
num_columns);
|
||||||
|
g_string_append_indent (data->output, data->indent + 2);
|
||||||
|
g_string_markup_printf (data->output, "<orientation>%d</orientation>\n",
|
||||||
|
orientation);
|
||||||
|
g_string_append_indent (data->output, data->indent + 1);
|
||||||
|
g_string_markup_printf (data->output, "</row>\n");
|
||||||
|
}
|
||||||
|
|
||||||
data->indent++;
|
data->indent++;
|
||||||
eek_container_foreach_child (EEK_CONTAINER(element),
|
eek_container_foreach_child (EEK_CONTAINER(element),
|
||||||
@ -200,7 +224,7 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
|
|||||||
g_string_append_indent (output, indent + 1);
|
g_string_append_indent (output, indent + 1);
|
||||||
g_string_markup_printf (output, "</outline>\n");
|
g_string_markup_printf (output, "</outline>\n");
|
||||||
}
|
}
|
||||||
g_array_free (data.outline_array, FALSE);
|
g_array_free (data.outline_array, TRUE);
|
||||||
|
|
||||||
g_string_append_indent (output, indent);
|
g_string_append_indent (output, indent);
|
||||||
g_string_markup_printf (output, "</keyboard>\n");
|
g_string_markup_printf (output, "</keyboard>\n");
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void eek_keyboard_print (EekKeyboard *keyboard, gint indent);
|
void eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_XML_H */
|
#endif /* EEK_XML_H */
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) $(GIO2_CFLAGS) $(GTK_CFLAGS) $(XKB_CFLAGS)
|
INCLUDES = -I$(top_srcdir) $(GIO2_CFLAGS) $(GTK_CFLAGS) $(XKB_CFLAGS)
|
||||||
|
|
||||||
TESTS = eek-simple-test eek-xkb-test
|
TESTS = eek-simple-test eek-xkb-test eek-xml-test
|
||||||
noinst_PROGRAMS = $(TESTS)
|
noinst_PROGRAMS = $(TESTS)
|
||||||
|
|
||||||
eek_simple_test_SOURCES = eek-simple-test.c
|
eek_simple_test_SOURCES = eek-simple-test.c
|
||||||
@ -26,3 +26,6 @@ eek_simple_test_LDADD = $(top_builddir)/eek/libeek.la
|
|||||||
|
|
||||||
eek_xkb_test_SOURCES = eek-xkb-test.c
|
eek_xkb_test_SOURCES = eek-xkb-test.c
|
||||||
eek_xkb_test_LDADD = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkb.la
|
eek_xkb_test_LDADD = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkb.la
|
||||||
|
|
||||||
|
eek_xml_test_SOURCES = eek-xml-test.c
|
||||||
|
eek_xml_test_LDADD = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkl.la
|
||||||
|
|||||||
71
tests/eek-xml-test.c
Normal file
71
tests/eek-xml-test.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "eek/eek-xml.h"
|
||||||
|
#include "eek/eek-xkl.h"
|
||||||
|
|
||||||
|
/* For gdk_x11_display_get_xdisplay(). See main(). */
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_output_parse (void)
|
||||||
|
{
|
||||||
|
GString *output;
|
||||||
|
GInputStream *input;
|
||||||
|
EekLayout *layout;
|
||||||
|
EekKeyboard *keyboard;
|
||||||
|
|
||||||
|
output = g_string_sized_new (8192);
|
||||||
|
|
||||||
|
layout = eek_xkl_layout_new ();
|
||||||
|
|
||||||
|
keyboard = eek_keyboard_new (layout, 640, 480);
|
||||||
|
g_object_unref (layout);
|
||||||
|
|
||||||
|
eek_keyboard_output (keyboard, output, 0);
|
||||||
|
g_object_unref (keyboard);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fwrite (output->str, sizeof(gchar), output->len, stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
input = g_memory_input_stream_new_from_data (output->str,
|
||||||
|
output->len,
|
||||||
|
NULL);
|
||||||
|
layout = eek_xml_layout_new (input);
|
||||||
|
g_object_unref (input);
|
||||||
|
|
||||||
|
keyboard = eek_keyboard_new (layout, 640, 480);
|
||||||
|
g_object_unref (layout);
|
||||||
|
g_object_unref (keyboard);
|
||||||
|
|
||||||
|
g_string_free (output, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_type_init ();
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
gtk_init (&argc, &argv); /* for gdk_x11_display_get_xdisplay() */
|
||||||
|
|
||||||
|
g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user