aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2012-09-08 11:07:54 +0200
committerThomas White <taw@bitwiz.org.uk>2012-09-08 11:07:54 +0200
commit017121b0816250ddcc8a08746a6f140e48ca2d9e (patch)
tree15ccd482f6ee023c954905b3c89c385db8c61bbb /src
parent0a6d0255787a7b95a31ab317ed83463109c9fc01 (diff)
Plug in stylesheets and load/save
Diffstat (limited to 'src')
-rw-r--r--src/loadsave.c818
-rw-r--r--src/loadsave.h75
-rw-r--r--src/mainwindow.c40
-rw-r--r--src/presentation.c7
-rw-r--r--src/presentation.h22
-rw-r--r--src/stylesheet.c247
-rw-r--r--src/stylesheet.h29
7 files changed, 1188 insertions, 50 deletions
diff --git a/src/loadsave.c b/src/loadsave.c
new file mode 100644
index 0000000..8200200
--- /dev/null
+++ b/src/loadsave.c
@@ -0,0 +1,818 @@
+/*
+ * loadsave.c
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "presentation.h"
+#include "stylesheet.h"
+#include "mainwindow.h"
+
+
+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)
+{
+ struct ds_node *new;
+
+ new = malloc(sizeof(*new));
+ if ( new == NULL ) return NULL;
+
+ new->key = strdup(key);
+ if ( new->key == NULL ) {
+ free(new);
+ return 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);
+ if ( new == 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;
+}
+
+
+void show_tree(struct ds_node *root, const char *path)
+{
+ char newpath[1024];
+ int i;
+
+ snprintf(newpath, 1023, "%s%s/", path, root->key);
+
+ printf("%s\n", newpath);
+ for ( i=0; i<root->n_children; i++ ) {
+ printf(" %s => %s\n", 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");
+ show_tree(root->children[i], newpath);
+ }
+ }
+}
+
+
+struct ds_node *find_node(struct ds_node *root, const char *path, int cr)
+{
+ size_t start, len;
+ char element[1024];
+ struct ds_node *cur = root;
+
+ len = strlen(path);
+
+ 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' ) {
+ goto out;
+ }
+ start = i+1;
+
+ 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 ) {
+
+ if ( cr ) {
+ cur = add_child(cur, element);
+ if ( cur == NULL ) {
+ return NULL; /* Error */
+ }
+ } else {
+ return NULL;
+ }
+
+ }
+
+ }
+
+out:
+ return cur;
+}
+
+
+static void parse_line(struct ds_node *root, struct ds_node **cn,
+ const char *line)
+{
+ size_t i;
+ 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;
+ struct ds_node *cur_node = *cn;
+
+ len = strlen(line);
+
+ s_start = len;
+
+ for ( i=0; i<len; 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);
+ return;
+ }
+
+ if ( !h_openbracket && !h_equals ) return;
+
+ if ( !h_openbracket && (!h_start || !h_val || !h_equals) ) {
+ fprintf(stderr, "Incomplete assignment: %s", line);
+ return;
+ }
+
+ if ( h_equals && (h_openbracket || h_closebracket) ) {
+ fprintf(stderr, "Brackets and equals: %s", line);
+ return;
+ }
+
+ if ( !h_openbracket ) {
+
+ size_t pos = 0;
+ char *key;
+ char *value;
+ struct ds_node *node;
+
+ key = malloc(len);
+ value = malloc(len);
+
+ 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, 1);
+ node->value = strdup(value);
+
+ free(key);
+ free(value);
+
+ } else {
+
+ size_t pos = 0;
+ char *path;
+
+ path = malloc(len);
+
+ for ( i=s_openbracket+1; i<s_closebracket; i++ ) {
+ if ( !isspace(line[i]) ) path[pos++] = line[i];
+ }
+ path[pos] = '\0';
+ cur_node = find_node(root, path, 1);
+
+ free(path);
+
+ }
+
+ *cn = cur_node;
+}
+
+
+static char *fgets_long(FILE *fh)
+{
+ char *line;
+ size_t la, l;
+
+ la = 1024;
+ line = malloc(la);
+ if ( line == NULL ) return NULL;
+
+ l = 0;
+ do {
+
+ int r;
+
+ r = fgetc(fh);
+ if ( r == EOF ) {
+ free(line);
+ return NULL;
+ }
+
+ if ( r == '\n' ) {
+ line[l++] = '\0';
+ return line;
+ }
+
+ line[l++] = r;
+
+ if ( l == la ) {
+
+ char *ln;
+
+ la += 1024;
+ ln = realloc(line, la);
+ if ( ln == NULL ) {
+ free(line);
+ return NULL;
+ }
+
+ line = ln;
+
+ }
+
+ } while ( 1 );
+}
+
+
+static int deserialize_file(FILE *fh, struct ds_node *root)
+{
+ char *line;
+ struct ds_node *cur_node = root;
+
+ line = NULL;
+ do {
+
+ line = fgets_long(fh);
+ if ( line == NULL ) {
+ if ( ferror(fh) ) printf("Read error!\n");
+ continue;
+ }
+
+ parse_line(root, &cur_node, line);
+
+ } while ( line != NULL );
+
+ 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);
+}
+
+
+char *escape_text(const char *a)
+{
+ char *b;
+ size_t l1, l, i;
+
+ l1 = strlen(a);
+
+ b = malloc(2*l1 + 1);
+ l = 0;
+
+ for ( i=0; i<l1; i++ ) {
+
+ char c = a[i];
+
+ /* Yes, this is horribly confusing */
+ if ( c == '\n' ) {
+ b[l++] = '\\'; b[l++] = 'n';
+ } else if ( c == '\r' ) {
+ b[l++] = '\\'; b[l++] = 'r';
+ } else if ( c == '\"' ) {
+ b[l++] = '\\'; b[l++] = '\"';
+ } else if ( c == '\t' ) {
+ b[l++] = '\\'; b[l++] = 't';
+ } else {
+ b[l++] = c;
+ }
+
+ }
+ b[l++] = '\0';
+
+ return realloc(b, l);
+}
+
+
+char *unescape_text(const char *a)
+{
+ char *b;
+ size_t l1, l, i;
+ int escape;
+
+ l1 = strlen(a);
+
+ b = malloc(l1 + 1);
+ l = 0;
+ escape = 0;
+
+ for ( i=0; i<l1; i++ ) {
+
+ char c = a[i];
+
+ if ( escape ) {
+ if ( c == 'r' ) b[l++] = '\r';
+ if ( c == 'n' ) b[l++] = '\n';
+ if ( c == '\"' ) b[l++] = '\"';
+ if ( c == 't' ) b[l++] = '\t';
+ escape = 0;
+ continue;
+ }
+
+ if ( c == '\\' ) {
+ escape = 1;
+ continue;
+ }
+
+ b[l++] = c;
+
+ }
+ b[l++] = '\0';
+
+ return realloc(b, l);
+}
+
+
+
+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, 0);
+ 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;
+}
+
+
+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, 0);
+ 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;
+}
+
+
+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, 0);
+ if ( node == NULL ) {
+ *val = NULL;
+ 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, "Mismatched 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 = unescape_text(v);
+ free(v);
+
+ return 0;
+}
+
+
+static struct slide *tree_to_slide(struct presentation *p, struct ds_node *root)
+{
+ struct slide *s;
+
+ s = new_slide();
+ s->parent = p;
+
+ /* FIXME: Load stuff */
+
+ return s;
+}
+
+
+static int tree_to_slides(struct ds_node *root, struct presentation *p)
+{
+ int i;
+
+ for ( i=0; i<root->n_children; i++ ) {
+
+ struct slide *s;
+
+ s = tree_to_slide(p, root->children[i]);
+ if ( s != NULL ) {
+ insert_slide(p, s, p->num_slides-1);
+ }
+
+ }
+
+ return 0;
+}
+
+
+int tree_to_presentation(struct ds_node *root, struct presentation *p)
+{
+ struct ds_node *node;
+ char *check;
+ int i;
+
+ p->cur_edit_slide = NULL;
+ p->cur_proj_slide = NULL;
+
+ node = find_node(root, "slide-properties/width", 0);
+ 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", 0);
+ 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", 0);
+ 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;
+ }
+ }
+
+ for ( i=0; i<p->num_slides; i++ ) {
+ free_slide(p->slides[i]);
+ p->num_slides = 0;
+ }
+
+ node = find_node(root, "slides", 0);
+ if ( node != NULL ) {
+ tree_to_slides(node, p);
+ if ( p->num_slides == 0 ) {
+ fprintf(stderr, "Failed to load any slides\n");
+ p->cur_edit_slide = add_slide(p, 0);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+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;
+
+ root = new_ds_node("root");
+ if ( root == NULL ) return 1;
+
+ if ( deserialize_file(fh, root) ) {
+ fclose(fh);
+ return 1;
+ }
+
+ r = tree_to_presentation(root, p);
+ free_ds_tree(root);
+
+ fclose(fh);
+
+ if ( r ) {
+ p->cur_edit_slide = new_slide();
+ insert_slide(p, p->cur_edit_slide, 0);
+ p->completely_empty = 1;
+ return r; /* Error */
+ }
+
+ assert(p->filename == NULL);
+ p->filename = strdup(filename);
+ update_titlebar(p);
+
+ p->cur_edit_slide = p->slides[0];
+
+ return 0;
+}
+
+
+static void rebuild_prefix(struct serializer *ser)
+{
+ int i;
+ size_t sz = 1; /* Space for terminator */
+
+ for ( i=0; i<ser->stack_depth; i++ ) {
+ sz += strlen(ser->stack[i]) + 1;
+ }
+
+ free(ser->prefix);
+ ser->prefix = malloc(sz);
+ if ( ser->prefix == NULL ) return; /* Probably bad! */
+
+ ser->prefix[0] = '\0';
+ for ( i=0; i<ser->stack_depth; i++ ) {
+ if ( i != 0 ) strcat(ser->prefix, "/");
+ strcat(ser->prefix, ser->stack[i]);
+ }
+}
+
+
+void serialize_start(struct serializer *ser, const char *id)
+{
+ ser->stack[ser->stack_depth++] = strdup(id);
+ rebuild_prefix(ser);
+ ser->empty_set = 1;
+}
+
+
+static void check_prefix_output(struct serializer *ser)
+{
+ if ( ser->empty_set ) {
+ ser->empty_set = 0;
+ if ( ser->prefix != NULL ) {
+ fprintf(ser->fh, "\n");
+ fprintf(ser->fh, "[%s]\n", ser->prefix);
+ }
+ }
+}
+
+
+void serialize_s(struct serializer *ser, const char *key, const char *val)
+{
+ char *n;
+
+ n = escape_text(val);
+ if ( n == NULL ) {
+ fprintf(stderr, "Failed to escape '%s'\n", val);
+ return;
+ }
+
+ check_prefix_output(ser);
+ fprintf(ser->fh, "%s = \"%s\"\n", key, n);
+
+ free(n);
+}
+
+
+void serialize_f(struct serializer *ser, const char *key, double val)
+{
+ check_prefix_output(ser);
+ fprintf(ser->fh, "%s = %.2f\n", key, val);
+}
+
+
+void serialize_b(struct serializer *ser, const char *key, int val)
+{
+ check_prefix_output(ser);
+ fprintf(ser->fh, "%s = %i\n", key, val);
+}
+
+
+void serialize_end(struct serializer *ser)
+{
+ free(ser->stack[--ser->stack_depth]);
+ rebuild_prefix(ser);
+ ser->empty_set = 1;
+}
+
+
+int save_presentation(struct presentation *p, const char *filename)
+{
+ FILE *fh;
+ int i;
+ struct serializer ser;
+ char *old_fn;
+
+ //grab_current_notes(p);
+
+ 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 presentation file\n");
+ serialize_f(&ser, "version", 0.1);
+
+ serialize_start(&ser, "slide-properties");
+ serialize_f(&ser, "width", p->slide_width);
+ serialize_f(&ser, "height", p->slide_height);
+ serialize_end(&ser);
+
+ serialize_start(&ser, "stylesheet");
+ write_stylesheet(p->ss, &ser);
+ serialize_end(&ser);
+
+ serialize_start(&ser, "slides");
+ for ( i=0; i<p->num_slides; i++ ) {
+
+ struct slide *s;
+ char s_id[32];
+
+ s = p->slides[i];
+
+ snprintf(s_id, 31, "%i", i);
+ serialize_start(&ser, s_id);
+
+ /* FIXME: Save stuff */
+
+ serialize_end(&ser);
+
+ }
+ serialize_end(&ser);
+
+ /* Slightly fiddly because someone might
+ * do save_presentation(p, p->filename) */
+ old_fn = p->filename;
+ p->filename = strdup(filename);
+ if ( old_fn != NULL ) free(old_fn);
+ update_titlebar(p);
+
+ fclose(fh);
+ return 0;
+}
diff --git a/src/loadsave.h b/src/loadsave.h
new file mode 100644
index 0000000..14fb6ff
--- /dev/null
+++ b/src/loadsave.h
@@ -0,0 +1,75 @@
+/*
+ * loadsave.h
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LOADSAVE_H
+#define LOADSAVE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* Forward declaration */
+struct presentation;
+
+struct ds_node
+{
+ char *key;
+ char *value;
+ struct ds_node **children;
+ int n_children;
+ int max_children;
+};
+
+/* 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 show_tree(struct ds_node *root, const char *path);
+
+extern char *escape_text(const char *a);
+extern char *unescape_text(const char *a);
+
+extern void serialize_start(struct serializer *s, const char *id);
+extern void serialize_s(struct serializer *s, const char *key, const char *val);
+extern void serialize_f(struct serializer *s, const char *key, double val);
+extern void serialize_b(struct serializer *s, const char *key, int val);
+extern void serialize_end(struct serializer *s);
+
+extern int get_field_f(struct ds_node *root, const char *key, double *val);
+extern int get_field_i(struct ds_node *root, const char *key, int *val);
+extern int get_field_s(struct ds_node *root, const char *key, char **val);
+
+extern struct ds_node *find_node(struct ds_node *root, const char *path,
+ int cr);
+
+extern int load_presentation(struct presentation *p, const char *filename);
+extern int save_presentation(struct presentation *p, const char *filename);
+
+#endif /* LOADSAVE_H */
diff --git a/src/mainwindow.c b/src/mainwindow.c
index a5601a5..65a94df 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -94,8 +94,7 @@ static gint quit_sig(GtkWidget *widget, struct presentation *p)
}
-/* FIXME (unused) */
-static UNUSED void show_error(struct presentation *p, const char *message)
+static void show_error(struct presentation *p, const char *message)
{
GtkWidget *window;
@@ -163,11 +162,11 @@ static gint open_response_sig(GtkWidget *d, gint response,
if ( p->completely_empty ) {
- /* FIXME */
- //if ( load_presentation(p, filename) ) {
- // show_error(p, "Failed to open presentation");
- //}
- //redraw_slide(p->cur_edit_slide);
+ if ( load_presentation(p, filename) ) {
+ show_error(p, "Failed to open presentation");
+ }
+ p->cur_edit_slide = p->slides[0];
+ redraw_slide(p->cur_edit_slide);
update_toolbar(p);
} else {
@@ -176,11 +175,11 @@ static gint open_response_sig(GtkWidget *d, gint response,
/* FIXME */
p = new_presentation();
- //if ( load_presentation(p, filename) ) {
- // show_error(p, "Failed to open presentation");
- //} else {
+ if ( load_presentation(p, filename) ) {
+ show_error(p, "Failed to open presentation");
+ } else {
open_mainwindow(p);
- //}
+ }
}
@@ -238,10 +237,9 @@ static gint saveas_response_sig(GtkWidget *d, gint response,
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
- /* FIXME */
- //if ( save_presentation(p, filename) ) {
- // show_error(p, "Failed to save presentation");
- //}
+ if ( save_presentation(p, filename) ) {
+ show_error(p, "Failed to save presentation");
+ }
g_free(filename);
@@ -281,8 +279,7 @@ static gint save_sig(GtkWidget *widget, struct presentation *p)
return saveas_sig(widget, p);
}
- /* FIXME */
- //save_presentation(p, p->filename);
+ save_presentation(p, p->filename);
return 0;
}
@@ -432,9 +429,9 @@ void notify_slide_changed(struct presentation *p, struct slide *np)
update_toolbar(p);
redraw_slide(p->cur_edit_slide);
- if ( p->notes != NULL ) {
- //notify_notes_slide_changed(p, np);
- }
+ //if ( p->notes != NULL ) {
+ // notify_notes_slide_changed(p, np);
+ //}
if ( (p->slideshow != NULL) && p->slideshow_linked ) {
//notify_slideshow_slide_changed(p, np);
@@ -610,9 +607,6 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
gtk_separator_tool_item_new(), -1);
- p->tbox = GTK_WIDGET(gtk_tool_item_new());
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(p->tbox), -1);
-
/* Add the styles to the "Insert" menu */
menu = gtk_ui_manager_get_widget(p->ui, "/displaywindow/insert");
menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
diff --git a/src/presentation.c b/src/presentation.c
index 01a8fbf..405cf49 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -62,7 +62,7 @@ void free_presentation(struct presentation *p)
int insert_slide(struct presentation *p, struct slide *new, int pos)
{
struct slide **try;
-
+
try = realloc(p->slides, (1+p->num_slides)*sizeof(struct slide *));
if ( try == NULL ) {
free(new);
@@ -207,7 +207,6 @@ struct presentation *new_presentation()
new->ui = NULL;
new->action_group = NULL;
new->slideshow = NULL;
- new->notes = NULL;
new->slide_width = 1024.0;
new->slide_height = 768.0;
@@ -220,8 +219,8 @@ struct presentation *new_presentation()
new->completely_empty = 1;
- //new->ss = new_stylesheet();
- //default_stylesheet(new->ss);
+ new->ss = new_stylesheet();
+ default_stylesheet(new->ss);
return new;
}
diff --git a/src/presentation.h b/src/presentation.h
index d8fe5c4..62237c0 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -33,6 +33,7 @@
struct frame;
#include "layout.h"
+#include "stylesheet.h"
struct slide
{
@@ -83,20 +84,11 @@ struct presentation
int completely_empty;
int *num_presentations;
- struct prefs *prefs;
-
- struct toolinfo *select_tool;
- struct toolinfo *text_tool;
- struct toolinfo *image_tool;
-
GtkWidget *window;
GtkWidget *drawingarea;
GtkUIManager *ui;
GtkActionGroup *action_group;
GtkIMContext *im_context;
- GtkWidget *tbox;
- GtkWidget *cur_tbox;
- struct notes *notes;
/* Pointers to the current "editing" and "projection" slides */
struct slide *cur_edit_slide;
@@ -126,17 +118,7 @@ struct presentation
int ss_blank;
char ss_geom[256];
- /* Tool status */
- struct toolinfo *cur_tool;
-
- /* Stuff to do with drag and drop import of "content" */
- int drag_preview_pending;
- int have_drag_data;
- int drag_highlight;
- double import_width;
- double import_height;
- int import_acceptable;
-
+ StyleSheet *ss;
unsigned int num_slides;
struct slide **slides;
};
diff --git a/src/stylesheet.c b/src/stylesheet.c
new file mode 100644
index 0000000..8cf519f
--- /dev/null
+++ b/src/stylesheet.c
@@ -0,0 +1,247 @@
+/*
+ * stylesheet.c
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+
+#include "presentation.h"
+#include "stylesheet.h"
+#include "loadsave.h"
+
+
+struct style *new_style(StyleSheet *ss, const char *name)
+{
+ struct style *sty;
+ int n;
+ struct style **styles_new;
+
+ sty = calloc(1, sizeof(*sty));
+ if ( sty == NULL ) return NULL;
+
+ sty->name = strdup(name);
+
+ n = ss->n_styles;
+ styles_new = realloc(ss->styles, (n+1)*sizeof(sty));
+ if ( styles_new == NULL ) {
+ free(sty->name);
+ free(sty);
+ return NULL;
+ }
+ ss->styles = styles_new;
+ ss->styles[n] = sty;
+ ss->n_styles = n+1;
+
+ return sty;
+}
+
+
+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;
+
+ /* Default style must be first */
+ sty = new_style(ss, "Default");
+ sty->lop.margin_l = 20.0;
+ sty->lop.margin_r = 20.0;
+ sty->lop.margin_t = 20.0;
+ sty->lop.margin_b = 20.0;
+
+ sty = new_style(ss, "Slide title");
+ sty->lop.margin_l = 20.0;
+ sty->lop.margin_r = 20.0;
+ sty->lop.margin_t = 20.0;
+ sty->lop.margin_b = 20.0;
+}
+
+
+static int read_style(struct style *sty, struct ds_node *root)
+{
+ get_field_f(root, "margin_l", &sty->lop.margin_l);
+ get_field_f(root, "margin_r", &sty->lop.margin_r);
+ get_field_f(root, "margin_t", &sty->lop.margin_t);
+ get_field_f(root, "margin_b", &sty->lop.margin_b);
+
+ return 0;
+}
+
+
+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", 0);
+ 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;
+ }
+
+ }
+
+ node = find_node(root, "bgblocks", 0);
+ if ( node == NULL ) {
+ fprintf(stderr, "Couldn't find bgblocks\n");
+ free_stylesheet(ss);
+ return NULL;
+ }
+
+ return ss;
+}
+
+
+StyleSheet *new_stylesheet()
+{
+ StyleSheet *ss;
+
+ ss = calloc(1, sizeof(struct _stylesheet));
+ if ( ss == NULL ) return NULL;
+
+ ss->n_styles = 0;
+ ss->styles = NULL;
+
+ return ss;
+}
+
+
+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;
+}
+
+
+StyleSheet *load_stylesheet(const char *filename)
+{
+ StyleSheet *ss;
+
+ ss = new_stylesheet();
+ if ( ss == NULL ) return NULL;
+
+ /* FIXME: Implement this */
+
+ return ss;
+}
+
+
+void write_stylesheet(StyleSheet *ss, struct serializer *ser)
+{
+ int i;
+
+ serialize_start(ser, "styles");
+ for ( i=0; i<ss->n_styles; i++ ) {
+
+ struct style *s = ss->styles[i];
+ char id[32];
+
+ snprintf(id, 31, "%i", i);
+
+ serialize_start(ser, id);
+ serialize_s(ser, "name", s->name);
+ serialize_f(ser, "margin_l", s->lop.margin_l);
+ serialize_f(ser, "margin_r", s->lop.margin_r);
+ serialize_f(ser, "margin_t", s->lop.margin_t);
+ serialize_f(ser, "margin_b", s->lop.margin_b);
+ serialize_end(ser);
+
+ }
+ serialize_end(ser);
+}
+
+
+struct style *find_style(StyleSheet *ss, const char *name)
+{
+ int i;
+ for ( i=0; i<ss->n_styles; i++ ) {
+ if ( strcmp(ss->styles[i]->name, name) == 0 ) {
+ return ss->styles[i];
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/stylesheet.h b/src/stylesheet.h
index f2f72b2..58f4c13 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -3,7 +3,7 @@
*
* Colloquium - A tiny presentation program
*
- * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ * Copyright (c) 2012 Thomas White <taw@bitwiz.org.uk>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
struct frame;
#include "layout.h"
+#include "loadsave.h"
struct style
@@ -50,13 +51,35 @@ struct slide_template
struct frame_class **frame_classes;
int n_frame_classes;
+};
+
- struct bgblock **bgblocks;
- int n_bgblocks;
+struct _stylesheet
+{
+ struct style **styles;
+ int n_styles;
};
typedef struct _stylesheet StyleSheet;
struct presentation;
+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 StyleSheet *tree_to_stylesheet(struct ds_node *root);
+extern void write_stylesheet(StyleSheet *ss, struct serializer *ser);
+
+
#endif /* STYLESHEET_H */