Fix stylesheet
[colloquium.git] / src / stylesheet.c
1 /*
2  * stylesheet.c
3  *
4  * Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
5  *
6  * This file is part of Colloquium.
7  *
8  * Colloquium is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <gtk/gtk.h>
31 #include <assert.h>
32
33 #include "presentation.h"
34 #include "stylesheet.h"
35 #include "loadsave.h"
36
37
38 struct _stylesheet
39 {
40         struct style          **styles;
41         int                     n_styles;
42
43         struct slide_template **templates;
44         int                     n_templates;
45 };
46
47
48 struct style *new_style(StyleSheet *ss, const char *name)
49 {
50         struct style *sty;
51         int n;
52         struct style **styles_new;
53
54         sty = calloc(1, sizeof(*sty));
55         if ( sty == NULL ) return NULL;
56
57         sty->name = strdup(name);
58
59         /* DS9K compatibility */
60         sty->lop.x = 0.0;
61         sty->lop.y = 0.0;
62         sty->lop.w = 100.0;
63         sty->lop.h = 100.0;
64
65         n = ss->n_styles;
66         styles_new = realloc(ss->styles, (n+1)*sizeof(sty));
67         if ( styles_new == NULL ) {
68                 free(sty->name);
69                 free(sty);
70                 return NULL;
71         }
72         ss->styles = styles_new;
73         ss->styles[n] = sty;
74         ss->n_styles = n+1;
75
76         return sty;
77 }
78
79
80 void free_stylesheet(StyleSheet *ss)
81 {
82         int i;
83
84         for ( i=0; i<ss->n_styles; i++ ) {
85                 free(ss->styles[i]->name);
86                 free(ss->styles[i]->sc_prologue);
87                 free(ss->styles[i]);
88         }
89
90         free(ss->styles);
91         free(ss);
92 }
93
94
95 void default_stylesheet(StyleSheet *ss)
96 {
97         struct style *sty;
98         struct slide_template *titlepage;
99         struct slide_template *slide;
100         struct slide_template *acknowledgements;
101
102         titlepage = new_template(ss, "Title page");
103         slide = new_template(ss, "Slide");
104         acknowledgements = new_template(ss, "Acknowledgements");
105
106         sty = new_style(ss, "Presentation title");
107         sty->lop.margin_l = 0.0;
108         sty->lop.margin_r = 0.0;
109         sty->lop.margin_t = 0.0;
110         sty->lop.margin_b = 0.0;
111         sty->lop.pad_l = 0.0;
112         sty->lop.pad_r = 0.0;
113         sty->lop.pad_t = 0.0;
114         sty->lop.pad_b = 0.0;
115         sty->lop.w = 1.0;
116         sty->lop.w_units = UNITS_FRAC;
117         sty->lop.h = 100.0;
118         sty->lop.h_units = UNITS_SLIDE;
119         sty->lop.x = 0.0;
120         sty->lop.y = 300.0;
121         sty->sc_prologue = strdup("\\font[Sorts Mill Goudy 64]");
122         add_to_template(titlepage, sty);
123
124         sty = new_style(ss, "Slide title");
125         sty->lop.margin_l = 0.0;
126         sty->lop.margin_r = 0.0;
127         sty->lop.margin_t = 0.0;
128         sty->lop.margin_b = 0.0;
129         sty->lop.pad_l = 20.0;
130         sty->lop.pad_r = 20.0;
131         sty->lop.pad_t = 20.0;
132         sty->lop.pad_b = 20.0;
133         sty->lop.w = 1.0;
134         sty->lop.w_units = UNITS_FRAC;
135         sty->lop.h = 100.0;
136         sty->lop.h_units = UNITS_SLIDE;
137         sty->lop.x = 0.0;
138         sty->lop.y = 0.0;
139         sty->sc_prologue = strdup("\\bgcol{#00a6eb}\\fgcol{#ffffff}"
140                                   "\\font[Sans 40]");
141         add_to_template(slide, sty);
142
143         sty = new_style(ss, "Slide title");
144         sty->lop.margin_r = 0.0;
145         sty->lop.margin_t = 0.0;
146         sty->lop.margin_b = 0.0;
147         sty->lop.pad_l = 20.0;
148         sty->lop.pad_r = 20.0;
149         sty->lop.pad_t = 20.0;
150         sty->lop.pad_b = 20.0;
151         sty->lop.w = 1.0;
152         sty->lop.w_units = UNITS_FRAC;
153         sty->lop.h = 100.0;
154         sty->lop.h_units = UNITS_SLIDE;
155         sty->lop.x = 0.0;
156         sty->lop.y = 0.0;
157         sty->sc_prologue = strdup("\\bgcol{#00a6eb}\\fgcol{#ffffff}"
158                                   "\\font[Sans 40]Acknowledgements");
159         add_to_template(acknowledgements, sty);
160
161         sty = new_style(ss, "Content");
162         sty->lop.margin_l = 0.0;
163         sty->lop.margin_r = 0.0;
164         sty->lop.margin_t = 0.0;
165         sty->lop.margin_b = 0.0;
166         sty->lop.pad_l = 20.0;
167         sty->lop.pad_r = 20.0;
168         sty->lop.pad_t = 20.0;
169         sty->lop.pad_b = 20.0;
170         sty->lop.w = 1.0;
171         sty->lop.w_units = UNITS_FRAC;
172         sty->lop.h = 1.0;
173         sty->lop.h_units = UNITS_FRAC;
174         sty->lop.x = 0.0;
175         sty->lop.y = 0.0;
176         sty->sc_prologue = strdup("\\bgcol{#00a6eb}\\fgcol{#ffffff}"
177                                   "\\font[Sans 24]");
178         add_to_template(acknowledgements, sty);
179 }
180
181
182 static int read_style(struct style *sty, struct ds_node *root)
183 {
184         get_field_f(root, "margin_l", &sty->lop.margin_l);
185         get_field_f(root, "margin_r", &sty->lop.margin_r);
186         get_field_f(root, "margin_t", &sty->lop.margin_t);
187         get_field_f(root, "margin_b", &sty->lop.margin_b);
188
189         return 0;
190 }
191
192
193 StyleSheet *tree_to_stylesheet(struct ds_node *root)
194 {
195         StyleSheet *ss;
196         struct ds_node *node;
197         int i;
198
199         ss = new_stylesheet();
200         if ( ss == NULL ) return NULL;
201
202         node = find_node(root, "styles", 0);
203         if ( node == NULL ) {
204                 fprintf(stderr, "Couldn't find styles\n");
205                 free_stylesheet(ss);
206                 return NULL;
207         }
208
209         for ( i=0; i<node->n_children; i++ ) {
210
211                 struct style *ns;
212                 char *v;
213
214                 get_field_s(node->children[i], "name", &v);
215                 if ( v == NULL ) {
216                         fprintf(stderr, "No name for style '%s'\n",
217                                 node->children[i]->key);
218                         continue;
219                 }
220
221                 ns = new_style(ss, v);
222                 if ( ns == NULL ) {
223                         fprintf(stderr, "Couldn't create style for '%s'\n",
224                                 node->children[i]->key);
225                         continue;
226                 }
227
228                 if ( read_style(ns, node->children[i]) ) {
229                         fprintf(stderr, "Couldn't read style '%s'\n", v);
230                         continue;
231                 }
232
233         }
234
235         node = find_node(root, "bgblocks", 0);
236         if ( node == NULL ) {
237                 fprintf(stderr, "Couldn't find bgblocks\n");
238                 free_stylesheet(ss);
239                 return NULL;
240         }
241
242         return ss;
243 }
244
245
246 StyleSheet *new_stylesheet()
247 {
248         StyleSheet *ss;
249
250         ss = calloc(1, sizeof(struct _stylesheet));
251         if ( ss == NULL ) return NULL;
252
253         ss->n_styles = 0;
254         ss->styles = NULL;
255
256         return ss;
257 }
258
259
260 int save_stylesheet(StyleSheet *ss, const char *filename)
261 {
262         FILE *fh;
263         struct serializer ser;
264
265         fh = fopen(filename, "w");
266         if ( fh == NULL ) return 1;
267
268         /* Set up the serializer */
269         ser.fh = fh;
270         ser.stack_depth = 0;
271         ser.prefix = NULL;
272
273         fprintf(fh, "# Colloquium style sheet file\n");
274         serialize_f(&ser, "version", 0.1);
275
276         serialize_start(&ser, "stylesheet");
277         write_stylesheet(ss, &ser);
278         serialize_end(&ser);
279
280         return 0;
281 }
282
283
284 StyleSheet *load_stylesheet(const char *filename)
285 {
286         StyleSheet *ss;
287
288         ss = new_stylesheet();
289         if ( ss == NULL ) return NULL;
290
291         /* FIXME: Implement this */
292
293         return ss;
294 }
295
296
297 void write_stylesheet(StyleSheet *ss, struct serializer *ser)
298 {
299         int i;
300
301         serialize_start(ser, "styles");
302         for ( i=0; i<ss->n_styles; i++ ) {
303
304                 struct style *s = ss->styles[i];
305                 char id[32];
306
307                 snprintf(id, 31, "%i", i);
308
309                 serialize_start(ser, id);
310                 serialize_s(ser, "name", s->name);
311                 serialize_f(ser, "margin_l", s->lop.margin_l);
312                 serialize_f(ser, "margin_r", s->lop.margin_r);
313                 serialize_f(ser, "margin_t", s->lop.margin_t);
314                 serialize_f(ser, "margin_b", s->lop.margin_b);
315                 serialize_end(ser);
316
317         }
318         serialize_end(ser);
319 }
320
321
322 struct style *find_style(StyleSheet *ss, const char *name)
323 {
324         int i;
325         for ( i=0; i<ss->n_styles; i++ ) {
326                 if ( strcmp(ss->styles[i]->name, name) == 0 ) {
327                         return ss->styles[i];
328                 }
329         }
330
331         return NULL;
332 }
333
334
335 struct slide_template *new_template(StyleSheet *ss, const char *name)
336 {
337         struct slide_template *t;
338         int n;
339         struct slide_template **templates_new;
340
341         t = calloc(1, sizeof(*t));
342         if ( t == NULL ) return NULL;
343
344         t->name = strdup(name);
345
346         n = ss->n_templates;
347         templates_new = realloc(ss->templates, (n+1)*sizeof(t));
348         if ( templates_new == NULL ) {
349                 free(t->name);
350                 free(t);
351                 return NULL;
352         }
353         ss->templates = templates_new;
354         ss->templates[n] = t;
355         ss->n_templates = n+1;
356
357         return t;
358 }
359
360
361 void add_to_template(struct slide_template *t, struct style *sty)
362 {
363         int n;
364         struct style **styles_new;
365
366         n = t->n_styles;
367         styles_new = realloc(t->styles, (n+1)*sizeof(sty));
368         if ( styles_new == NULL ) {
369                 fprintf(stderr, "Failed to add style '%s' to template '%s'.\n",
370                         sty->name, t->name);
371                 return;
372         }
373         t->styles = styles_new;
374         t->styles[n] = sty;
375         t->n_styles = n+1;
376 }
377
378
379 struct _styleiterator
380 {
381         int n;
382 };
383
384 struct style *style_first(StyleSheet *ss, StyleIterator **piter)
385 {
386         StyleIterator *iter;
387
388         if ( ss->n_styles == 0 ) return NULL;
389
390         iter = calloc(1, sizeof(StyleIterator));
391         if ( iter == NULL ) return NULL;
392
393         iter->n = 0;
394         *piter = iter;
395
396         return ss->styles[0];
397 }
398
399
400 struct style *style_next(StyleSheet *ss, StyleIterator *iter)
401 {
402         iter->n++;
403         if ( iter->n == ss->n_styles ) {
404                 free(iter);
405                 return NULL;
406         }
407
408         return ss->styles[iter->n];
409 }
410
411
412 struct _templateiterator
413 {
414         int n;
415 };
416
417 struct slide_template *template_first(StyleSheet *ss, TemplateIterator **piter)
418 {
419         TemplateIterator *iter;
420
421         if ( ss->n_templates == 0 ) return NULL;
422
423         iter = calloc(1, sizeof(TemplateIterator));
424         if ( iter == NULL ) return NULL;
425
426         iter->n = 0;
427         *piter = iter;
428
429         return ss->templates[0];
430 }
431
432
433 struct slide_template *template_next(StyleSheet *ss, TemplateIterator *iter)
434 {
435         iter->n++;
436         if ( iter->n == ss->n_templates ) {
437                 free(iter);
438                 return NULL;
439         }
440
441         return ss->templates[iter->n];
442 }