diff options
-rw-r--r-- | src/loadsave.c | 298 | ||||
-rw-r--r-- | src/loadsave.h | 13 | ||||
-rw-r--r-- | src/mainwindow.c | 39 | ||||
-rw-r--r-- | src/stylesheet.c | 21 | ||||
-rw-r--r-- | src/stylesheet.h | 1 | ||||
-rw-r--r-- | src/tool_text.c | 18 |
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); |