diff options
author | Thomas White <taw@bitwiz.org.uk> | 2012-09-08 11:07:54 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2012-09-08 11:07:54 +0200 |
commit | 017121b0816250ddcc8a08746a6f140e48ca2d9e (patch) | |
tree | 15ccd482f6ee023c954905b3c89c385db8c61bbb | |
parent | 0a6d0255787a7b95a31ab317ed83463109c9fc01 (diff) |
Plug in stylesheets and load/save
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | src/loadsave.c | 818 | ||||
-rw-r--r-- | src/loadsave.h | 75 | ||||
-rw-r--r-- | src/mainwindow.c | 40 | ||||
-rw-r--r-- | src/presentation.c | 7 | ||||
-rw-r--r-- | src/presentation.h | 22 | ||||
-rw-r--r-- | src/stylesheet.c | 247 | ||||
-rw-r--r-- | src/stylesheet.h | 29 |
8 files changed, 1191 insertions, 52 deletions
diff --git a/Makefile.am b/Makefile.am index f565eb7..2111532 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,12 +10,13 @@ AM_CPPFLAGS = -DDATADIR=\""$(datadir)"\" -I$(top_builddir)/lib \ LDADD = $(top_builddir)/lib/libgnu.a @IGNORE_UNUSED_LIBRARIES_CFLAGS@ src_colloquium_SOURCES = src/colloquium.c src/storycode.c src/render.c \ - src/layout.c src/mainwindow.c src/presentation.c + src/layout.c src/mainwindow.c src/presentation.c \ + src/stylesheet.c src/loadsave.c INCLUDES = "-I$(top_srcdir)/data" EXTRA_DIST += src/layout.h src/presentation.h src/render.h src/storycode.h \ - src/stylesheet.h + src/stylesheet.h src/loadsave.h colloquiumdir = $(datadir)/colloquium colloquium_DATA = data/colloquium.ui 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 */ |