aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2011-11-04 21:01:57 +0100
committerThomas White <taw@bitwiz.org.uk>2011-11-04 21:01:57 +0100
commitdbff61bb3053e4fe30397b48a32ec415119bcf66 (patch)
tree1eacc5147554b47cf6b536c123340a2d7d487925
parentd6c04212c403a817c5f98f8ee3e453422a02cc91 (diff)
Load stylesheet from presentation file
-rw-r--r--src/loadsave.c240
-rw-r--r--src/presentation.c1
-rw-r--r--src/presentation.h2
-rw-r--r--src/stylesheet.c39
-rw-r--r--src/stylesheet.h9
5 files changed, 286 insertions, 5 deletions
diff --git a/src/loadsave.c b/src/loadsave.c
index aa204ad..289d793 100644
--- a/src/loadsave.c
+++ b/src/loadsave.c
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+#include <assert.h>
#include "presentation.h"
#include "objects.h"
@@ -106,7 +107,7 @@ static struct ds_node *add_child(struct ds_node *node, const char *key)
}
-static void show_tree(struct ds_node *root, const char *path)
+static void UNUSED show_tree(struct ds_node *root, const char *path)
{
char newpath[1024];
int i;
@@ -292,7 +293,234 @@ static int deserialize_file(FILE *fh, struct ds_node *root)
} while ( rval != NULL );
- show_tree(root, "");
+ return 0;
+}
+
+
+static void free_ds_tree(struct ds_node *root)
+{
+ int i;
+
+ for ( i=0; i<root->n_children; i++ ) {
+ if ( root->children[i]->n_children > 0 ) {
+ free_ds_tree(root->children[i]);
+ }
+ }
+
+ free(root->key);
+ free(root->value); /* Might free(NULL), but that's fine */
+ free(root);
+}
+
+
+static int get_field_f(struct ds_node *root, const char *key, double *val)
+{
+ struct ds_node *node;
+ double v;
+ char *check;
+
+ node = find_node(root, key);
+ if ( node == NULL ) {
+ fprintf(stderr, "Couldn't find field '%s'\n", key);
+ return 1;
+ }
+
+ v = strtod(node->value, &check);
+ if ( check == node->value ) {
+ fprintf(stderr, "Invalid value for '%s'\n", key);
+ return 1;
+ }
+
+ *val = v;
+
+ return 0;
+}
+
+
+static int get_field_i(struct ds_node *root, const char *key, int *val)
+{
+ struct ds_node *node;
+ int v;
+ char *check;
+
+ node = find_node(root, key);
+ if ( node == NULL ) {
+ fprintf(stderr, "Couldn't find field '%s'\n", key);
+ return 1;
+ }
+
+ v = strtol(node->value, &check, 0);
+ if ( check == node->value ) {
+ fprintf(stderr, "Invalid value for '%s'\n", key);
+ return 1;
+ }
+
+ *val = v;
+
+ return 0;
+}
+
+
+static int get_field_s(struct ds_node *root, const char *key, char **val)
+{
+ struct ds_node *node;
+ char *v;
+ size_t i, len, s1, s2;
+ int hq;
+
+ node = find_node(root, key);
+ if ( node == NULL ) {
+ fprintf(stderr, "Couldn't find field '%s'\n", key);
+ return 1;
+ }
+
+ len = strlen(node->value);
+ hq = 0;
+ for ( i=0; i<len; i++ ) {
+ if ( node->value[i] == '"' ) {
+ s1 = i;
+ hq = 1;
+ break;
+ }
+ }
+ if ( !hq ) {
+ fprintf(stderr, "No quotes in '%s'\n", node->value);
+ return 1;
+ }
+
+ for ( i=len-1; i>=0; i-- ) {
+ if ( node->value[i] == '"' ) {
+ s2 = i;
+ break;
+ }
+ }
+
+ if ( s1 == s2 ) {
+ fprintf(stderr, "Mismatchd quotes in '%s'\n", node->value);
+ return 1;
+ }
+
+ v = malloc(s2-s1+1);
+ if ( v == NULL ) {
+ fprintf(stderr, "Failed to allocate space for '%s'\n", key);
+ return 1;
+ }
+
+ strncpy(v, node->value+s1+1, s2-s1-1);
+ v[s2-s1-1] = '\0';
+
+ *val = v;
+
+ return 0;
+}
+
+
+static int read_style(struct style *sty, struct ds_node *root)
+{
+ char *align;
+
+ get_field_f(root, "margin_left", &sty->margin_left);
+ get_field_f(root, "margin_right", &sty->margin_right);
+ get_field_f(root, "margin_top", &sty->margin_top);
+ get_field_f(root, "margin_bottom", &sty->margin_bottom);
+
+ get_field_i(root, "use_max_width", &sty->use_max_width);
+ get_field_f(root, "max_width", &sty->max_width);
+
+ get_field_f(root, "offset_x", &sty->offset_x);
+ get_field_f(root, "offset_y", &sty->offset_y);
+
+ get_field_s(root, "font", &sty->font);
+ get_field_s(root, "colour", &sty->colour);
+ get_field_f(root, "alpha", &sty->alpha);
+
+ get_field_s(root, "halign", &align);
+ sty->halign = str_to_halign(align);
+ free(align);
+ get_field_s(root, "valign", &align);
+ sty->valign = str_to_valign(align);
+ free(align);
+
+ return 0;
+}
+
+
+static StyleSheet *tree_to_stylesheet(struct ds_node *root)
+{
+ StyleSheet *ss;
+ struct ds_node *node;
+ int i;
+
+ ss = new_stylesheet();
+ if ( ss == NULL ) return NULL;
+
+ node = find_node(root, "styles");
+ if ( node == NULL ) {
+ fprintf(stderr, "Couldn't find styles\n");
+ free_stylesheet(ss);
+ return NULL;
+ }
+
+ for ( i=0; i<node->n_children; i++ ) {
+
+ struct style *ns;
+ char *v;
+
+ get_field_s(node->children[i], "name", &v);
+ if ( v == NULL ) {
+ fprintf(stderr, "No name for style '%s'\n",
+ node->children[i]->key);
+ continue;
+ }
+
+ ns = new_style(ss, v);
+ if ( ns == NULL ) {
+ fprintf(stderr, "Couldn't create style for '%s'\n",
+ node->children[i]->key);
+ continue;
+ }
+
+ if ( read_style(ns, node->children[i]) ) {
+ fprintf(stderr, "Couldn't read style '%s'\n", v);
+ continue;
+ }
+
+ }
+
+ return ss;
+}
+
+
+int tree_to_presentation(struct ds_node *root, struct presentation *p)
+{
+ struct ds_node *node;
+ char *check;
+
+ node = find_node(root, "slide-properties/width");
+ if ( node == NULL ) return 1;
+ p->slide_width = strtod(node->value, &check);
+ if ( check == node->value ) {
+ fprintf(stderr, "Invalid slide width\n");
+ return 1;
+ }
+
+ node = find_node(root, "slide-properties/height");
+ if ( node == NULL ) return 1;
+ p->slide_height = strtod(node->value, &check);
+ if ( check == node->value ) {
+ fprintf(stderr, "Invalid slide height\n");
+ return 1;
+ }
+
+ node = find_node(root, "stylesheet");
+ if ( node != NULL ) {
+ free_stylesheet(p->ss);
+ p->ss = tree_to_stylesheet(node);
+ if ( p->ss == NULL ) {
+ fprintf(stderr, "Invalid style sheet\n");
+ return 1;
+ }
+ }
return 0;
}
@@ -302,6 +530,9 @@ int load_presentation(struct presentation *p, const char *filename)
{
FILE *fh;
struct ds_node *root;
+ int r;
+
+ assert(p->completely_empty);
fh = fopen(filename, "r");
if ( fh == NULL ) return 1;
@@ -314,8 +545,13 @@ int load_presentation(struct presentation *p, const char *filename)
return 1;
}
+ r = tree_to_presentation(root, p);
+ free_ds_tree(root);
+
fclose(fh);
+ if ( r ) return r; /* Error */
+
p->cur_edit_slide = p->slides[0];
return 0;
diff --git a/src/presentation.c b/src/presentation.c
index 9782b81..2dacde2 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -237,6 +237,7 @@ struct presentation *new_presentation()
new->drag_status = DRAG_STATUS_NONE;
new->ss = new_stylesheet();
+ default_stylesheet(new->ss);
new->image_store = image_store_new();
return new;
diff --git a/src/presentation.h b/src/presentation.h
index fdf36b3..804cc4b 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -183,4 +183,6 @@ extern struct object *find_object_at_position(struct slide *s,
extern int slide_number(struct presentation *p, struct slide *s);
+#define UNUSED __attribute__((unused))
+
#endif /* PRESENTATION_H */
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 61b37fe..323b3a4 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -409,7 +409,7 @@ static gint destroy_stylesheet_sig(GtkWidget *w, struct _stylesheetwindow *s)
}
-static struct style *new_style(StyleSheet *ss, const char *name)
+struct style *new_style(StyleSheet *ss, const char *name)
{
struct style *sty;
int n;
@@ -435,7 +435,21 @@ static struct style *new_style(StyleSheet *ss, const char *name)
}
-static void default_stylesheet(StyleSheet *ss)
+void free_stylesheet(StyleSheet *ss)
+{
+ int i;
+
+ for ( i=0; i<ss->n_styles; i++ ) {
+ free(ss->styles[i]->name);
+ free(ss->styles[i]);
+ }
+
+ free(ss->styles);
+ free(ss);
+}
+
+
+void default_stylesheet(StyleSheet *ss)
{
struct style *sty;
@@ -568,7 +582,6 @@ StyleSheet *new_stylesheet()
ss->n_styles = 0;
ss->styles = NULL;
- default_stylesheet(ss);
return ss;
}
@@ -668,6 +681,16 @@ static const char *str_halign(enum justify halign)
}
+enum justify str_to_halign(char *halign)
+{
+ if ( strcmp(halign, "left") == 0 ) return J_LEFT;
+ if ( strcmp(halign, "right") == 0 ) return J_RIGHT;
+ if ( strcmp(halign, "center") == 0 ) return J_CENTER;
+
+ return J_LEFT;
+}
+
+
static const char *str_valign(enum vert_pos valign)
{
switch ( valign ) {
@@ -679,6 +702,16 @@ static const char *str_valign(enum vert_pos valign)
}
+enum vert_pos str_to_valign(char *valign)
+{
+ if ( strcmp(valign, "top") == 0 ) return V_TOP;
+ if ( strcmp(valign, "bottom") == 0 ) return V_BOTTOM;
+ if ( strcmp(valign, "center") == 0 ) return V_CENTER;
+
+ return J_LEFT;
+}
+
+
void write_stylesheet(StyleSheet *ss, struct serializer *ser)
{
int i;
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 224083a..cde0bcc 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -87,10 +87,19 @@ extern StylesheetWindow *open_stylesheet(struct presentation *p);
extern StyleSheet *new_stylesheet();
extern StyleSheet *load_stylesheet(const char *filename);
+extern void free_stylesheet(StyleSheet *ss);
+extern void default_stylesheet(StyleSheet *ss);
+
+extern struct style *new_style(StyleSheet *ss, const char *name);
+
extern int save_stylesheet(StyleSheet *ss, const char *filename);
extern struct style *find_style(StyleSheet *ss, const char *name);
+extern enum justify str_to_halign(char *halign);
+extern enum vert_pos str_to_valign(char *valign);
+
+
extern void write_stylesheet(StyleSheet *ss, struct serializer *ser);
#endif /* STYLESHEET_H */