aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2011-11-04 00:10:03 +0100
committerThomas White <taw@bitwiz.org.uk>2011-11-04 00:10:03 +0100
commit1d1806f5cffa1ffda929de0ef7b74eb6c7df9fba (patch)
treeb84bfbc004af73ecebe2bc29094d1dfc89a7cd7e
parent04d9338eef4c3b864a1693f8312ce35f9ac8302c (diff)
Add most of the serializer
-rw-r--r--src/loadsave.c298
-rw-r--r--src/loadsave.h13
-rw-r--r--src/mainwindow.c39
-rw-r--r--src/stylesheet.c21
-rw-r--r--src/stylesheet.h1
-rw-r--r--src/tool_text.c18
6 files changed, 373 insertions, 17 deletions
diff --git a/src/loadsave.c b/src/loadsave.c
index 45b8ab3..ea2a8da 100644
--- a/src/loadsave.c
+++ b/src/loadsave.c
@@ -1,5 +1,5 @@
/*
- * loadsave.v
+ * loadsave.c
*
* Colloquium - A tiny presentation program
*
@@ -28,26 +28,296 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <ctype.h>
#include "presentation.h"
#include "objects.h"
#include "stylesheet.h"
-struct serializer
+struct ds_node
{
- FILE *fh;
-
- char *stack[32];
- int stack_depth;
- char *prefix;
- int empty_set;
- int blank_written;
+ char *key;
+ char *value;
+ struct ds_node **children;
+ int n_children;
+ int max_children;
};
+static int alloc_children(struct ds_node *node)
+{
+ struct ds_node **new;
+
+ new = realloc(node->children,
+ node->max_children*sizeof(*node->children));
+ if ( new == NULL ) return 1;
+
+ node->children = new;
+ return 0;
+}
+
+
+static struct ds_node *new_ds_node(const char *key, const char *value)
+{
+ struct ds_node *new;
+
+ new = malloc(sizeof(*new));
+ if ( new == NULL ) return NULL;
+
+ new->key = NULL;
+ new->value = NULL;
+ new->n_children = 0;
+ new->max_children = 32;
+ new->children = NULL;
+
+ if ( alloc_children(new) ) {
+ free(new);
+ return NULL;
+ }
+
+ return new;
+}
+
+
+static struct ds_node *add_child(struct ds_node *node, const char *key)
+{
+ struct ds_node *new;
+
+ new = new_ds_node(key, NULL);
+ if ( new == NULL ) return NULL;
+ new->key = strdup(key);
+ if ( new->key == NULL ) return NULL;
+
+ if ( node->n_children >= new->max_children ) {
+ new->max_children += 32;
+ if ( alloc_children(node) ) {
+ free(new);
+ return NULL;
+ }
+ }
+
+ node->children[node->n_children++] = new;
+
+ return new;
+}
+
+
+static void show_tree(struct ds_node *root)
+{
+ int i;
+
+ for ( i=0; i<root->n_children; i++ ) {
+ printf("%3i: %s => %s\n", i, root->children[i]->key,
+ root->children[i]->value);
+ }
+
+ for ( i=0; i<root->n_children; i++ ) {
+ if ( root->children[i]->n_children > 0 ) {
+ printf("\n");
+ printf("%s:\n", root->children[i]->key);
+ show_tree(root->children[i]);
+ }
+ }
+}
+
+
+static struct ds_node *find_node(struct ds_node *root, const char *path)
+{
+ size_t start, len;
+ char element[1024];
+ struct ds_node *cur = root;
+
+ len = strlen(path);
+ printf("looking for '%s' in %s\n", path, root->key);
+
+ start = 0;
+ while ( start < len ) {
+
+ size_t pos, i;
+ int child;
+ int found = 0;
+
+ pos = 0;
+ for ( i=start; i<len; i++ ) {
+
+ if ( path[i] == '/' ) break;
+ element[pos++] = path[i];
+
+ }
+ element[pos++] = '\0';
+ if ( element[0] == '\0' ) {
+ printf("done.\n");
+ goto out;
+ }
+ start = i;
+ printf("got '%s' (%i %i)\n", element, start, pos);
+
+ for ( child=0; child<cur->n_children; child++ ) {
+
+ const char *this_key = cur->children[child]->key;
+
+ if ( strcmp(this_key, element) == 0 ) {
+ cur = cur->children[child];
+ found = 1;
+ break;
+ }
+
+ }
+
+ if ( !found ) {
+
+ cur = add_child(cur, element);
+ printf("Adding %s to %s\n", element, cur->key);
+ if ( cur == NULL ) {
+ return NULL; /* Error */
+ }
+
+ }
+
+ }
+
+out:
+ return cur;
+}
+
+
+static int deserialize_file(FILE *fh, struct ds_node *root)
+{
+ char *rval = NULL;
+ struct ds_node *cur_node = root;
+
+ do {
+ size_t i;
+ char line[1024];
+ size_t len, s_start;
+ size_t s_equals = 0;
+ size_t s_val = 0;
+ size_t s_openbracket = 0;
+ size_t s_closebracket = 0;
+ int h_start = 0;
+ int h_equals = 0;
+ int h_val = 0;
+ int h_openbracket = 0;
+ int h_closebracket = 0;
+
+ rval = fgets(line, 1023, fh);
+ if ( rval == NULL ) {
+ printf("Error!\n");
+ continue;
+ }
+
+ len = strlen(line);
+ s_start = len-1;
+
+ for ( i=0; i<len-1; i++ ) {
+ if ( !h_start && !isspace(line[i]) ) {
+ s_start = i;
+ h_start = 1;
+ }
+ if ( !h_val && h_equals && !isspace(line[i]) ) {
+ s_val = i;
+ h_val = 1;
+ }
+ if ( !h_equals && (line[i] == '=') ) {
+ s_equals = i;
+ h_equals = 1;
+ }
+ if ( !h_openbracket && (line[i] == '[') ) {
+ s_openbracket = i;
+ h_openbracket = 1;
+ }
+ if ( h_openbracket && !h_closebracket
+ && (line[i] == ']') )
+ {
+ s_closebracket = i;
+ h_closebracket = 1;
+ }
+ }
+
+ if ( (h_openbracket && !h_closebracket)
+ || (!h_openbracket && h_closebracket) )
+ {
+ fprintf(stderr, "Mismatched square brackets: %s", line);
+ continue;
+ }
+
+ if ( !h_openbracket && !h_equals ) continue;
+
+ if ( !h_openbracket && (!h_start || !h_val || !h_equals) ) {
+ fprintf(stderr, "Incomplete assignment: %s", line);
+ continue;
+ }
+
+ if ( h_equals && (h_openbracket || h_closebracket) ) {
+ fprintf(stderr, "Brackets and equals: %s", line);
+ continue;
+ }
+
+ if ( !h_openbracket ) {
+
+ size_t pos = 0;
+ char key[1024];
+ char value[1024];
+ struct ds_node *node;
+
+ for ( i=s_start; i<s_equals; i++ ) {
+ if ( !isspace(line[i]) ) key[pos++] = line[i];
+ }
+ key[pos] = '\0';
+
+ pos = 0;
+ for ( i=s_val; i<len; i++ ) {
+ if ( line[i] != '\n' ) value[pos++] = line[i];
+ }
+ value[pos] = '\0';
+
+ node = find_node(cur_node, key);
+ node->value = strdup(value);
+
+ } else {
+
+ size_t pos = 0;
+ char path[1024];
+
+ for ( i=s_openbracket+1; i<s_closebracket; i++ ) {
+ if ( !isspace(line[i]) ) path[pos++] = line[i];
+ }
+ path[pos] = '\0';
+ printf("descending to %s\n", path);
+ cur_node = find_node(root, path);
+ printf("cur_node->key = '%s'\n", cur_node->key);
+
+ }
+
+ } while ( rval != NULL );
+
+ show_tree(root);
+
+ return 0;
+}
+
+
int load_presentation(struct presentation *p, const char *filename)
{
+ FILE *fh;
+ struct ds_node *root;
+
+ fh = fopen(filename, "r");
+ if ( fh == NULL ) return 1;
+
+ root = new_ds_node(NULL, NULL);
+ if ( root == NULL ) return 1;
+
+ if ( deserialize_file(fh, root) ) {
+ fclose(fh);
+ return 1;
+ }
+
+ fclose(fh);
+
+ p->cur_edit_slide = p->slides[0];
+
return 0;
}
@@ -95,8 +365,10 @@ static void check_prefix_output(struct serializer *ser)
{
if ( ser->empty_set ) {
ser->empty_set = 0;
- fprintf(ser->fh, "\n");
- fprintf(ser->fh, "[%s]\n", ser->prefix);
+ if ( ser->prefix != NULL ) {
+ fprintf(ser->fh, "\n");
+ fprintf(ser->fh, "[%s]\n", ser->prefix);
+ }
}
}
@@ -111,7 +383,7 @@ void serialize_s(struct serializer *ser, const char *key, const char *val)
void serialize_f(struct serializer *ser, const char *key, double val)
{
check_prefix_output(ser);
- fprintf(ser->fh, "%s = %.2ff\n", key, val);
+ fprintf(ser->fh, "%s = %.2f\n", key, val);
}
@@ -176,7 +448,7 @@ int save_presentation(struct presentation *p, const char *filename)
serialize_start(&ser, o_id);
serialize_s(&ser, "type", type_text(o->type));
- //o->serialize(o, &ser);
+ o->serialize(o, &ser);
serialize_end(&ser);
}
diff --git a/src/loadsave.h b/src/loadsave.h
index 981e0ab..90e2f0a 100644
--- a/src/loadsave.h
+++ b/src/loadsave.h
@@ -30,8 +30,17 @@
/* Forward declaration */
struct presentation;
-/* Opaque structure */
-struct serializer;
+/* Would be opaque if I could be bothered to write the constructor */
+struct serializer
+{
+ FILE *fh;
+
+ char *stack[32];
+ int stack_depth;
+ char *prefix;
+ int empty_set;
+ int blank_written;
+};
extern void serialize_start(struct serializer *s, const char *id);
extern void serialize_s(struct serializer *s, const char *key, const char *val);
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 74bcca4..7b4c8e6 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -89,7 +89,7 @@ static gint open_response_sig(GtkWidget *d, gint response,
if ( load_presentation(p, filename) ) {
show_error(p, "Failed to open presentation");
} else {
- open_mainwindow(p);
+ redraw_slide(p->cur_edit_slide);
}
} else {
struct presentation *p;
@@ -186,8 +186,45 @@ static gint save_sig(GtkWidget *widget, struct presentation *p)
}
+static gint save_ss_response_sig(GtkWidget *d, gint response,
+ struct presentation *p)
+{
+ if ( response == GTK_RESPONSE_ACCEPT ) {
+
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+
+ if ( save_stylesheet(p->ss, filename) ) {
+ show_error(p, "Failed to save style sheet");
+ }
+
+ g_free(filename);
+
+ }
+
+ gtk_widget_destroy(d);
+
+ return 0;
+}
+
+
static gint save_ss_sig(GtkWidget *widget, struct presentation *p)
{
+ GtkWidget *d;
+
+ d = gtk_file_chooser_dialog_new("Save Style sheet",
+ GTK_WINDOW(p->window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ g_signal_connect(G_OBJECT(d), "response",
+ G_CALLBACK(save_ss_response_sig), p);
+
+ gtk_widget_show_all(d);
+
return 0;
}
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 69ff98c..61b37fe 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -574,8 +574,27 @@ StyleSheet *new_stylesheet()
}
-void save_stylesheet(StyleSheet *ss, const char *filename)
+int save_stylesheet(StyleSheet *ss, const char *filename)
{
+ FILE *fh;
+ struct serializer ser;
+
+ fh = fopen(filename, "w");
+ if ( fh == NULL ) return 1;
+
+ /* Set up the serializer */
+ ser.fh = fh;
+ ser.stack_depth = 0;
+ ser.prefix = NULL;
+
+ fprintf(fh, "# Colloquium style sheet file\n");
+ serialize_f(&ser, "version", 0.1);
+
+ serialize_start(&ser, "stylesheet");
+ write_stylesheet(ss, &ser);
+ serialize_end(&ser);
+
+ return 0;
}
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 113e38e..224083a 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -87,6 +87,7 @@ extern StylesheetWindow *open_stylesheet(struct presentation *p);
extern StyleSheet *new_stylesheet();
extern StyleSheet *load_stylesheet(const char *filename);
+extern int save_stylesheet(StyleSheet *ss, const char *filename);
extern struct style *find_style(StyleSheet *ss, const char *name);
diff --git a/src/tool_text.c b/src/tool_text.c
index 8f18c7c..cdf96b5 100644
--- a/src/tool_text.c
+++ b/src/tool_text.c
@@ -35,6 +35,7 @@
#include "objects.h"
#include "mainwindow.h"
#include "slide_render.h"
+#include "loadsave.h"
enum text_drag_reason
@@ -393,6 +394,22 @@ static void delete_text_object(struct object *op)
}
+static void serialize(struct object *op, struct serializer *ser)
+{
+ struct text_object *o = (struct text_object *)op;
+
+ serialize_s(ser, "style", op->style->name);
+ if ( op->style == op->parent->parent->ss->styles[0] ) {
+ serialize_f(ser, "x", op->x);
+ serialize_f(ser, "y", op->y);
+ serialize_f(ser, "w", op->bb_width);
+ serialize_f(ser, "h", op->bb_height);
+ }
+
+ serialize_s(ser, "text", o->text);
+}
+
+
static struct object *add_text_object(struct slide *s, double x, double y,
struct style *sty,
struct text_toolinfo *ti)
@@ -424,6 +441,7 @@ static struct object *add_text_object(struct slide *s, double x, double y,
new->base.render_object = render_text_object;
new->base.delete_object = delete_text_object;
new->base.update_object = update_text_object;
+ new->base.serialize = serialize;
if ( add_object_to_slide(s, (struct object *)new) ) {
delete_object((struct object *)new);