aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2018-10-28 00:03:51 +0200
committerThomas White <taw@bitwiz.me.uk>2018-10-28 00:03:51 +0200
commit8e05062ad3b94068825a1f80eb362aa3d3e9098f (patch)
tree77944d65437fa57755a7bc8bc16fd3e2c5b43f17
parent791ee4e65f3ec7ef470302e4381baefb431fb56d (diff)
parent21418cfb52b87a32cfdc9bb14be83b85a8e70281 (diff)
Merge branch 'json-stylesheets'
-rw-r--r--data/colloquium.gresource.xml2
-rw-r--r--data/default.ss37
-rw-r--r--data/demo.sc23
-rw-r--r--data/demo.ss37
-rw-r--r--data/stylesheeteditor.ui1167
-rw-r--r--meson.build4
-rw-r--r--src/colloquium.c6
-rw-r--r--src/colloquium.h1
-rw-r--r--src/debugger.c23
-rw-r--r--src/frame.c212
-rw-r--r--src/frame.h27
-rw-r--r--src/narrative_window.c102
-rw-r--r--src/presentation.c136
-rw-r--r--src/presentation.h5
-rw-r--r--src/print.c12
-rw-r--r--src/render.c28
-rw-r--r--src/render.h4
-rw-r--r--src/sc_editor.c28
-rw-r--r--src/sc_editor.h11
-rw-r--r--src/sc_interp.c727
-rw-r--r--src/sc_interp.h29
-rw-r--r--src/sc_parse.c92
-rw-r--r--src/sc_parse.h7
-rw-r--r--src/slide_window.c2
-rw-r--r--src/slide_window.h1
-rw-r--r--src/stylesheet.c234
-rw-r--r--src/stylesheet.h48
-rw-r--r--src/stylesheet_editor.c594
-rw-r--r--src/stylesheet_editor.h29
-rw-r--r--src/utils.c92
-rw-r--r--src/utils.h3
-rw-r--r--tests/json_test.c102
-rw-r--r--tests/meson.build11
33 files changed, 1600 insertions, 2236 deletions
diff --git a/data/colloquium.gresource.xml b/data/colloquium.gresource.xml
index 369144b..819a966 100644
--- a/data/colloquium.gresource.xml
+++ b/data/colloquium.gresource.xml
@@ -5,6 +5,8 @@
<file>menus.ui</file>
<file>stylesheeteditor.ui</file>
<file>demo.sc</file>
+ <file>demo.ss</file>
+ <file>default.ss</file>
<file>canvas.png</file>
<file>alpha_warning.svg</file>
<file>colloquium.svg</file>
diff --git a/data/default.ss b/data/default.ss
new file mode 100644
index 0000000..77c3492
--- /dev/null
+++ b/data/default.ss
@@ -0,0 +1,37 @@
+{
+ "narrative": {
+ "font": "Cantarell Regular 16",
+ "fgcol": "#222222",
+ "pad": "10,10,10,10",
+ "paraspace": "0,0,10,10",
+ "bgcol": "#ffffff"
+ },
+
+ "slide": {
+ "size": "1280x720",
+ "bggradv": "#333333,#000055",
+ "frame": {
+ "font": "Cantarell Regular 14",
+ "pad": "0,0,0,0",
+ "fgcol": "#c5c5c5",
+ "bgcol": "rgba(0,0,0,0)",
+ "paraspace": "5,5,5,5"
+ },
+ "slidetitle": {
+ "geometry": "1fx90u+0+0",
+ "pad": "20,20,20,20",
+ "fgcol": "#eeeeee",
+ "font": "Cantarell Regular 36",
+ "bgcol": "rgba(0,0,0,0)"
+ },
+ "prestitle": {
+ "geometry": "1fx140u+0+0",
+ "pad": "20,20,20,20",
+ "fgcol": "#eeeeee",
+ "font": "Cantarell Regular 64",
+ "alignment": "center",
+ "bgcol": "rgba(0,0,0,0)"
+ },
+ "_comment": "Add footer, credit and bp"
+ }
+}
diff --git a/data/demo.sc b/data/demo.sc
index 805cfb4..e6a60a7 100644
--- a/data/demo.sc
+++ b/data/demo.sc
@@ -1,21 +1,4 @@
-\stylesheet{
-
- \style[narrative]{\font[Cantarell Regular 16]\paraspace[0,0,10,10]\pad[10,10,10,10]\fgcol[#222222]\bgcol[#ffffff]}
- \style[slide]{\bggradv[#333333,#000055]}
- \style[frame]{\fgcol[#c5c5c5]}
- \slidesize[1024x768]
-
- \def[prestitle]{\f[1fx140u+0+0]\pad[20,20,20,20]\fontsize[64]\fgcol[#eeeeee]\center\contents}
- \def[slidetitle]{\f[1fx90u+0+0]\pad[20,20,20,20]\fontsize[36]\fgcol[#eeeeee]\contents}
- \def[footer]{\f[0.97fx30u+0+740]{\ralign\editable{\fontsize[11]\bold{T. A. White} | \editable{A demonstration talk | 1 March 2018} | \bold{Slide} \slidenumber}}}
- \def[credit]{\f[600ux30u+700+700]{\fontsize[11]\contents}}
- \def[bp]{➤ }
-
- \template[slide]{\slide{\slidetitle{New slide}\footer}}
- \template[bp,name="Bullet point"]{\bp{}}
- \template[credit,name="Credit"]{\credit{Image: }}
-
-}\fontsize[40]{\bold{}Hi there, welcome to \bold{Colloquium}!}
+\fontsize[40]{\bold{}Hi there, welcome to \bold{Colloquium}!}
It looks like this is the first time you've used Colloquium. Keep reading to understand a little bit about how Colloquium works and how to use it.
Colloquium works differently to other presentation programs. Colloquium makes \italic{narrative, not slides,} the centre of attention. Slides come when you need to illustrate something. This window is called the \oblique{narrative editor}. Your slides are embedded into the narrative text, like this:\slide{
\prestitle{Welcome to Colloquium}
@@ -36,7 +19,7 @@ What is the narrative window for? Well, it's up to you! Here are some suggesti
\bp{}Use it as a journal, adding slides whenever you have an illustration. You'll have a ready-made presentation on your activity, with no extra effort!
Besides this, Colloquium has some features which will help you when you come to give your presentation. In the "Tools" menu, you'll find the presentation clock and the test card.
Use the test card to make sure your computer is talking to the projector correctly. It shows you the resolution of the screen, where it thinks the edges are, and some colours. This helps you spot and fix all-too-common display problems early.
-Now, a short warning:\slide{\slidetitle{Alpha test software}\footer\f[394.9ux428.0u+571.9+178.8]{Colloquium is "alpha test" software.
+Now, a short warning:\slide{\slidetitle{Alpha test software}\footer\f[391.8ux473.5u+567.8+143.7]{Colloquium is "alpha test" software.
It will probably crash and lose your work a few times. Save and back up your work as frequently as possible.
@@ -45,5 +28,5 @@ However, in years of use it has \bold{never} crashed on me in front of an audien
Creating a backup slide deck in PDF format (File->Export slides as PDF) is nevertheless a wise safety measure.
Please report all bugs here:
-https://www.bitwiz.me.uk/tracker}\f[452.2ux431.0u+64.8+168.9]{\image[1fx1f+0+0,filename="alpha_warning.svg"]{}}}
+https://github.com/taw10/colloquium/issues}\f[452.2ux431.0u+64.8+168.9]{\image[1fx1f+0+0,filename="alpha_warning.svg"]{}}\f[2.1ux10.3u+959.6+665.7]{}\f[0.0ux31.0u+957.5+654.3]{}}
That's enough to get you started. I hope you enjoy using Colloquium!
diff --git a/data/demo.ss b/data/demo.ss
new file mode 100644
index 0000000..507299d
--- /dev/null
+++ b/data/demo.ss
@@ -0,0 +1,37 @@
+{
+ "narrative": {
+ "font": "Cantarell Regular 16",
+ "fgcol": "#222222",
+ "pad": "10,10,10,10",
+ "paraspace": "0,0,10,10",
+ "bgcol": "#ffffff"
+ },
+
+ "slide": {
+ "size": "1024x768",
+ "bggradv": "#333333,#000055",
+ "frame": {
+ "font": "Cantarell Regular 14",
+ "pad": "0,0,0,0",
+ "fgcol": "#c5c5c5",
+ "bgcol": "#ffffff00",
+ "paraspace": "5,5,5,5"
+ },
+ "slidetitle": {
+ "geometry": "1fx90u+0+0",
+ "pad": "20,20,20,20",
+ "fgcol": "#eeeeee",
+ "font": "Cantarell Regular 36",
+ "bgcol": "#ffffff00"
+ },
+ "prestitle": {
+ "geometry": "1fx140u+0+0",
+ "pad": "20,20,20,20",
+ "fgcol": "#eeeeee",
+ "font": "Cantarell Regular 64",
+ "alignment": "center",
+ "bgcol": "#ffffff00"
+ },
+ "_comment": "Add footer, credit and bp"
+ }
+}
diff --git a/data/stylesheeteditor.ui b/data/stylesheeteditor.ui
index 6e61d79..19723bb 100644
--- a/data/stylesheeteditor.ui
+++ b/data/stylesheeteditor.ui
@@ -2,6 +2,96 @@
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment10">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment11">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment12">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment13">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment14">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment15">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment16">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment17">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment18">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment3">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment4">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment5">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment6">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment7">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment8">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment9">
+ <property name="upper">2000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
<template class="StylesheetEditor" parent="GtkDialog">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Stylesheet editor</property>
@@ -120,6 +210,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_alpha">True</property>
<signal name="color-set" handler="narrative_fgcol_sig" swapped="no"/>
</object>
<packing>
@@ -162,7 +253,7 @@
<item id="horiz" translatable="yes">Horizontal gradient</item>
<item id="vert" translatable="yes">Vertical gradient</item>
</items>
- <signal name="changed" handler="narrative_bggrad_sig" swapped="no"/>
+ <signal name="changed" handler="narrative_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@@ -175,7 +266,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="narrative_bgcol_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="narrative_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -188,7 +280,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="narrative_bgcol2_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="narrative_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -214,150 +307,114 @@
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="margin_right">40</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
<child>
- <object class="GtkBox">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_right">4</property>
- <property name="margin_bottom">4</property>
- <property name="orientation">vertical</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <property name="column_homogeneous">True</property>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Top:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Left:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Left:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Right:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Right:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">1</property>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Bottom:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Top:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">2</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Bottom:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_paraspace_l">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment1</property>
+ <signal name="value-changed" handler="narrative_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_paraspace_t">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment2</property>
+ <signal name="value-changed" handler="narrative_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_paraspace_r">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment3</property>
+ <signal name="value-changed" handler="narrative_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_paraspace_b">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment4</property>
+ <signal name="value-changed" handler="narrative_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
@@ -389,150 +446,114 @@
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="margin_right">40</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
<child>
- <object class="GtkBox">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_right">4</property>
- <property name="margin_bottom">4</property>
- <property name="orientation">vertical</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <property name="column_homogeneous">True</property>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Top:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Left:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Left:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Right:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Right:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">1</property>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Bottom:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Top:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">2</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Bottom:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_padding_l">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment5</property>
+ <signal name="value-changed" handler="narrative_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_padding_t">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment6</property>
+ <signal name="value-changed" handler="narrative_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_padding_r">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment7</property>
+ <signal name="value-changed" handler="narrative_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="narrative_style_padding_b">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment8</property>
+ <signal name="value-changed" handler="narrative_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
@@ -596,12 +617,14 @@
</packing>
</child>
<child>
- <object class="GtkSpinButton">
+ <object class="GtkSpinButton" id="slide_size_w">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">6</property>
+ <property name="adjustment">adjustment17</property>
<property name="numeric">True</property>
<property name="value">1024</property>
+ <signal name="value-changed" handler="slide_size_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -622,12 +645,14 @@
</packing>
</child>
<child>
- <object class="GtkSpinButton">
+ <object class="GtkSpinButton" id="slide_size_h">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">6</property>
+ <property name="adjustment">adjustment18</property>
<property name="numeric">True</property>
<property name="value">768</property>
+ <signal name="value-changed" handler="slide_size_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -681,7 +706,7 @@
<item id="horiz" translatable="yes">Horizontal gradient</item>
<item id="vert" translatable="yes">Vertical gradient</item>
</items>
- <signal name="changed" handler="slide_bggrad_sig" swapped="no"/>
+ <signal name="changed" handler="slide_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@@ -694,7 +719,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="slide_bgcol_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="slide_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -707,7 +733,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="slide_bgcol2_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="slide_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -723,27 +750,43 @@
<property name="position">1</property>
</packing>
</child>
- <child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Slides</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Frames within slides</property>
+ <property name="label" translatable="yes">This refers to the boxes you create within slides</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
@@ -783,6 +826,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_alpha">True</property>
<signal name="color-set" handler="frame_fgcol_sig" swapped="no"/>
</object>
<packing>
@@ -796,7 +840,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">4</property>
- <property name="position">4</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
@@ -824,9 +868,8 @@
<item id="flat" translatable="yes">Flat colour</item>
<item id="horiz" translatable="yes">Horizontal gradient</item>
<item id="vert" translatable="yes">Vertical gradient</item>
- <item id="none" translatable="yes">None</item>
</items>
- <signal name="changed" handler="frame_bggrad_sig" swapped="no"/>
+ <signal name="changed" handler="frame_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@@ -839,7 +882,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="frame_bgcol_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="frame_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -852,7 +896,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="color-set" handler="frame_bgcol2_sig" swapped="no"/>
+ <property name="use_alpha">True</property>
+ <signal name="color-set" handler="frame_bg_sig" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -865,7 +910,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">4</property>
- <property name="position">5</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
@@ -878,150 +923,114 @@
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="margin_right">40</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
<child>
- <object class="GtkBox">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_right">4</property>
- <property name="margin_bottom">4</property>
- <property name="orientation">vertical</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <property name="column_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Left:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Top:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Right:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Left:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Right:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Top:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Bottom:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Bottom:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_paraspace_l">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment9</property>
+ <signal name="value-changed" handler="frame_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_paraspace_t">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment10</property>
+ <signal name="value-changed" handler="frame_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_paraspace_r">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment11</property>
+ <signal name="value-changed" handler="frame_paraspace_sig" swapped="no"/>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">2</property>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_paraspace_b">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment12</property>
+ <signal name="value-changed" handler="frame_paraspace_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
@@ -1040,7 +1049,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">4</property>
- <property name="position">6</property>
+ <property name="position">3</property>
</packing>
</child>
<child>
@@ -1053,150 +1062,114 @@
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="margin_right">40</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
<child>
- <object class="GtkBox">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_right">4</property>
- <property name="margin_bottom">4</property>
- <property name="orientation">vertical</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <property name="column_homogeneous">True</property>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Top:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Left:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Left:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Right:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Right:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">1</property>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">5</property>
- <property name="label" translatable="yes">Bottom:</property>
- <property name="xalign">1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child type="center">
- <object class="GtkSpinButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Top:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">5</property>
- <property name="position">2</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Bottom:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_padding_l">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment13</property>
+ <signal name="value-changed" handler="frame_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_padding_t">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment14</property>
+ <signal name="value-changed" handler="frame_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_padding_r">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment15</property>
+ <signal name="value-changed" handler="frame_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="frame_style_padding_b">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment16</property>
+ <signal name="value-changed" handler="frame_padding_sig" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
@@ -1215,87 +1188,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">4</property>
- <property name="position">7</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Slides</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="orientation">vertical</property>
- <property name="spacing">8</property>
- <child>
- <object class="GtkComboBoxText">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="active">0</property>
- <items>
- <item translatable="yes">Presentation title</item>
- <item translatable="yes">Slide title</item>
- </items>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkAlignment">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkTextView">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="wrap_mode">char</property>
- <property name="left_margin">12</property>
- <property name="right_margin">12</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Storycode</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="padding">4</property>
- <property name="position">1</property>
+ <property name="position">4</property>
</packing>
</child>
</object>
@@ -1307,7 +1200,7 @@
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Style definitions</property>
+ <property name="label" translatable="yes">Frames</property>
</object>
<packing>
<property name="position">2</property>
@@ -1315,84 +1208,10 @@
</packing>
</child>
<child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="orientation">vertical</property>
- <property name="spacing">8</property>
- <child>
- <object class="GtkComboBoxText">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="active">0</property>
- <items>
- <item translatable="yes">Presentation title</item>
- <item translatable="yes">Slide title</item>
- </items>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkAlignment">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="left_padding">12</property>
- <property name="right_padding">12</property>
- <child>
- <object class="GtkTextView">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="wrap_mode">char</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Storycode</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="padding">4</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">3</property>
- </packing>
+ <placeholder/>
</child>
<child type="tab">
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Templates</property>
- </object>
- <packing>
- <property name="position">3</property>
- <property name="tab_fill">False</property>
- </packing>
+ <placeholder/>
</child>
</object>
<packing>
diff --git a/meson.build b/meson.build
index a2e3fb2..52b9243 100644
--- a/meson.build
+++ b/meson.build
@@ -19,6 +19,7 @@ subdir('po')
# Dependencies
gtkdep = dependency('gtk+-3.0')
+jsondep = dependency('json-glib-1.0')
cc = meson.get_compiler('c')
mdep = cc.find_library('m', required : false)
@@ -44,10 +45,11 @@ executable('colloquium',
'src/print.c',
'src/sc_parse.c',
'src/utils.c',
+ 'src/stylesheet.c',
'src/stylesheet_editor.c',
],
gresources,
- dependencies : [gtkdep, mdep],
+ dependencies : [gtkdep, mdep, jsondep],
install : true)
# Desktop file
diff --git a/src/colloquium.c b/src/colloquium.c
index 66e3dcb..a8da4d9 100644
--- a/src/colloquium.c
+++ b/src/colloquium.c
@@ -320,12 +320,6 @@ int colloquium_get_hidepointer(Colloquium *app)
}
-GtkBuilder *colloquium_get_uibuilder(Colloquium *app)
-{
- return app->builder;
-}
-
-
static void colloquium_startup(GApplication *papp)
{
Colloquium *app = COLLOQUIUM(papp);
diff --git a/src/colloquium.h b/src/colloquium.h
index 4c8133f..89f600f 100644
--- a/src/colloquium.h
+++ b/src/colloquium.h
@@ -38,7 +38,6 @@ typedef struct _colloquium Colloquium;
extern const char *colloquium_get_imagestore(Colloquium *app);
extern int colloquium_get_hidepointer(Colloquium *app);
-extern GtkBuilder *colloquium_get_uibuilder(Colloquium *app);
extern void open_about_dialog(GtkWidget *parent);
diff --git a/src/debugger.c b/src/debugger.c
index edb79e1..12ef9d8 100644
--- a/src/debugger.c
+++ b/src/debugger.c
@@ -109,25 +109,17 @@ static void debug_text_para(Paragraph *para, cairo_t *cr, double *ypos,
for ( i=0; i<nrun; i++ ) {
SCBlock *scblock;
- SCBlock *rscblock;
- if ( para_debug_run_info(para, i, &scblock, &rscblock) ) {
+ if ( para_debug_run_info(para, i, &scblock) ) {
/* Failed to get debug info for paragraph */
plot_text(cr, ypos, fontdesc, _("Error"));
} else {
-
- if ( scblock != rscblock ) {
- snprintf(tmp, 255, " Run %i: SCBlock %p / %p", i,
- scblock, rscblock);
- } else {
- snprintf(tmp, 255, " Run %i: SCBlock %p", i,
- scblock);
- }
+ snprintf(tmp, 255, " Run %i: SCBlock %p", i, scblock);
plot_text(cr, ypos, fontdesc, tmp);
-
}
}
- snprintf(tmp, 255, "Newline at end: %p", get_newline_at_end(para));
+ snprintf(tmp, 255, "Newline at end: %p",
+ para_debug_get_newline_at_end(para));
plot_text(cr, ypos, fontdesc, tmp);
}
@@ -161,17 +153,12 @@ static gboolean dbg_draw_sig(GtkWidget *da, cairo_t *cr, struct debugwindow *dbg
enum para_type t = para_type(dbgw->fr->paras[i]);
SCBlock *scblock = para_scblock(dbgw->fr->paras[i]);
- SCBlock *rscblock = para_rscblock(dbgw->fr->paras[i]);
plot_hr(cr, &ypos, width);
snprintf(tmp, 255, "Paragraph %i: type %s", i, str_type(t));
plot_text(cr, &ypos, fontdesc, tmp);
- if ( scblock == rscblock ) {
- snprintf(tmp, 255, "SCBlock %p", scblock);
- } else {
- snprintf(tmp, 255, "SCBlock %p / %p", scblock, rscblock);
- }
+ snprintf(tmp, 255, "SCBlock %p", scblock);
plot_text(cr, &ypos, fontdesc, tmp);
if ( t == PARA_TYPE_TEXT ) {
diff --git a/src/frame.c b/src/frame.c
index d4a5637..2926d4e 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -39,7 +39,6 @@
struct text_run
{
SCBlock *scblock; /* If macro, this is \macro */
- SCBlock *rscblock; /* The block with the actual text */
PangoFontDescription *fontdesc;
double col[4];
};
@@ -61,7 +60,6 @@ struct _paragraph
/* For anything other than PARA_TYPE_TEXT
* (for text paragraphs, these things are in the runs) */
SCBlock *scblock;
- SCBlock *rscblock;
/* For PARA_TYPE_IMAGE */
char *filename;
@@ -186,7 +184,7 @@ struct frame *add_subframe(struct frame *fr)
}
-void show_hierarchy(struct frame *fr, const char *t)
+void show_frame_hierarchy(struct frame *fr, const char *t)
{
int i;
char tn[1024];
@@ -197,65 +195,12 @@ void show_hierarchy(struct frame *fr, const char *t)
printf(_("%s%p (%.2f x %.2f)\n"), t, fr, fr->w, fr->h);
for ( i=0; i<fr->num_children; i++ ) {
- show_hierarchy(fr->children[i], tn);
+ show_frame_hierarchy(fr->children[i], tn);
}
}
-static struct frame *find_parent(struct frame *fr, struct frame *search)
-{
- int i;
-
- for ( i=0; i<fr->num_children; i++ ) {
- if ( fr->children[i] == search ) {
- return fr;
- }
- }
-
- for ( i=0; i<fr->num_children; i++ ) {
- struct frame *tt;
- tt = find_parent(fr->children[i], search);
- if ( tt != NULL ) return tt;
- }
-
- return NULL;
-}
-
-
-void delete_subframe(struct frame *top, struct frame *fr)
-{
- struct frame *parent;
- int i, idx, found;
-
- parent = find_parent(top, fr);
- if ( parent == NULL ) {
- fprintf(stderr, _("Couldn't find parent when deleting frame.\n"));
- return;
- }
-
- found = 0;
- for ( i=0; i<parent->num_children; i++ ) {
- if ( parent->children[i] == fr ) {
- idx = i;
- found = 1;
- break;
- }
- }
-
- if ( !found ) {
- fprintf(stderr, _("Couldn't find child when deleting frame.\n"));
- return;
- }
-
- for ( i=idx; i<parent->num_children-1; i++ ) {
- parent->children[i] = parent->children[i+1];
- }
-
- parent->num_children--;
-}
-
-
struct frame *find_frame_with_scblocks(struct frame *fr, SCBlock *scblocks)
{
int i;
@@ -279,17 +224,17 @@ static size_t run_text_len(const struct text_run *run)
return 0;
}
- if ( run->rscblock == NULL ) {
- fprintf(stderr, _("NULL rscblock in run_text_len\n"));
+ if ( run->scblock == NULL ) {
+ fprintf(stderr, _("NULL scblock in run_text_len\n"));
return 0;
}
- if ( sc_block_contents(run->rscblock) == NULL ) {
- fprintf(stderr, _("NULL rscblock contents in run_text_len\n"));
+ if ( sc_block_contents(run->scblock) == NULL ) {
+ fprintf(stderr, _("NULL scblock contents in run_text_len\n"));
return 0;
}
- return strlen(sc_block_contents(run->rscblock));
+ return strlen(sc_block_contents(run->scblock));
}
@@ -340,7 +285,7 @@ void wrap_paragraph(Paragraph *para, PangoContext *pc, double w,
size_t run_len;
guint16 r, g, b;
- run_text = sc_block_contents(para->runs[i].rscblock);
+ run_text = sc_block_contents(para->runs[i].scblock);
run_len = strlen(run_text);
attr = pango_attr_font_desc_new(para->runs[i].fontdesc);
@@ -384,19 +329,25 @@ void wrap_paragraph(Paragraph *para, PangoContext *pc, double w,
para->height = pango_units_to_double(rect.height);
}
-SCBlock *get_newline_at_end(Paragraph *para)
+static SCBlock *get_newline_at_end(Paragraph *para)
{
return para->newline_at_end;
}
+SCBlock *para_debug_get_newline_at_end(Paragraph *para)
+{
+ return get_newline_at_end(para);
+}
+
+
void set_newline_at_end(Paragraph *para, SCBlock *bl)
{
para->newline_at_end = bl;
}
-void add_run(Paragraph *para, SCBlock *scblock, SCBlock *rscblock,
+void add_run(Paragraph *para, SCBlock *scblock,
PangoFontDescription *fdesc, double col[4])
{
struct text_run *runs_new;
@@ -410,7 +361,6 @@ void add_run(Paragraph *para, SCBlock *scblock, SCBlock *rscblock,
para->runs = runs_new;
para->runs[para->n_runs].scblock = scblock;
- para->runs[para->n_runs].rscblock = rscblock;
para->runs[para->n_runs].fontdesc = pango_font_description_copy(fdesc);
para->runs[para->n_runs].col[0] = col[0];
para->runs[para->n_runs].col[1] = col[1];
@@ -421,7 +371,7 @@ void add_run(Paragraph *para, SCBlock *scblock, SCBlock *rscblock,
}
-Paragraph *create_paragraph(struct frame *fr, SCBlock *bl, SCBlock *rbl)
+Paragraph *create_paragraph(struct frame *fr, SCBlock *bl)
{
Paragraph **paras_new;
Paragraph *pnew;
@@ -439,7 +389,6 @@ Paragraph *create_paragraph(struct frame *fr, SCBlock *bl, SCBlock *rbl)
* However, this can easily be changed */
pnew->type = PARA_TYPE_TEXT;
pnew->scblock = bl;
- pnew->rscblock = rbl;
pnew->n_runs = 0;
pnew->runs = NULL;
pnew->layout = NULL;
@@ -481,8 +430,7 @@ Paragraph *insert_paragraph(struct frame *fr, int pos)
}
-Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, SCBlock *rbl,
- double w, double h,
+Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, double w, double h,
SCCallbackDrawFunc draw_func,
SCCallbackClickFunc click_func, void *bvp,
void *vp)
@@ -492,7 +440,7 @@ Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, SCBlock *rbl,
if ( (fr->n_paras > 0) && (fr->paras[fr->n_paras-1]->empty) ) {
pnew = fr->paras[fr->n_paras-1];
} else {
- pnew = create_paragraph(fr, bl, rbl);
+ pnew = create_paragraph(fr, bl);
if ( pnew == NULL ) {
fprintf(stderr, _("Failed to add callback paragraph\n"));
return NULL;
@@ -501,7 +449,6 @@ Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, SCBlock *rbl,
pnew->type = PARA_TYPE_CALLBACK;
pnew->scblock = bl;
- pnew->rscblock = rbl;
pnew->cb_w = w;
pnew->cb_h = h;
pnew->draw_func = draw_func;
@@ -515,7 +462,7 @@ Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, SCBlock *rbl,
}
-void add_image_para(struct frame *fr, SCBlock *scblock, SCBlock *rscblock,
+void add_image_para(struct frame *fr, SCBlock *scblock,
const char *filename,
ImageStore *is, double w, double h, int editable)
{
@@ -530,7 +477,7 @@ void add_image_para(struct frame *fr, SCBlock *scblock, SCBlock *rscblock,
if ( (fr->n_paras > 0) && (fr->paras[fr->n_paras-1]->empty) ) {
pnew = fr->paras[fr->n_paras-1];
} else {
- pnew = create_paragraph(fr, scblock, rscblock);
+ pnew = create_paragraph(fr, scblock);
if ( pnew == NULL ) {
fprintf(stderr, _("Failed to add image paragraph\n"));
return;
@@ -545,7 +492,6 @@ void add_image_para(struct frame *fr, SCBlock *scblock, SCBlock *rscblock,
pnew->type = PARA_TYPE_IMAGE;
pnew->scblock = scblock;
- pnew->rscblock = rscblock;
pnew->filename = strdup(filename);
pnew->image_w = w;
pnew->image_h = h;
@@ -662,7 +608,7 @@ void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is)
}
-size_t end_offset_of_para(struct frame *fr, int pn)
+static size_t end_offset_of_para(struct frame *fr, int pn)
{
int i;
size_t total = 0;
@@ -726,11 +672,6 @@ void ensure_run(struct frame *fr, struct edit_pos cpos)
if ( para->type != PARA_TYPE_TEXT ) return;
- if ( para->scblock != para->rscblock ) {
- fprintf(stderr, _("Need to add run, but paragraph not editable\n"));
- return;
- }
-
if ( para->scblock != NULL ) {
bl = sc_block_prepend(para->scblock, fr->scblocks);
@@ -745,13 +686,12 @@ void ensure_run(struct frame *fr, struct edit_pos cpos)
/* If the paragraph's SCBlock is NULL, it means this paragraph
* is right at the end of the document. The last thing in the
* document is something like \newpara. */
- bl = sc_block_append_end(fr->scblocks, NULL, NULL, strdup(""));
+ bl = sc_block_append_inside(fr->scblocks, NULL, NULL, strdup(""));
}
para->scblock = bl;
- para->rscblock = bl;
- add_run(para, bl, bl, fr->fontdesc, fr->col);
+ add_run(para, bl, fr->fontdesc, fr->col);
wrap_paragraph(para, NULL, fr->w - fr->pad_l - fr->pad_r, 0, 0);
}
@@ -907,11 +847,6 @@ void cursor_moveh(struct frame *fr, struct edit_pos *cp, signed int dir)
}
-void cursor_movev(struct frame *fr, struct edit_pos *cp, signed int dir)
-{
-}
-
-
void check_callback_click(struct frame *fr, int para)
{
Paragraph *p = fr->paras[para];
@@ -987,7 +922,7 @@ size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail)
return 0;
}
- if ( sc_block_contents(run->rscblock) == NULL ) {
+ if ( sc_block_contents(run->scblock) == NULL ) {
fprintf(stderr, _("pos_trail_to_offset: No contents "
"(%p name=%s, options=%s)\n"),
run->scblock, sc_block_name(run->scblock),
@@ -996,7 +931,7 @@ size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail)
}
/* Get the text for the run */
- run_text = sc_block_contents(run->rscblock);
+ run_text = sc_block_contents(run->scblock);
/* Turn the paragraph offset into a run offset */
para_offset_of_run = get_paragraph_offset(para, nrun);
@@ -1035,11 +970,6 @@ int position_editable(struct frame *fr, struct edit_pos cp)
para = fr->paras[cp.para];
- if ( para->scblock != para->rscblock ) {
- fprintf(stderr, _("Paragraph is not editable.\n"));
- return 0;
- }
-
if ( para->type != PARA_TYPE_TEXT ) {
fprintf(stderr, _("Paragraph is not text.\n"));
return 0;
@@ -1052,7 +982,7 @@ int position_editable(struct frame *fr, struct edit_pos cp)
return 0;
}
- return (para->runs[run].scblock == para->runs[run].rscblock);
+ return 1;
}
@@ -1074,33 +1004,11 @@ void insert_text_in_paragraph(Paragraph *para, size_t offs, const char *t)
size_t run_offs;
run = &para->runs[nrun];
run_offs = offs - get_paragraph_offset(para, nrun);
- sc_insert_text(run->rscblock, run_offs, t);
+ sc_insert_text(run->scblock, run_offs, t);
}
}
-static SCBlock *pos_to_rscblock(struct frame *fr, struct edit_pos p)
-{
- int run;
- size_t paraoffs;
- Paragraph *para;
-
- para = fr->paras[p.para];
-
- if ( para->type != PARA_TYPE_TEXT ) {
- return NULL;
- }
-
- paraoffs = pos_trail_to_offset(para, p.pos, p.trail);
-
- run = which_run(para, paraoffs);
- assert(run < para->n_runs);
-
- return para->runs[run].rscblock;
-}
-
-
-
static SCBlock *pos_to_scblock(struct frame *fr, struct edit_pos p,
enum para_type *type)
{
@@ -1192,17 +1100,9 @@ static Paragraph *scan_runs_for_scblock(struct frame *fr, int pn1, int pn2,
*run = 0;
return fr->paras[i];
}
- if ( fr->paras[i]->rscblock == bl ) {
- *run = 0;
- return fr->paras[i];
- }
/* Check all runs */
for ( j=0; j<fr->paras[i]->n_runs; j++ ) {
- if ( fr->paras[i]->runs[j].rscblock == bl ) {
- *run = j;
- return fr->paras[i];
- }
if ( fr->paras[i]->runs[j].scblock == bl ) {
*run = j;
return fr->paras[i];
@@ -1440,7 +1340,6 @@ void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_po
{
int i;
SCBlock *p1scblock, *p2scblock;
- SCBlock *p1rscblock, *p2rscblock;
enum para_type type1, type2;
size_t p2offs;
SCBlock *scblock;
@@ -1467,8 +1366,6 @@ void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_po
/* Find SC positions for start and end */
p1scblock = pos_to_scblock(fr, p1, &type1);
p2scblock = pos_to_scblock(fr, p2, &type2);
- p1rscblock = pos_to_rscblock(fr, p1);
- p2rscblock = pos_to_rscblock(fr, p2);
p2offs = pos_to_offset(fr, p2);
wrap_end = p2.para;
@@ -1512,9 +1409,9 @@ void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_po
printf(" offs %li\n", (long int)p1offs);
if ( p1offs != 0 ) {
printf("Partial delete\n");
- printf("contents '%s'\n", sc_block_contents(p1rscblock));
+ printf("contents '%s'\n", sc_block_contents(p1scblock));
printf("from offs %li\n", (long int)p1offs);
- scblock_delete_text(p1rscblock, p1offs, -1);
+ scblock_delete_text(p1scblock, p1offs, -1);
} else {
printf("Deleting the whole text SCBlock\n");
sc_block_delete(&fr->scblocks, p1scblock);
@@ -1564,8 +1461,8 @@ void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_po
if ( type2 == PARA_TYPE_TEXT ) {
size_t len;
printf(" offs %li\n", (long int)p2offs);
- if ( sc_block_contents(p2rscblock) != NULL ) {
- len = strlen(sc_block_contents(p2rscblock));
+ if ( sc_block_contents(p2scblock) != NULL ) {
+ len = strlen(sc_block_contents(p2scblock));
} else {
len = 0;
}
@@ -1580,9 +1477,9 @@ void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_po
NULL);
} else if ( p2offs > 0 ) {
printf("Partial delete\n");
- printf("contents '%s'\n", sc_block_contents(p2rscblock));
+ printf("contents '%s'\n", sc_block_contents(p2scblock));
printf("up to offs %li\n", (long int)p2offs);
- scblock_delete_text(p2rscblock, 0, p2offs);
+ scblock_delete_text(p2scblock, 0, p2offs);
} /* else do nothing */
} else {
printf("Deleting the whole non-text SCBlock\n");
@@ -1610,10 +1507,10 @@ void show_para(Paragraph *p)
printf(_("%i runs:\n"), p->n_runs);
for ( i=0; i<p->n_runs; i++ ) {
- printf(_(" Run %2i: SCBlock %p/%p %s '%s'\n"),
- i, p->runs[i].scblock, p->runs[i].rscblock,
+ printf(_(" Run %2i: SCBlock %p %s '%s'\n"),
+ i, p->runs[i].scblock,
pango_font_description_to_string(p->runs[i].fontdesc),
- sc_block_contents(p->runs[i].rscblock));
+ sc_block_contents(p->runs[i].scblock));
}
} else if ( p->type == PARA_TYPE_IMAGE ) {
@@ -1695,9 +1592,8 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
end = sc_block_append(np, NULL, NULL, strdup(""), NULL);
pnew->n_runs = 0;
- add_run(pnew, end, end, fr->fontdesc, fr->col);
+ add_run(pnew, end, fr->fontdesc, fr->col);
pnew->scblock = end;
- pnew->rscblock = end;
wrap_paragraph(pnew, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0);
@@ -1710,12 +1606,11 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
/* Split the run (and SCBlock) into two */
double col[4] = {0,0,0,0};
struct text_run *rn;
- int macro = 0;
printf("Splitting run %i. Before:\n", run);
show_para(para);
- add_run(para, NULL, NULL, NULL, col);
+ add_run(para, NULL, NULL, col);
/* -2 here because add_run increased para->n_runs by 1 */
memmove(&para->runs[run+2], &para->runs[run+1],
(para->n_runs - run - 2)*sizeof(struct text_run));
@@ -1723,19 +1618,7 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
rr = &para->runs[run]; /* Because add_run realloced the runs */
rn = &para->runs[run+1];
- if ( rr->rscblock != rr->scblock) {
- macro = 1;
- }
-
- rn->rscblock = sc_block_split(rr->rscblock, run_offs);
-
- if ( !macro ) {
- /* Literal text block */
- rn->scblock = rn->rscblock;
- } else {
- /* Macro block */
- rn->scblock = rr->scblock;
- }
+ rn->scblock = sc_block_split(rr->scblock, run_offs);
rn->fontdesc = pango_font_description_copy(rr->fontdesc);
rn->col[0] = rr->col[0];
@@ -1752,11 +1635,10 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
for ( i=run+1; i<para->n_runs; i++ ) {
double col[4] = {0,0,0,0};
printf("Moving run %i to pos %i\n", i, pnew->n_runs);
- add_run(pnew, NULL, NULL, NULL, col);
+ add_run(pnew, NULL, NULL, col);
pnew->runs[pnew->n_runs-1] = para->runs[i];
}
pnew->scblock = pnew->runs[0].scblock;
- pnew->rscblock = pnew->runs[0].rscblock;
/* Truncate the first paragraph at the appropriate position */
para->n_runs = run+1;
@@ -1768,7 +1650,7 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
show_para(pnew);
/* Add a \newpara after the end of the first paragraph's SC */
- nnp = sc_block_append(rr->rscblock, strdup("newpara"), NULL, NULL, NULL);
+ nnp = sc_block_append(rr->scblock, strdup("newpara"), NULL, NULL, NULL);
set_newline_at_end(pnew, get_newline_at_end(para));
set_newline_at_end(para, nnp);
@@ -1853,12 +1735,6 @@ SCBlock *para_scblock(Paragraph *para)
}
-SCBlock *para_rscblock(Paragraph *para)
-{
- return para->rscblock;
-}
-
-
enum para_type para_type(Paragraph *para)
{
return para->type;
@@ -1872,13 +1748,11 @@ int para_debug_num_runs(Paragraph *para)
}
-int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock,
- SCBlock **rscblock)
+int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock)
{
if ( para->type != PARA_TYPE_TEXT ) return 1;
if ( i >= para->n_runs ) return 1;
*scblock = para->runs[i].scblock;
- *rscblock = para->runs[i].rscblock;
return 0;
}
diff --git a/src/frame.h b/src/frame.h
index b50cfaf..f52c6e6 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -42,8 +42,7 @@ typedef enum
{
GRAD_NONE,
GRAD_HORIZ,
- GRAD_VERT,
- GRAD_NOBG
+ GRAD_VERT
} GradientType;
enum para_type
@@ -115,8 +114,6 @@ struct frame
extern struct frame *frame_new(void);
extern void frame_free(struct frame *fr);
extern struct frame *add_subframe(struct frame *fr);
-extern void show_hierarchy(struct frame *fr, const char *t);
-extern void delete_subframe(struct frame *top, struct frame *fr);
extern struct frame *find_frame_with_scblocks(struct frame *top,
SCBlock *scblocks);
@@ -130,32 +127,27 @@ extern void set_para_alignment(Paragraph *para, PangoAlignment align);
extern double paragraph_height(Paragraph *para);
extern void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is);
-extern SCBlock *get_newline_at_end(Paragraph *para);
extern void set_newline_at_end(Paragraph *para, SCBlock *bl);
-extern void check_run(struct frame *fr, int pn);
extern void show_edit_pos(struct edit_pos a);
-extern void add_run(Paragraph *para, SCBlock *scblock, SCBlock *rscblock,
+extern void add_run(Paragraph *para, SCBlock *scblock,
PangoFontDescription *fdesc, double col[4]);
extern Paragraph *insert_paragraph(struct frame *fr, int pos);
extern Paragraph *add_callback_para(struct frame *fr, SCBlock *scblock,
- SCBlock *rscblock,
double w, double h,
SCCallbackDrawFunc draw_func,
SCCallbackClickFunc click_func, void *bvp,
void *vp);
extern void add_image_para(struct frame *fr, SCBlock *scblock,
- SCBlock *rscblock, const char *filename,
+ const char *filename,
ImageStore *is, double w, double h, int editable);
extern void wrap_paragraph(Paragraph *para, PangoContext *pc, double w,
size_t sel_start, size_t sel_end);
-extern size_t end_offset_of_para(struct frame *fr, int pn);
-
extern int find_cursor(struct frame *fr, double x, double y,
struct edit_pos *pos);
@@ -175,8 +167,6 @@ extern int get_cursor_pos(struct frame *fr, int cursor_para, int cursor_pos,
extern void cursor_moveh(struct frame *fr, struct edit_pos *cp, signed int dir);
-extern void cursor_movev(struct frame *fr, struct edit_pos *cp, signed int dir);
-
extern void check_callback_click(struct frame *fr, int para);
extern size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail);
@@ -187,25 +177,24 @@ extern void insert_text_in_paragraph(Paragraph *para, size_t offs,
extern void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_pos p2,
double wrap_w);
-extern size_t delete_text_in_paragraph(struct frame *fr, int npara, size_t offs0, ssize_t offs2);
-
extern SCBlock *split_paragraph(struct frame *fr, int pn, size_t pos,
PangoContext *pc);
extern SCBlock *block_at_cursor(struct frame *fr, int para, size_t pos);
+extern void show_frame_hierarchy(struct frame *fr, const char *t);
+
extern int get_sc_pos(struct frame *fr, int pn, size_t pos,
SCBlock **bl, size_t *ppos);
extern void *get_para_bvp(Paragraph *para);
-extern Paragraph *create_paragraph(struct frame *fr, SCBlock *bl, SCBlock *rbl);
+extern Paragraph *create_paragraph(struct frame *fr, SCBlock *bl);
extern enum para_type para_type(Paragraph *para);
extern SCBlock *para_scblock(Paragraph *para);
-extern SCBlock *para_rscblock(Paragraph *para);
+extern SCBlock *para_debug_get_newline_at_end(Paragraph *para);
extern int para_debug_num_runs(Paragraph *para);
-extern int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock,
- SCBlock **rscblock);
+extern int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock);
#endif /* FRAME_H */
diff --git a/src/narrative_window.c b/src/narrative_window.c
index e549fc1..b287f61 100644
--- a/src/narrative_window.c
+++ b/src/narrative_window.c
@@ -185,105 +185,31 @@ static void delete_slide_sig(GSimpleAction *action, GVariant *parameter,
}
-static struct template_id *get_templates(SCBlock *ss, int *n)
-{
- struct template_id *list;
- SCInterpreter *scin;
-
- scin = sc_interp_new(NULL, NULL, NULL, NULL);
- sc_interp_run_stylesheet(scin, ss); /* ss == NULL is OK */
- list = sc_interp_get_templates(scin, n);
- sc_interp_destroy(scin);
- return list;
-}
-
-
-static void update_template_menus(NarrativeWindow *nw)
-{
- struct template_id *templates;
- int i, n_templates;
-
- templates = get_templates(nw->p->stylesheet, &n_templates);
-
- for ( i=0; i<n_templates; i++ ) {
- free(templates[i].name);
- free(templates[i].friendlyname);
- sc_block_free(templates[i].scblock);
- }
-
- free(templates);
-}
-
-
-static SCBlock *get_slide_template(SCBlock *ss)
-{
- struct template_id *templates;
- int i, n_templates;
- SCBlock *ret = NULL;
-
- templates = get_templates(ss, &n_templates);
-
- for ( i=0; i<n_templates; i++ ) {
- if ( strcmp(templates[i].name, "slide") == 0 ) {
- ret = templates[i].scblock;
- } else {
- sc_block_free(templates[i].scblock);
- }
- free(templates[i].name);
- free(templates[i].friendlyname);
- }
- free(templates);
-
- /* No template? */
- if ( ret == NULL ) {
- ret = sc_parse("\\slide{}");
- }
-
- return ret; /* NB this is a copy of the one owned by the interpreter */
-}
-
-
static gint load_ss_response_sig(GtkWidget *d, gint response,
NarrativeWindow *nw)
{
if ( response == GTK_RESPONSE_ACCEPT ) {
- char *filename;
- char *stext;
-
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
- printf("Loading %s\n",filename);
+ GFile *file;
+ Stylesheet *new_ss;
- stext = load_everything(filename);
- if ( stext != NULL ) {
+ file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(d));
- SCBlock *bl;
- SCBlock *ss;
- bl = sc_parse(stext);
- free(stext);
- ss = find_stylesheet(bl);
+ new_ss = stylesheet_load(file);
+ if ( new_ss != NULL ) {
- if ( ss != NULL ) {
+ stylesheet_free(nw->p->stylesheet);
+ nw->p->stylesheet = new_ss;
+ sc_editor_set_stylesheet(nw->sceditor, new_ss);
- /* Substitute the style sheet in
- * presentation Storycode */
- replace_stylesheet(nw->p, ss);
+ /* Full rerender */
+ sc_editor_set_scblock(nw->sceditor, nw->dummy_top);
- sc_editor_set_stylesheet(nw->sceditor, ss);
-
- /* Full rerender, first block may have
- * changed */
- sc_editor_set_scblock(nw->sceditor,
- nw->dummy_top);
-
- } else {
- fprintf(stderr, _("Not a style sheet\n"));
- }
} else {
fprintf(stderr, _("Failed to load\n"));
}
- g_free(filename);
+ g_object_unref(file);
}
@@ -351,9 +277,8 @@ static void add_slide_sig(GSimpleAction *action, GVariant *parameter,
/* Split the current paragraph */
nsblock = split_paragraph_at_cursor(nw->sceditor);
- /* Get the template */
- templ = get_slide_template(nw->p->stylesheet); /* our copy */
- show_sc_blocks(templ);
+ /* FIXME: Template from JSON */
+ templ = sc_parse("\\slide{}");
/* Link the new SCBlock in */
if ( nsblock != NULL ) {
@@ -886,7 +811,6 @@ NarrativeWindow *narrative_window_new(struct presentation *p, GApplication *papp
"win.last");
update_toolbar(nw);
- update_template_menus(nw);
scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
diff --git a/src/presentation.c b/src/presentation.c
index b8b4589..eab0f5a 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -67,6 +67,59 @@ char *get_titlebar_string(struct presentation *p)
}
+static void find_and_load_stylesheet(struct presentation *p, GFile *file)
+{
+ GFile *ssfile;
+ GFile *parent;
+ gchar *ssuri;
+
+ if ( file != NULL ) {
+
+ /* First choice: /same/directory/<presentation>.ss */
+ ssuri = g_file_get_uri(file);
+ if ( ssuri != NULL ) {
+ size_t l = strlen(ssuri);
+ if ( ssuri[l-3] == '.' && ssuri[l-2] == 's' && ssuri[l-1] =='c' ) {
+ ssuri[l-1] = 's';
+ ssfile = g_file_new_for_uri(ssuri);
+ p->stylesheet = stylesheet_load(ssfile);
+ g_object_unref(ssfile);
+ g_free(ssuri);
+ }
+ }
+
+ /* Second choice: /same/directory/stylesheet.ss */
+ if ( p->stylesheet == NULL ) {
+ parent = g_file_get_parent(file);
+ if ( parent != NULL ) {
+ ssfile = g_file_get_child(parent, "stylesheet.ss");
+ if ( ssfile != NULL ) {
+ p->stylesheet = stylesheet_load(ssfile);
+ g_object_unref(ssfile);
+ }
+ }
+ }
+
+ }
+
+ /* Third choice: <cwd>/stylesheet.ss */
+ if ( p->stylesheet == NULL ) {
+ ssfile = g_file_new_for_path("./stylesheet.ss");
+ p->stylesheet = stylesheet_load(ssfile);
+ g_object_unref(ssfile);
+ }
+
+ /* Fourth choice: internal default stylesheet */
+ if ( p->stylesheet == NULL ) {
+ ssfile = g_file_new_for_uri("resource:///uk/me/bitwiz/Colloquium/default.ss");
+ p->stylesheet = stylesheet_load(ssfile);
+ g_object_unref(ssfile);
+ }
+
+ /* Last resort is NULL stylesheet and SCInterpreter's defaults */
+}
+
+
struct presentation *new_presentation(const char *imagestore)
{
struct presentation *new;
@@ -89,6 +142,8 @@ struct presentation *new_presentation(const char *imagestore)
new->lang = pango_language_get_default();
+ find_and_load_stylesheet(new, NULL);
+
return new;
}
@@ -226,75 +281,17 @@ SCBlock *prev_slide(struct presentation *p, SCBlock *sl)
}
-int replace_stylesheet(struct presentation *p, SCBlock *ss)
-{
- /* Create style sheet from union of old and new,
- * preferring items from the new one */
-
- /* If there was no stylesheet before, add a dummy one */
- if ( p->stylesheet == NULL ) {
- p->stylesheet = sc_block_append_end(p->scblocks,
- "stylesheet", NULL, NULL);
- }
-
- /* Cut the old stylesheet out of the presentation,
- * and put in the new one */
- sc_block_substitute(&p->scblocks, p->stylesheet, ss);
- p->stylesheet = ss;
-
- return 0;
-}
-
-
-SCBlock *find_stylesheet(SCBlock *bl)
-{
- while ( bl != NULL ) {
-
- const char *name = sc_block_name(bl);
-
- if ( (name != NULL) && (strcmp(name, "stylesheet") == 0) ) {
- return bl;
- }
-
- bl = sc_block_next(bl);
-
- }
-
- return NULL;
-}
-
-
-static void install_stylesheet(struct presentation *p)
-{
- if ( p->stylesheet != NULL ) {
- fprintf(stderr, _("Duplicate style sheet!\n"));
- return;
- }
-
- p->stylesheet = find_stylesheet(p->scblocks);
-
- if ( p->stylesheet == NULL ) {
- fprintf(stderr, _("No style sheet.\n"));
- }
-}
-
-
static void set_slide_size_from_stylesheet(struct presentation *p)
{
- SCInterpreter *scin;
- double w, h;
- int r;
-
- if ( p->stylesheet == NULL ) return;
-
- scin = sc_interp_new(NULL, NULL, NULL, NULL);
- sc_interp_run_stylesheet(scin, p->stylesheet); /* ss == NULL is OK */
- r = sc_interp_get_slide_size(scin, &w, &h);
- sc_interp_destroy(scin);
-
- if ( r == 0 ) {
- p->slide_width = w;
- p->slide_height = h;
+ char *result;
+
+ result = stylesheet_lookup(p->stylesheet, "$.slide", "size");
+ if ( result != NULL ) {
+ float v[2];
+ if ( parse_double(result, v) == 0 ) {
+ p->slide_width = v[0];
+ p->slide_height = v[1];
+ }
}
}
@@ -324,7 +321,10 @@ int load_presentation(struct presentation *p, GFile *file)
return r; /* Error */
}
- install_stylesheet(p);
+ p->stylesheet = NULL;
+
+ find_and_load_stylesheet(p, file);
+
set_slide_size_from_stylesheet(p);
assert(p->uri == NULL);
diff --git a/src/presentation.h b/src/presentation.h
index ed8a188..ea3780e 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -34,6 +34,7 @@ struct presentation;
#include "slideshow.h"
#include "narrative_window.h"
#include "slide_window.h"
+#include "stylesheet.h"
struct menu_pl;
@@ -56,15 +57,13 @@ struct presentation
double slide_width;
double slide_height;
- SCBlock *stylesheet;
SCBlock *scblocks;
+ Stylesheet *stylesheet;
};
extern struct presentation *new_presentation(const char *imagestore);
-extern SCBlock *find_stylesheet(SCBlock *bl);
-extern int replace_stylesheet(struct presentation *p, SCBlock *ss);
extern void free_presentation(struct presentation *p);
extern char *get_titlebar_string(struct presentation *p);
diff --git a/src/print.c b/src/print.c
index c50a3c5..43c967e 100644
--- a/src/print.c
+++ b/src/print.c
@@ -54,9 +54,6 @@ struct print_stuff
struct frame *top;
int start_paras[256];
int slide_number;
-
- ImageStore *is;
- const char *storename;
};
@@ -194,13 +191,11 @@ static void begin_narrative_print(GtkPrintOperation *op, GtkPrintContext *ctx,
sc_callback_list_add_callback(cbl, "slide", print_create_thumbnail,
print_render_thumbnail, NULL, ps);
- ps->is = imagestore_new(ps->storename);
-
pc = gtk_print_context_create_pango_context(ctx);
dummy_top = sc_block_new_parent(ps->p->scblocks, "presentation");
ps->top = interp_and_shape(dummy_top, ps->p->stylesheet, cbl,
- ps->is, 0, pc,
+ ps->p->is, 0, pc,
gtk_print_context_get_width(ctx),
gtk_print_context_get_height(ctx),
ps->p->lang);
@@ -242,7 +237,10 @@ static void print_narrative(GtkPrintOperation *op, GtkPrintContext *ctx,
h += paragraph_height(ps->top->paras[i]);
if ( h > page_height ) return;
- render_paragraph(cr, ps->top->paras[i], ps->is);
+ cairo_save(cr);
+ render_paragraph(cr, ps->top->paras[i], ps->p->is);
+ cairo_restore(cr);
+
cairo_translate(cr, 0.0, paragraph_height(ps->top->paras[i]));
}
diff --git a/src/render.c b/src/render.c
index 580a4cd..f9f4cca 100644
--- a/src/render.c
+++ b/src/render.c
@@ -48,8 +48,6 @@ static void do_background(cairo_t *cr, struct frame *fr)
{
cairo_pattern_t *patt = NULL;
- if ( fr->grad == GRAD_NOBG ) return; /* Should not end up here */
-
cairo_new_path(cr);
cairo_rectangle(cr, 0.0, 0.0, fr->w, fr->h);
@@ -86,9 +84,6 @@ static void do_background(cairo_t *cr, struct frame *fr)
cairo_set_source(cr, patt);
break;
- case GRAD_NOBG:
- break;
-
}
cairo_fill(cr);
@@ -176,14 +171,14 @@ int recursive_wrap(struct frame *fr, PangoContext *pc)
}
-struct frame *interp_and_shape(SCBlock *scblocks, SCBlock *stylesheet,
+struct frame *interp_and_shape(SCBlock *scblocks, Stylesheet *stylesheet,
SCCallbackList *cbl, ImageStore *is,
int slide_number,
PangoContext *pc, double w, double h,
PangoLanguage *lang)
{
SCInterpreter *scin;
- char snum[64];
+// char snum[64];
struct frame *top;
top = frame_new();
@@ -203,12 +198,13 @@ struct frame *interp_and_shape(SCBlock *scblocks, SCBlock *stylesheet,
sc_interp_set_callbacks(scin, cbl);
- snprintf(snum, 63, "%i", slide_number);
- add_macro(scin, "slidenumber", snum);
-
- if ( stylesheet != NULL ) {
- sc_interp_run_stylesheet(scin, stylesheet);
- }
+ /* FIXME: Set up slide number and style sheet */
+// snprintf(snum, 63, "%i", slide_number);
+// add_macro(scin, "slidenumber", snum);
+//
+// if ( stylesheet != NULL ) {
+// sc_interp_run_stylesheet(scin, stylesheet);
+// }
top->fontdesc = pango_font_description_copy(sc_interp_get_fontdesc(scin));
top->col[0] = sc_interp_get_fgcol(scin)[0];
@@ -216,7 +212,7 @@ struct frame *interp_and_shape(SCBlock *scblocks, SCBlock *stylesheet,
top->col[2] = sc_interp_get_fgcol(scin)[2];
top->col[3] = sc_interp_get_fgcol(scin)[3];
- sc_interp_add_block(scin, scblocks);
+ sc_interp_add_block(scin, scblocks, stylesheet);
sc_interp_destroy(scin);
@@ -226,7 +222,7 @@ struct frame *interp_and_shape(SCBlock *scblocks, SCBlock *stylesheet,
static struct frame *render_sc_with_context(SCBlock *scblocks,
cairo_t *cr, double log_w, double log_h,
- SCBlock *stylesheet, SCCallbackList *cbl,
+ Stylesheet *stylesheet, SCCallbackList *cbl,
ImageStore *is,
int slide_number, PangoLanguage *lang,
PangoContext *pc)
@@ -250,7 +246,7 @@ static struct frame *render_sc_with_context(SCBlock *scblocks,
cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h,
double log_w, double log_h,
- SCBlock *stylesheet, SCCallbackList *cbl,
+ Stylesheet *stylesheet, SCCallbackList *cbl,
ImageStore *is,
int slide_number, struct frame **ptop,
PangoLanguage *lang)
diff --git a/src/render.h b/src/render.h
index aadb033..0cfae26 100644
--- a/src/render.h
+++ b/src/render.h
@@ -35,7 +35,7 @@
/* Convienience function to run the entire pipeline */
extern cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h,
double log_w, double log_h,
- SCBlock *stylesheet, SCCallbackList *cbl,
+ Stylesheet *stylesheet, SCCallbackList *cbl,
ImageStore *is,
int slide_number, struct frame **ptop,
PangoLanguage *lang);
@@ -44,7 +44,7 @@ extern cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h,
* Needs to be followed by: wrap_contents() (recursively)
* recursive_draw()
*/
-extern struct frame *interp_and_shape(SCBlock *scblocks, SCBlock *stylesheet,
+extern struct frame *interp_and_shape(SCBlock *scblocks, Stylesheet *stylesheet,
SCCallbackList *cbl,
ImageStore *is,
int slide_number, PangoContext *pc,
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 999f919..e95beb4 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -384,7 +384,7 @@ void sc_editor_ensure_cursor(SCEditor *e)
}
-void sc_editor_remove_cursor(SCEditor *e)
+static void sc_editor_remove_cursor(SCEditor *e)
{
e->cursor_frame = NULL;
e->cpos.para = 0;
@@ -999,7 +999,7 @@ static void insert_text(char *t, SCEditor *e)
fprintf(stderr, _("Failed to insert paragraph\n"));
return;
}
- add_run(pnew, ad, ad, e->cursor_frame->fontdesc,
+ add_run(pnew, ad, e->cursor_frame->fontdesc,
e->cursor_frame->col);
wrap_frame(e->cursor_frame, e->pc);
@@ -1222,7 +1222,7 @@ static void check_paragraph(struct frame *fr, PangoContext *pc,
}
scblocks = sc_block_append(scblocks, NULL, NULL, strdup(""), NULL);
- add_run(para, scblocks, scblocks, fr->fontdesc, fr->col);
+ add_run(para, scblocks, fr->fontdesc, fr->col);
wrap_paragraph(para, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0);
}
@@ -1979,30 +1979,12 @@ void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks)
}
-SCBlock *sc_editor_get_scblock(SCEditor *e)
-{
- return e->scblocks;
-}
-
-
static void update_size_request(SCEditor *e)
{
gtk_widget_set_size_request(GTK_WIDGET(e), 0, e->h + 2.0*e->min_border);
}
-void sc_editor_set_size(SCEditor *e, int w, int h)
-{
- e->w = w;
- e->h = h;
- update_size_request(e);
- if ( gtk_widget_get_mapped(GTK_WIDGET(e)) ) {
- full_rerender(e);
- sc_editor_redraw(e);
- }
-}
-
-
void sc_editor_set_logical_size(SCEditor *e, double w, double h)
{
e->log_w = w;
@@ -2033,7 +2015,7 @@ void sc_editor_set_top_frame_editable(SCEditor *e, int top_frame_editable)
}
-void sc_editor_set_stylesheet(SCEditor *e, SCBlock *stylesheet)
+void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet)
{
e->stylesheet = stylesheet;
}
@@ -2125,7 +2107,7 @@ void sc_editor_set_imagestore(SCEditor *e, ImageStore *is)
}
-SCEditor *sc_editor_new(SCBlock *scblocks, SCBlock *stylesheet,
+SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet,
PangoLanguage *lang, const char *storename)
{
SCEditor *sceditor;
diff --git a/src/sc_editor.h b/src/sc_editor.h
index adbbaf2..d3c111b 100644
--- a/src/sc_editor.h
+++ b/src/sc_editor.h
@@ -32,6 +32,7 @@
#include "frame.h"
#include "sc_interp.h"
+#include "stylesheet.h"
struct presentation;
@@ -94,7 +95,7 @@ struct _sceditor
double log_w; /* Size of surface in "SC units" */
double log_h;
SCBlock *scblocks;
- SCBlock *stylesheet;
+ Stylesheet *stylesheet;
ImageStore *is;
SCCallbackList *cbl;
struct frame *top;
@@ -168,12 +169,9 @@ typedef struct _sceditor SCEditor;
typedef struct _sceditorclass SCEditorClass;
extern void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks);
-extern void sc_editor_set_stylesheet(SCEditor *e, SCBlock *stylesheet);
-extern SCBlock *sc_editor_get_scblock(SCEditor *e);
-extern GtkWidget *sc_editor_get_widget(SCEditor *e);
-extern SCEditor *sc_editor_new(SCBlock *scblocks, SCBlock *stylesheet,
+extern void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet);
+extern SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet,
PangoLanguage *lang, const char *storename);
-extern void sc_editor_set_size(SCEditor *e, int w, int h);
extern void sc_editor_set_logical_size(SCEditor *e, double w, double h);
extern void sc_editor_set_flow(SCEditor *e, int flow);
extern void sc_editor_set_scale(SCEditor *e, int scale);
@@ -188,7 +186,6 @@ extern void sc_editor_paste(SCEditor *e);
extern void sc_editor_add_storycode(SCEditor *e, const char *sc);
extern void sc_editor_copy_selected_frame(SCEditor *e);
extern void sc_editor_delete_selected_frame(SCEditor *e);
-extern void sc_editor_remove_cursor(SCEditor *e);
extern void sc_editor_ensure_cursor(SCEditor *e);
extern SCBlock *split_paragraph_at_cursor(SCEditor *e);
diff --git a/src/sc_interp.c b/src/sc_interp.c
index dea8446..7bbfeeb 100644
--- a/src/sc_interp.c
+++ b/src/sc_interp.c
@@ -38,21 +38,6 @@
#include "utils.h"
-struct macro
-{
- char *name;
- SCBlock *bl;
- struct macro *prev; /* Previous declaration, or NULL */
-};
-
-
-struct template
-{
- char *name;
- SCBlock *bl;
-};
-
-
struct sc_state
{
PangoFontDescription *fontdesc;
@@ -71,25 +56,8 @@ struct sc_state
double slide_height;
struct frame *fr; /* The current frame */
-
- int n_macros;
- int max_macros;
- struct macro *macros; /* Contents need to be copied on push */
-
- int n_styles;
- int max_styles;
- struct macro *styles; /* Contents need to be copied on push */
-
- int n_templates;
- int max_templates;
- struct template *templates;
-
- SCBlock *macro_contents; /* If running a macro, the child block of the caller */
- SCBlock *macro_real_block; /* If running a macro, the block which called the macro */
- int macro_editable; /* If running a macro, whether this bit can be edited or not */
};
-
struct _scinterp
{
PangoContext *pc;
@@ -118,6 +86,17 @@ struct _sccallbacklist
};
+static int sc_interp_add_blocks(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss)
+{
+ while ( bl != NULL ) {
+ if ( sc_interp_add_block(scin, bl, ss) ) return 1;
+ bl = sc_block_next(bl);
+ }
+
+ return 0;
+}
+
+
SCCallbackList *sc_callback_list_new()
{
SCCallbackList *cbl;
@@ -242,12 +221,6 @@ static int check_callback(SCInterpreter *scin, SCBlock *bl)
double w, h;
int r;
void *bvp;
- SCBlock *rbl;
-
- rbl = bl;
- if ( sc_interp_get_macro_real_block(scin) != NULL ) {
- bl = sc_interp_get_macro_real_block(scin);
- }
if ( strcmp(cbl->names[i], name) != 0 ) continue;
r = cbl->box_funcs[i](scin, bl, &w, &h, &bvp, cbl->vps[i]);
@@ -255,7 +228,7 @@ static int check_callback(SCInterpreter *scin, SCBlock *bl)
struct sc_state *st = &scin->state[scin->j];
Paragraph *pnew;
pnew = add_callback_para(sc_interp_get_frame(scin),
- bl, rbl, w, h,
+ bl, w, h,
cbl->draw_funcs[i],
cbl->click_funcs[i],
bvp, cbl->vps[i]);
@@ -293,41 +266,6 @@ double *sc_interp_get_fgcol(SCInterpreter *scin)
}
-double *sc_interp_get_bgcol(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->bgcol;
-}
-
-
-double *sc_interp_get_bgcol2(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->bgcol2;
-}
-
-
-GradientType sc_interp_get_bggrad(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->bggrad;
-}
-
-
-int sc_interp_get_ascent(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->ascent;
-}
-
-
-int sc_interp_get_height(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->height;
-}
-
-
static void set_frame_default_style(struct frame *fr, SCInterpreter *scin)
{
if ( fr == NULL ) return;
@@ -526,38 +464,22 @@ static void set_bggrad(SCInterpreter *scin, const char *options,
{
struct sc_state *st = &scin->state[scin->j];
GdkRGBA col1, col2;
- char *n2;
- char *optcopy = strdup(options);
- if ( options == NULL ) {
- fprintf(stderr, _("Invalid bg gradient spec '%s'\n"), options);
- return;
- }
-
- n2 = strchr(optcopy, ',');
- if ( n2 == NULL ) {
- fprintf(stderr, _("Invalid bg gradient spec '%s'\n"), options);
- return;
- }
+ if ( parse_colour_duo(options, &col1, &col2) == 0 ) {
- n2[0] = '\0';
+ st->bgcol[0] = col1.red;
+ st->bgcol[1] = col1.green;
+ st->bgcol[2] = col1.blue;
+ st->bgcol[3] = col1.alpha;
- gdk_rgba_parse(&col1, optcopy);
- gdk_rgba_parse(&col2, &n2[1]);
+ st->bgcol2[0] = col2.red;
+ st->bgcol2[1] = col2.green;
+ st->bgcol2[2] = col2.blue;
+ st->bgcol2[3] = col2.alpha;
- st->bgcol[0] = col1.red;
- st->bgcol[1] = col1.green;
- st->bgcol[2] = col1.blue;
- st->bgcol[3] = col1.alpha;
+ st->bggrad = grad;
- st->bgcol2[0] = col2.red;
- st->bgcol2[1] = col2.green;
- st->bgcol2[2] = col2.blue;
- st->bgcol2[3] = col2.alpha;
-
- st->bggrad = grad;
-
- free(optcopy);
+ }
}
@@ -611,13 +533,6 @@ struct frame *sc_interp_get_frame(SCInterpreter *scin)
}
-SCBlock *sc_interp_get_macro_real_block(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- return st->macro_real_block;
-}
-
-
static void set_frame(SCInterpreter *scin, struct frame *fr)
{
struct sc_state *st = &scin->state[scin->j];
@@ -649,33 +564,6 @@ SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang,
scin->cbl = NULL;
st = &scin->state[0];
- st->n_macros = 0;
- st->max_macros = 16;
- st->macros = malloc(16*sizeof(struct macro));
- if ( st->macros == NULL ) {
- free(scin->state);
- free(scin);
- return NULL;
- }
- st->n_styles = 0;
- st->max_styles = 16;
- st->styles = malloc(16*sizeof(struct macro));
- if ( st->styles == NULL ) {
- free(scin->state);
- free(scin);
- return NULL;
- }
- st->n_templates = 0;
- st->max_templates = 16;
- st->templates = malloc(16*sizeof(struct template));
- if ( st->templates == NULL ) {
- free(scin->state);
- free(scin);
- return NULL;
- }
- st->macro_contents = NULL;
- st->macro_real_block = NULL;
- st->macro_editable = 0;
st->fr = NULL;
st->paraspace[0] = 0.0;
st->paraspace[1] = 0.0;
@@ -696,7 +584,7 @@ SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang,
st->bgcol2[1] = 1.0;
st->bgcol2[2] = 1.0;
st->bgcol2[3] = 1.0;
- st->bggrad = GRAD_NOBG;
+ st->bggrad = GRAD_NONE;
scin->lang = lang;
/* The "ultimate" default font */
@@ -713,8 +601,6 @@ SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang,
void sc_interp_destroy(SCInterpreter *scin)
{
- /* FIXME: Free all templates and macros */
-
/* Empty the stack */
while ( scin->j > 0 ) {
sc_interp_restore(scin);
@@ -729,34 +615,6 @@ void sc_interp_destroy(SCInterpreter *scin)
}
-static int parse_double(const char *a, float v[2])
-{
- int nn;
-
- nn = sscanf(a, "%fx%f", &v[0], &v[1]);
- if ( nn != 2 ) {
- fprintf(stderr, _("Invalid size '%s'\n"), a);
- return 1;
- }
-
- return 0;
-}
-
-
-static int parse_tuple(const char *a, float v[4])
-{
- int nn;
-
- nn = sscanf(a, "%f,%f,%f,%f", &v[0], &v[1], &v[2], &v[3]);
- if ( nn != 4 ) {
- fprintf(stderr, _("Invalid tuple '%s'\n"), a);
- return 1;
- }
-
- return 0;
-}
-
-
static void set_padding(struct frame *fr, const char *opts)
{
float p[4];
@@ -788,19 +646,6 @@ static void set_paraspace(SCInterpreter *scin, const char *opts)
}
-static void set_slide_size(SCInterpreter *scin, const char *opts)
-{
- float p[2];
- struct sc_state *st = &scin->state[scin->j];
-
- if ( parse_double(opts, p) ) return;
-
- st->slide_width = p[0];
- st->slide_height = p[1];
- st->have_size = 1;
-}
-
-
void update_geom(struct frame *fr)
{
char geom[256];
@@ -1015,24 +860,17 @@ static void maybe_recurse_before(SCInterpreter *scin, SCBlock *child)
}
-static void maybe_recurse_after(SCInterpreter *scin, SCBlock *child)
+static void maybe_recurse_after(SCInterpreter *scin, SCBlock *child,
+ Stylesheet *ss)
{
if ( child == NULL ) return;
- sc_interp_add_blocks(scin, child);
+ sc_interp_add_blocks(scin, child, ss);
sc_interp_restore(scin);
}
-static int in_macro(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- if ( st->macro_contents == NULL ) return 0;
- return 1;
-}
-
-
-static void add_newpara(struct frame *fr, SCBlock *bl, SCBlock *mrb)
+static void add_newpara(struct frame *fr, SCBlock *bl)
{
Paragraph *last_para;
@@ -1043,7 +881,7 @@ static void add_newpara(struct frame *fr, SCBlock *bl, SCBlock *mrb)
/* The block after the \newpara will always be the first one of the
* next paragraph, by definition, even if it's \f or another \newpara */
- create_paragraph(fr, sc_block_next(mrb), sc_block_next(bl));
+ create_paragraph(fr, sc_block_next(bl));
}
@@ -1055,7 +893,6 @@ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl,
PangoFontDescription *fontdesc;
double *col;
struct sc_state *st = &scin->state[scin->j];
- SCBlock *rbl;
Paragraph *para;
/* Empty block? */
@@ -1064,47 +901,113 @@ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl,
fontdesc = sc_interp_get_fontdesc(scin);
col = sc_interp_get_fgcol(scin);
- rbl = bl;
- if ( st->macro_real_block != NULL ) {
- bl = st->macro_real_block;
- }
-
para = last_para(fr);
if ( (para == NULL) || (para_type(para) != PARA_TYPE_TEXT) ) {
/* Last paragraph is not text.
* or: no paragraphs yet.
* Either way: Create the first one */
- para = create_paragraph(fr, bl, rbl);
+ para = create_paragraph(fr, bl);
}
set_para_alignment(para, st->alignment);
- add_run(para, bl, rbl, fontdesc, col);
+ add_run(para, bl, fontdesc, col);
set_para_spacing(para, st->paraspace);
return 0;
}
-void sc_interp_run_style(SCInterpreter *scin, const char *sname)
+static void apply_style(SCInterpreter *scin, Stylesheet *ss, const char *path)
{
- int i;
- struct sc_state *st = &scin->state[scin->j];
+ char *result;
- for ( i=0; i<st->n_styles; i++ ) {
- if ( strcmp(sname, st->styles[i].name) == 0 ) {
- sc_interp_add_blocks(scin, st->styles[i].bl);
- return;
+ if ( ss == NULL ) return;
+
+ /* Font */
+ result = stylesheet_lookup(ss, path, "font");
+ if ( result != NULL ) set_font(scin, result);
+
+ /* Foreground colour */
+ result = stylesheet_lookup(ss, path, "fgcol");
+ if ( result != NULL ) set_colour(scin, result);
+
+ /* Background (vertical gradient) */
+ result = stylesheet_lookup(ss, path, "bggradv");
+ if ( result != NULL ) set_bggrad(scin, result, GRAD_VERT);
+
+ /* Background (horizontal gradient) */
+ result = stylesheet_lookup(ss, path, "bggradh");
+ if ( result != NULL ) set_bggrad(scin, result, GRAD_HORIZ);
+
+ /* Background (solid colour) */
+ result = stylesheet_lookup(ss, path, "bgcol");
+ if ( result != NULL ) set_bgcol(scin, result);
+
+ /* Padding */
+ result = stylesheet_lookup(ss, path, "pad");
+ if ( result != NULL ) set_padding(sc_interp_get_frame(scin), result);
+
+ /* Paragraph spacing */
+ result = stylesheet_lookup(ss, path, "paraspace");
+ if ( result != NULL ) set_paraspace(scin, result);
+
+ /* Alignment */
+ result = stylesheet_lookup(ss, path, "alignment");
+ if ( result != NULL ) {
+ if ( strcmp(result, "center") == 0 ) {
+ set_alignment(scin, PANGO_ALIGN_CENTER);
}
+ if ( strcmp(result, "left") == 0 ) {
+ set_alignment(scin, PANGO_ALIGN_LEFT);
+ }
+ if ( strcmp(result, "right") == 0 ) {
+ set_alignment(scin, PANGO_ALIGN_RIGHT);
+ }
+ }
+
+ update_bg(scin);
+}
+
+
+static void output_frame(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss,
+ const char *stylename)
+{
+ struct frame *fr;
+ SCBlock *child = sc_block_child(bl);
+ const char *options = sc_block_options(bl);
+ char *result;
+
+ fr = add_subframe(sc_interp_get_frame(scin));
+ fr->scblocks = bl;
+ fr->resizable = 1;
+ if ( fr == NULL ) {
+ fprintf(stderr, _("Failed to add frame.\n"));
+ return;
+ }
+
+ /* Lowest priority: current state of interpreter */
+ set_frame_default_style(fr, scin);
+
+ /* Next priority: geometry from stylesheet */
+ result = stylesheet_lookup(ss, stylename, "geometry");
+ if ( result != NULL ) {
+ parse_frame_options(fr, sc_interp_get_frame(scin), result);
}
+
+ /* Highest priority: parameters to \f (or \slidetitle etc) */
+ parse_frame_options(fr, sc_interp_get_frame(scin), options);
+
+ maybe_recurse_before(scin, child);
+ set_frame(scin, fr);
+ apply_style(scin, ss, stylename);
+ maybe_recurse_after(scin, child, ss);
}
-static int check_outputs(SCBlock *bl, SCInterpreter *scin)
+static int check_outputs(SCBlock *bl, SCInterpreter *scin, Stylesheet *ss)
{
const char *name = sc_block_name(bl);
const char *options = sc_block_options(bl);
- SCBlock *child = sc_block_child(bl);
- struct sc_state *st = &scin->state[scin->j];
if ( name == NULL ) {
add_text(sc_interp_get_frame(scin),
@@ -1116,11 +1019,7 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
if ( parse_image_options(options, sc_interp_get_frame(scin),
&w, &h, &filename) == 0 )
{
- SCBlock *rbl = bl;
- if ( st->macro_real_block != NULL ) {
- bl = st->macro_real_block;
- }
- add_image_para(sc_interp_get_frame(scin), bl, rbl,
+ add_image_para(sc_interp_get_frame(scin), bl,
filename, scin->is, w, h, 1);
free(filename);
} else {
@@ -1129,38 +1028,20 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
}
} else if ( strcmp(name, "f")==0 ) {
+ output_frame(scin, bl, ss, "$.slide.frame");
- struct frame *fr;
+ } else if ( strcmp(name, "slidetitle")==0 ) {
+ output_frame(scin, bl, ss, "$.slide.slidetitle");
- fr = add_subframe(sc_interp_get_frame(scin));
- fr->scblocks = bl;
- if ( in_macro(scin) ) {
- fr->resizable = 0;
- } else {
- fr->resizable = 1;
- }
- if ( fr == NULL ) {
- fprintf(stderr, _("Failed to add frame.\n"));
- return 1;
- }
-
- set_frame_default_style(fr, scin);
+ } else if ( strcmp(name, "prestitle")==0 ) {
+ output_frame(scin, bl, ss, "$.slide.prestitle");
- parse_frame_options(fr, sc_interp_get_frame(scin), options);
-
- maybe_recurse_before(scin, child);
- set_frame(scin, fr);
- sc_interp_run_style(scin, "frame");
- maybe_recurse_after(scin, child);
+ } else if ( strcmp(name, "author")==0 ) {
+ output_frame(scin, bl, ss, "$.slide.author");
} else if ( strcmp(name, "newpara")==0 ) {
-
struct frame *fr = sc_interp_get_frame(scin);
- SCBlock *rbl = bl;
- if ( st->macro_real_block != NULL ) {
- bl = st->macro_real_block;
- }
- add_newpara(fr, bl, rbl);
+ add_newpara(fr, bl);
} else {
return 0;
@@ -1170,68 +1051,7 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
}
-static int check_macro(const char *name, SCInterpreter *scin)
-{
- int i;
- struct sc_state *st = &scin->state[scin->j];
-
- if ( name == NULL ) return 0;
-
- for ( i=0; i<st->n_macros; i++ ) {
- if ( strcmp(st->macros[i].name, name) == 0 ) {
- return 1;
- }
- }
-
- return 0;
-}
-
-
-static void exec_macro(SCBlock *bl, SCInterpreter *scin, SCBlock *child)
-{
- struct sc_state *st = &scin->state[scin->j];
- int i;
- const char *name;
-
- name = sc_block_name(bl);
- for ( i=0; i<st->n_macros; i++ ) {
- if ( strcmp(st->macros[i].name, name) == 0 ) {
- sc_interp_save(scin);
- scin->state[scin->j].macro_real_block = bl;
- scin->state[scin->j].macro_contents = child;
- sc_interp_add_blocks(scin, scin->state[scin->j].macros[i].bl);
- sc_interp_restore(scin);
- break; /* Stop iterating, because "st" is now invalid */
- }
- }
-}
-
-
-static void run_macro_contents(SCInterpreter *scin)
-{
- struct sc_state *st = &scin->state[scin->j];
- SCBlock *contents = st->macro_contents;
-
- sc_interp_save(scin);
- scin->state[scin->j].macro_real_block = NULL;
- sc_interp_add_blocks(scin, contents);
- sc_interp_restore(scin);
-}
-
-
-static void run_editable(SCInterpreter *scin, SCBlock *contents)
-{
- //struct sc_state *st = &scin->state[scin->j];
-
- sc_interp_save(scin);
- //scin->state[scin->j].macro_real_block = NULL;
- scin->state[scin->j].macro_editable = 1;
- sc_interp_add_blocks(scin, contents);
- sc_interp_restore(scin);
-}
-
-
-int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl)
+int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss)
{
const char *name = sc_block_name(bl);
const char *options = sc_block_options(bl);
@@ -1241,16 +1061,11 @@ int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl)
//show_sc_blocks(bl);
//printf("<------------\n");
- if ( check_macro(name, scin) ) {
- sc_interp_save(scin);
- exec_macro(bl, scin, child);
- sc_interp_restore(scin);
-
- } else if ( check_callback(scin, bl) ) {
+ if ( check_callback(scin, bl) ) {
/* Handled in check_callback, don't do anything else */
} else if ((sc_interp_get_frame(scin) != NULL)
- && check_outputs(bl, scin) ) {
+ && check_outputs(bl, scin, ss) ) {
/* Block handled as output thing */
} else if ( name == NULL ) {
@@ -1258,95 +1073,86 @@ int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl)
} else if ( strcmp(name, "presentation") == 0 ) {
maybe_recurse_before(scin, child);
- sc_interp_run_style(scin, "narrative");
- maybe_recurse_after(scin, child);
-
- } else if ( strcmp(name, "stylesheet") == 0 ) {
- /* Ignore (see sc_interp_run_stylesheet) */
+ apply_style(scin, ss, "$.narrative");
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "slide") == 0 ) {
maybe_recurse_before(scin, child);
- sc_interp_run_style(scin, "slide");
- maybe_recurse_after(scin, child);
+ apply_style(scin, ss, "$.slide");
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "font") == 0 ) {
maybe_recurse_before(scin, child);
set_font(scin, options);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "fontsize") == 0 ) {
maybe_recurse_before(scin, child);
set_fontsize(scin, options);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "bold") == 0 ) {
maybe_recurse_before(scin, child);
set_bold(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "oblique") == 0 ) {
maybe_recurse_before(scin, child);
set_oblique(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "italic") == 0 ) {
maybe_recurse_before(scin, child);
set_italic(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "lalign") == 0 ) {
maybe_recurse_before(scin, child);
set_alignment(scin, PANGO_ALIGN_LEFT);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "ralign") == 0 ) {
maybe_recurse_before(scin, child);
set_alignment(scin, PANGO_ALIGN_RIGHT);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "center") == 0 ) {
maybe_recurse_before(scin, child);
set_alignment(scin, PANGO_ALIGN_CENTER);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "fgcol") == 0 ) {
maybe_recurse_before(scin, child);
set_colour(scin, options);
- maybe_recurse_after(scin, child);
-
- } else if ( strcmp(name, "contents") == 0 ) {
- run_macro_contents(scin);
-
- } else if ( strcmp(name, "editable") == 0 ) {
- run_editable(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "pad") == 0 ) {
maybe_recurse_before(scin, child);
set_padding(sc_interp_get_frame(scin), options);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "bgcol") == 0 ) {
maybe_recurse_before(scin, child);
set_bgcol(scin, options);
update_bg(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "bggradh") == 0 ) {
maybe_recurse_before(scin, child);
set_bggrad(scin, options, GRAD_HORIZ);
update_bg(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "bggradv") == 0 ) {
maybe_recurse_before(scin, child);
set_bggrad(scin, options, GRAD_VERT);
update_bg(scin);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else if ( strcmp(name, "paraspace") == 0 ) {
maybe_recurse_before(scin, child);
set_paraspace(scin, options);
- maybe_recurse_after(scin, child);
+ maybe_recurse_after(scin, child, ss);
} else {
@@ -1358,252 +1164,3 @@ int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl)
return 0;
}
-
-int sc_interp_add_blocks(SCInterpreter *scin, SCBlock *bl)
-{
- while ( bl != NULL ) {
- if ( sc_interp_add_block(scin, bl) ) return 1;
- bl = sc_block_next(bl);
- }
-
- return 0;
-}
-
-
-static int try_add_style(SCInterpreter *scin, const char *options, SCBlock *bl)
-{
- struct sc_state *st = &scin->state[scin->j];
- char *nn;
- char *comma;
- int i;
-
- nn = strdup(options);
- comma = strchr(nn, ',');
- if ( comma != NULL ) {
- comma[0] = '\0';
- }
-
- for ( i=0; i<st->n_styles; i++ ) {
- if ( strcmp(st->styles[i].name, nn) == 0 ) {
- st->styles[i].name = nn;
- st->styles[i].bl = bl;
- st->styles[i].prev = NULL; /* FIXME: Stacking */
- return 0;
- }
- }
-
- if ( st->max_styles == st->n_styles ) {
-
- struct macro *styles_new;
-
- styles_new = realloc(st->styles, sizeof(struct macro)
- * (st->max_styles+16));
- if ( styles_new == NULL ) {
- fprintf(stderr, _("Failed to add style.\n"));
- return 1;
- }
-
- st->styles = styles_new;
- st->max_styles += 16;
-
- }
-
- i = st->n_styles++;
-
- st->styles[i].name = nn;
- st->styles[i].bl = bl;
- st->styles[i].prev = NULL; /* FIXME: Stacking */
-
- return 0;
-}
-
-
-static int try_add_macro(SCInterpreter *scin, const char *options, SCBlock *bl)
-{
- struct sc_state *st = &scin->state[scin->j];
- char *nn;
- char *comma;
- int i;
-
- nn = strdup(options);
- comma = strchr(nn, ',');
- if ( comma != NULL ) {
- comma[0] = '\0';
- }
-
- for ( i=0; i<st->n_macros; i++ ) {
- if ( strcmp(st->macros[i].name, nn) == 0 ) {
- st->macros[i].name = nn;
- st->macros[i].bl = bl;
- st->macros[i].prev = NULL; /* FIXME: Stacking */
- return 0;
- }
- }
-
- if ( st->max_macros == st->n_macros ) {
-
- struct macro *macros_new;
-
- macros_new = realloc(st->macros, sizeof(struct macro)
- * (st->max_macros+16));
- if ( macros_new == NULL ) {
- fprintf(stderr, _("Failed to add macro.\n"));
- return 1;
- }
-
- st->macros = macros_new;
- st->max_macros += 16;
-
- }
-
- i = st->n_macros++;
-
- st->macros[i].name = nn;
- st->macros[i].bl = bl;
- st->macros[i].prev = NULL; /* FIXME: Stacking */
-
- return 0;
-}
-
-
-static int try_add_template(SCInterpreter *scin, const char *options, SCBlock *bl)
-{
- struct sc_state *st = &scin->state[scin->j];
- char *nn;
- char *comma;
- int i;
-
- nn = strdup(options);
- comma = strchr(nn, ',');
- if ( comma != NULL ) {
- comma[0] = '\0';
- }
-
- for ( i=0; i<st->n_templates; i++ ) {
- if ( strcmp(st->templates[i].name, nn) == 0 ) {
- fprintf(stderr, _("Duplicate template '%s'\n"), nn);
- return 0;
- }
- }
-
- if ( st->max_templates == st->n_templates ) {
-
- struct template *templates_new;
-
- templates_new = realloc(st->templates, sizeof(struct template)
- * (st->max_templates+16));
- if ( templates_new == NULL ) {
- fprintf(stderr, _("Failed to add templates\n"));
- return 1;
- }
-
- st->templates = templates_new;
- st->max_templates += 16;
-
- }
-
- i = st->n_templates++;
-
- st->templates[i].name = nn;
- st->templates[i].bl = bl;
-
- return 0;
-}
-
-void add_macro(SCInterpreter *scin, const char *mname, const char *contents)
-{
- SCBlock *bl = sc_parse(contents);
- try_add_macro(scin, mname, bl);
-}
-
-
-void sc_interp_run_stylesheet(SCInterpreter *scin, SCBlock *bl)
-{
- if ( bl == NULL ) return;
-
- if ( strcmp(sc_block_name(bl), "stylesheet") != 0 ) {
- fprintf(stderr, _("Style sheet isn't a style sheet.\n"));
- return;
- }
-
- bl = sc_block_child(bl);
-
- while ( bl != NULL ) {
-
- const char *name = sc_block_name(bl);
- const char *options = sc_block_options(bl);
-
- if ( name == NULL ) {
-
- /* Do nothing */
-
- } else if ( strcmp(name, "def") == 0 ) {
- try_add_macro(scin, options, sc_block_child(bl));
-
- } else if ( strcmp(name, "ss") == 0 ) { /* Backward compatibility */
- try_add_macro(scin, options, sc_block_child(bl));
-
- } else if ( strcmp(name, "style") == 0 ) {
- try_add_style(scin, options, sc_block_child(bl));
-
- } else if ( strcmp(name, "template") == 0 ) {
- try_add_template(scin, options, sc_block_child(bl));
-
- } else if ( strcmp(name, "font") == 0 ) {
- set_font(scin, options);
-
- } else if ( strcmp(name, "fgcol") == 0 ) {
- set_colour(scin, options);
-
- } else if ( strcmp(name, "bgcol") == 0 ) {
- set_bgcol(scin, options);
- update_bg(scin);
-
- } else if ( strcmp(name, "bggradh") == 0 ) {
- set_bggrad(scin, options, GRAD_HORIZ);
- update_bg(scin);
-
- } else if ( strcmp(name, "bggradv") == 0 ) {
- set_bggrad(scin, options, GRAD_VERT);
- update_bg(scin);
-
- } else if ( strcmp(name, "paraspace") == 0 ) {
- set_paraspace(scin, options);
-
- } else if ( strcmp(name, "slidesize") == 0 ) {
- set_slide_size(scin, options);
-
- }
-
- bl = sc_block_next(bl);
-
- }
-}
-
-
-int sc_interp_get_slide_size(SCInterpreter *scin, double *w, double *h)
-{
- if ( !scin->state->have_size ) return 1;
- *w = scin->state->slide_width;
- *h = scin->state->slide_height;
- return 0;
-}
-
-
-struct template_id *sc_interp_get_templates(SCInterpreter *scin, int *np)
-{
- struct template_id *list;
- int i;
-
- list = malloc(sizeof(struct template_id)*scin->state->n_templates);
- if ( list == NULL ) return NULL;
-
- for ( i=0; i<scin->state->n_templates; i++ ) {
- list[i].name = strdup(scin->state->templates[i].name);
- list[i].friendlyname = strdup(scin->state->templates[i].name);
- list[i].scblock = sc_block_copy(scin->state->templates[i].bl);
- }
-
- *np = scin->state->n_templates;
- return list;
-}
diff --git a/src/sc_interp.h b/src/sc_interp.h
index 7b00aaa..418d6a6 100644
--- a/src/sc_interp.h
+++ b/src/sc_interp.h
@@ -41,6 +41,7 @@ typedef int (*SCCallbackClickFunc)(double x, double y, void *, void *);
#include "frame.h"
#include "imagestore.h"
+#include "stylesheet.h"
extern SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang,
ImageStore *is, struct frame *top);
@@ -49,13 +50,7 @@ extern void sc_interp_destroy(SCInterpreter *scin);
extern void sc_interp_save(SCInterpreter *scin);
extern void sc_interp_restore(SCInterpreter *scin);
-extern int sc_interp_add_blocks(SCInterpreter *scin, SCBlock *bl);
-extern int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl);
-
-extern void sc_interp_run_stylesheet(SCInterpreter *scin, SCBlock *bl);
-extern void sc_interp_run_style(SCInterpreter *scin, const char *sname);
-extern void add_macro(SCInterpreter *scin, const char *mname,
- const char *contents);
+extern int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss);
/* Callback lists */
@@ -73,28 +68,8 @@ extern struct frame *sc_interp_get_frame(SCInterpreter *scin);
extern PangoFont *sc_interp_get_font(SCInterpreter *scin);
extern PangoFontDescription *sc_interp_get_fontdesc(SCInterpreter *scin);
extern double *sc_interp_get_fgcol(SCInterpreter *scin);
-extern double *sc_interp_get_bgcol(SCInterpreter *scin);
-extern double *sc_interp_get_bgcol2(SCInterpreter *scin);
-extern GradientType sc_interp_get_bggrad(SCInterpreter *scin);
-
-extern int sc_interp_get_slide_size(SCInterpreter *scin, double *w, double *h);
-extern SCBlock *sc_interp_get_macro_real_block(SCInterpreter *scin);
-
-extern int sc_interp_get_ascent(SCInterpreter *scin);
-extern int sc_interp_get_height(SCInterpreter *scin);
extern void update_geom(struct frame *fr);
-struct template_id
-{
- char *name;
- char *friendlyname;
- SCBlock *scblock;
-};
-
-extern struct template_id *sc_interp_get_templates(SCInterpreter *scin,
- int *np);
-
-
#endif /* SC_INTERP_H */
diff --git a/src/sc_parse.c b/src/sc_parse.c
index b66dc1f..e8904a0 100644
--- a/src/sc_parse.c
+++ b/src/sc_parse.c
@@ -264,26 +264,8 @@ static SCBlock *sc_find_parent(SCBlock *top, SCBlock *find)
}
-void sc_block_substitute(SCBlock **top, SCBlock *old, SCBlock *new)
-{
- if ( old == NULL ) {
- fprintf(stderr, _("Substituting nothing!\n"));
- return;
- }
-
- if ( old == *top ) {
- /* It is the first block */
- new->next = old->next;
- *top = new;
- } else {
- sc_block_unlink(top, old);
- sc_block_append_p(*top, new);
- }
-}
-
-
/* Unlink "deleteme", which is somewhere under "top" */
-int sc_block_unlink(SCBlock **top, SCBlock *deleteme)
+static int sc_block_unlink(SCBlock **top, SCBlock *deleteme)
{
SCBlock *parent = sc_find_parent(*top, deleteme);
if ( parent == NULL ) {
@@ -413,36 +395,6 @@ char *serialise_sc_block(const SCBlock *bl)
}
-/* Serialise an entire chain of blocks */
-char *serialise_sc_block_chain(const SCBlock *bl)
-{
- char *a = strdup("");
- size_t len = 1;
-
- if ( a == NULL ) return NULL;
-
- while ( bl != NULL ) {
-
- char *c = serialise_sc_block(bl);
- if ( c == NULL ) {
- free(a);
- return NULL;
- }
-
- len += strlen(c);
- a = realloc(a, len);
- if ( a == NULL ) return NULL;
- strcat(a, c);
- free(c);
-
- bl = bl->next;
-
- }
-
- return a;
-}
-
-
int save_sc_block(GOutputStream *fh, const SCBlock *bl)
{
while ( bl != NULL ) {
@@ -770,17 +722,6 @@ void sc_block_set_contents(SCBlock *bl, char *con)
}
-SCBlock *find_last_child(SCBlock *bl)
-{
- if ( bl == NULL ) return NULL;
- if ( bl->child == NULL ) return NULL;
-
- bl = bl->child;
- while ( bl->next != NULL ) bl = bl->next;
- return bl;
-}
-
-
void sc_insert_text(SCBlock *b1, size_t o1, const char *t)
{
if ( b1->contents == NULL ) {
@@ -850,37 +791,6 @@ size_t scblock_delete_text(SCBlock *b, ssize_t o1, ssize_t o2)
}
-/* Create a deep copy of "bl", including all its children */
-SCBlock *sc_block_copy(const SCBlock *bl)
-{
- SCBlock *copy;
- SCBlock *first_copy;
-
- first_copy = sc_block_new();
-
- copy = first_copy;
- do {
-
- if ( bl->name != NULL ) copy->name = strdup(bl->name);
- if ( bl->options != NULL ) copy->options = strdup(bl->options);
- if ( bl->contents != NULL ) copy->contents = strdup(bl->contents);
- if ( bl->child != NULL ) copy->child = sc_block_copy(bl->child);
-
- bl = bl->next;
-
- if ( bl != NULL ) {
- SCBlock *nn;
- nn = sc_block_new();
- copy->next = nn;
- copy = nn;
- }
-
- } while ( bl != NULL );
-
- return first_copy;
-}
-
-
static char *s_strdup(const char *a)
{
if ( a == NULL ) return NULL;
diff --git a/src/sc_parse.h b/src/sc_parse.h
index 9277ee6..17ce2dd 100644
--- a/src/sc_parse.h
+++ b/src/sc_parse.h
@@ -37,14 +37,11 @@ extern SCBlock *sc_parse(const char *sc);
extern SCBlock *sc_block_new(void);
extern void sc_block_free(SCBlock *bl);
-extern SCBlock *sc_block_copy(const SCBlock *bl);
-
extern SCBlock *sc_block_next(const SCBlock *bl);
extern SCBlock *sc_block_child(const SCBlock *bl);
extern const char *sc_block_name(const SCBlock *bl);
extern const char *sc_block_options(const SCBlock *bl);
extern const char *sc_block_contents(const SCBlock *bl);
-extern void sc_block_substitute(SCBlock **top, SCBlock *old, SCBlock *new);
extern SCBlock *sc_block_append(SCBlock *bl,
char *name, char *opt, char *contents,
@@ -68,9 +65,6 @@ extern SCBlock *sc_block_insert_after(SCBlock *afterme,
char *name, char *opt, char *contents);
extern int sc_block_delete(SCBlock **top, SCBlock *deleteme);
-extern int sc_block_unlink(SCBlock **top, SCBlock *deleteme);
-
-extern SCBlock *find_last_child(SCBlock *bl);
extern void sc_block_set_name(SCBlock *bl, char *nam);
@@ -84,7 +78,6 @@ extern void show_sc_blocks(const SCBlock *bl);
extern void show_sc_block(const SCBlock *bl, const char *prefix);
extern char *serialise_sc_block(const SCBlock *bl);
-extern char *serialise_sc_block_chain(const SCBlock *bl);
extern int save_sc_block(GOutputStream *fh, const SCBlock *bl);
extern size_t scblock_delete_text(SCBlock *b, ssize_t o1, ssize_t o2);
diff --git a/src/slide_window.c b/src/slide_window.c
index b010d1b..e23a3d7 100644
--- a/src/slide_window.c
+++ b/src/slide_window.c
@@ -109,7 +109,7 @@ static void delete_frame_sig(GSimpleAction *action, GVariant *parameter,
/* Change the editor's slide to "np" */
-void change_edit_slide(SlideWindow *sw, SCBlock *np)
+static void change_edit_slide(SlideWindow *sw, SCBlock *np)
{
sc_editor_set_slidenum(sw->sceditor, slide_number(sw->p, np));
diff --git a/src/slide_window.h b/src/slide_window.h
index 77de920..b1d39a8 100644
--- a/src/slide_window.h
+++ b/src/slide_window.h
@@ -31,6 +31,5 @@ typedef struct _slidewindow SlideWindow;
extern SlideWindow *slide_window_open(struct presentation *p, SCBlock *scblocks,
GApplication *app);
-extern void change_edit_slide(SlideWindow *sw, SCBlock *np);
#endif /* SLIDEWINDOW_H */
diff --git a/src/stylesheet.c b/src/stylesheet.c
new file mode 100644
index 0000000..96172a4
--- /dev/null
+++ b/src/stylesheet.c
@@ -0,0 +1,234 @@
+/*
+ * stylesheet.c
+ *
+ * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium 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 <json-glib/json-glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+
+#include "stylesheet.h"
+#include "utils.h"
+
+
+struct _stylesheet {
+ JsonNode *root;
+};
+
+
+static int find_comma(const char *a)
+{
+ int i = 0;
+ int in_brackets = 0;
+ size_t len = strlen(a);
+
+ do {
+ if ( (a[i] == ',') && !in_brackets ) return i;
+ if ( a[i] == '(' ) in_brackets++;
+ if ( a[i] == ')' ) in_brackets--;
+ i++;
+ } while ( i < len );
+ return 0;
+}
+
+
+int parse_colour_duo(const char *a, GdkRGBA *col1, GdkRGBA *col2)
+{
+ char *acopy;
+ int cpos;
+
+ acopy = strdup(a);
+ if ( acopy == NULL ) return 1;
+
+ cpos = find_comma(acopy);
+ if ( cpos == 0 ) {
+ fprintf(stderr, _("Invalid bg gradient spec '%s'\n"), a);
+ return 1;
+ }
+
+ acopy[cpos] = '\0';
+
+ if ( gdk_rgba_parse(col1, acopy) != TRUE ) {
+ fprintf(stderr, _("Failed to parse colour: %s\n"), acopy);
+ }
+ if ( gdk_rgba_parse(col2, &acopy[cpos+1]) != TRUE ) {
+ fprintf(stderr, _("Failed to parse colour: %s\n"), &acopy[cpos+1]);
+ }
+
+ free(acopy);
+ return 0;
+}
+
+
+Stylesheet *stylesheet_load(GFile *file)
+{
+ JsonParser *parser;
+ gboolean r;
+ GError *err = NULL;
+ Stylesheet *ss;
+ char *everything;
+ gsize len;
+
+ printf("Trying stylesheet '%s'\n", g_file_get_uri(file));
+
+ ss = calloc(1, sizeof(Stylesheet));
+ if ( ss == NULL ) return NULL;
+
+ parser = json_parser_new();
+
+ if ( !g_file_load_contents(file, NULL, &everything, &len, NULL, NULL) ) {
+ fprintf(stderr, _("Failed to load stylesheet '%s'\n"),
+ g_file_get_uri(file));
+ return NULL;
+ }
+
+ r = json_parser_load_from_data(parser, everything, len, &err);
+ if ( r == FALSE ) {
+ fprintf(stderr, "Failed to load style sheet: '%s'\n", err->message);
+ return NULL;
+ }
+
+ ss->root = json_parser_steal_root(parser);
+ g_object_unref(parser);
+
+ return ss;
+}
+
+
+static JsonObject *find_stylesheet_object(Stylesheet *ss, const char *path,
+ JsonNode **freeme)
+{
+ JsonNode *node;
+ JsonObject *obj;
+ JsonArray *array;
+ GError *err = NULL;
+
+ node = json_path_query(path, ss->root, &err);
+ array = json_node_get_array(node);
+
+ if ( json_array_get_length(array) != 1 ) {
+ json_node_unref(node);
+ fprintf(stderr, "More than one result in SS lookup (%s)!\n", path);
+ return NULL;
+ }
+
+ obj = json_array_get_object_element(array, 0);
+ if ( obj == NULL ) {
+ printf("%s not a JSON object\n", path);
+ json_node_unref(node);
+ return NULL;
+ }
+
+ *freeme = node;
+ return obj;
+}
+
+
+char *stylesheet_lookup(Stylesheet *ss, const char *path, const char *key)
+{
+ JsonObject *obj;
+ char *ret = NULL;
+ JsonNode *node = NULL;
+
+ if ( ss == NULL ) {
+ fprintf(stderr, _("No stylesheet!\n"));
+ return NULL;
+ }
+
+ obj = find_stylesheet_object(ss, path, &node);
+
+ if ( json_object_has_member(obj, key) ) {
+
+ const gchar *v;
+ v = json_object_get_string_member(obj, key);
+ if ( v != NULL ) {
+ ret = strdup(v);
+ } else {
+ fprintf(stderr, "Error retrieving %s.%s\n", path, key);
+ }
+
+ } /* else not found, too bad */
+
+ if ( node != NULL ) json_node_unref(node);
+ return ret;
+}
+
+
+int stylesheet_set(Stylesheet *ss, const char *path, const char *key,
+ const char *new_val)
+{
+ JsonObject *obj;
+ JsonNode *node = NULL;
+ int r = 1;
+
+ if ( ss == NULL ) {
+ fprintf(stderr, _("No stylesheet!\n"));
+ return 1;
+ }
+
+ obj = find_stylesheet_object(ss, path, &node);
+ if ( obj != NULL ) {
+ json_object_set_string_member(obj, key, new_val);
+ r = 0;
+ } /* else most likely the object (e.g. "$.slide", "$.slide.frame",
+ * "$.narrative" etc doesn't exist */
+
+ if ( node != NULL ) json_node_unref(node);
+ return r;
+}
+
+
+int stylesheet_delete(Stylesheet *ss, const char *path, const char *key)
+{
+ JsonObject *obj;
+ JsonNode *node = NULL;
+ int r = 1;
+
+ if ( ss == NULL ) {
+ fprintf(stderr, _("No stylesheet!\n"));
+ return 1;
+ }
+
+ obj = find_stylesheet_object(ss, path, &node);
+ if ( obj != NULL ) {
+ json_object_remove_member(obj, key);
+ r = 0;
+ } /* else most likely the object (e.g. "$.slide", "$.slide.frame",
+ * "$.narrative" etc doesn't exist */
+
+ if ( node != NULL ) json_node_unref(node);
+ return r;
+}
+
+
+void stylesheet_free(Stylesheet *ss)
+{
+ g_object_unref(ss->root);
+ free(ss);
+}
+
diff --git a/src/stylesheet.h b/src/stylesheet.h
new file mode 100644
index 0000000..c24c62c
--- /dev/null
+++ b/src/stylesheet.h
@@ -0,0 +1,48 @@
+/*
+ * stylesheet.h
+ *
+ * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium 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 STYLESHEET_H
+#define STYLESHEET_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+
+typedef struct _stylesheet Stylesheet;
+
+extern Stylesheet *stylesheet_load(GFile *file);
+
+extern int parse_colour_duo(const char *a, GdkRGBA *col1, GdkRGBA *col2);
+
+extern char *stylesheet_lookup(Stylesheet *ss, const char *path, const char *key);
+
+extern int stylesheet_set(Stylesheet *ss, const char *path, const char *key,
+ const char *new_val);
+
+extern int stylesheet_delete(Stylesheet *ss, const char *path, const char *key);
+
+extern void stylesheet_free(Stylesheet *ss);
+
+#endif /* STYLESHEET_H */
diff --git a/src/stylesheet_editor.c b/src/stylesheet_editor.c
index 66e8afa..8100472 100644
--- a/src/stylesheet_editor.c
+++ b/src/stylesheet_editor.c
@@ -33,12 +33,13 @@
#include "stylesheet_editor.h"
#include "presentation.h"
#include "sc_interp.h"
+#include "stylesheet.h"
+#include "utils.h"
G_DEFINE_TYPE_WITH_CODE(StylesheetEditor, stylesheet_editor,
GTK_TYPE_DIALOG, NULL)
-static void set_values_from_presentation(StylesheetEditor *se);
struct _sspriv
{
@@ -46,175 +47,247 @@ struct _sspriv
};
-static SCBlock *find_block(SCBlock *bl, const char *find)
+static void set_font_from_ss(Stylesheet *ss, const char *path, GtkWidget *w)
{
- while ( bl != NULL ) {
-
- const char *name = sc_block_name(bl);
- if ( (name != NULL) && (strcmp(name, find)==0) ) {
- return bl;
- }
-
- bl = sc_block_next(bl);
-
+ char *result = stylesheet_lookup(ss, path, "font");
+ if ( result != NULL ) {
+ gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), result);
}
-
- return NULL;
}
-static void find_replace(SCBlock *parent, const char *find, const char *seti)
+static void set_col_from_ss(Stylesheet *ss, const char *path, GtkWidget *w)
{
- SCBlock *bl = find_block(sc_block_child(parent), find);
-
- if ( bl != NULL ) {
+ char *result = stylesheet_lookup(ss, path, "fgcol");
+ if ( result != NULL ) {
+ GdkRGBA rgba;
+ if ( gdk_rgba_parse(&rgba, result) == TRUE ) {
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(w), &rgba);
+ }
+ }
+}
- printf("replacing '%s' with '%s'\n", sc_block_options(bl), seti);
- sc_block_set_options(bl, strdup(seti));
+static void set_vals_from_ss(Stylesheet *ss, const char *path, const char *key,
+ GtkWidget *wl, GtkWidget *wr,
+ GtkWidget *wt, GtkWidget *wb)
+{
+ char *result = stylesheet_lookup(ss, path, key);
+ if ( result != NULL ) {
+ float v[4];
+ if ( parse_tuple(result, v) == 0 ) {
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(wl), v[0]);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(wr), v[1]);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(wt), v[2]);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(wb), v[3]);
+ } else {
+ fprintf(stderr, _("Failed to parse quad: %s\n"), result);
+ }
} else {
-
- /* Block not found -> create it */
- sc_block_append_inside(parent, strdup(find), strdup(seti), NULL);
-
+ printf("Not found %s\n", path);
}
}
-static SCBlock *find_or_create_style(struct presentation *p, const char *style_name)
+static void set_size_from_ss(Stylesheet *ss, const char *path,
+ GtkWidget *ww, GtkWidget *wh)
{
- SCBlock *bl;
- const char *name;
-
- /* If no stylesheet yet, create one now */
- if ( p->stylesheet == NULL ) {
- p->stylesheet = sc_parse("\\stylesheet");
- if ( p->stylesheet == NULL ) {
- fprintf(stderr, "WARNING: Couldn't create stylesheet\n");
- return NULL;
+ char *result = stylesheet_lookup(ss, path, "size");
+ if ( result != NULL ) {
+ float v[2];
+ if ( parse_double(result, v) == 0 ) {
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(ww), v[0]);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(wh), v[1]);
+ } else {
+ fprintf(stderr, _("Failed to parse double: %s\n"), result);
}
- sc_block_append_p(p->stylesheet, p->scblocks);
- p->scblocks = p->stylesheet;
+ } else {
+ printf("Not found %s\n", path);
}
- bl = p->stylesheet;
+}
- name = sc_block_name(bl);
- if ( (name != NULL) && (strcmp(name, "stylesheet")==0) ) {
- bl = sc_block_child(bl);
+static void set_bg_from_ss(Stylesheet *ss, const char *path, GtkWidget *wcol,
+ GtkWidget *wcol2, GtkWidget *wgrad)
+{
+ char *result;
+ int found = 0;
+
+ result = stylesheet_lookup(ss, path, "bgcol");
+ if ( result != NULL ) {
+ GdkRGBA rgba;
+ found = 1;
+ if ( gdk_rgba_parse(&rgba, result) == TRUE ) {
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba);
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "flat");
+ gtk_widget_set_sensitive(wcol, TRUE);
+ gtk_widget_set_sensitive(wcol2, FALSE);
+ } else {
+ fprintf(stderr, _("Failed to parse colour: %s\n"), result);
+ }
}
- while ( bl != NULL ) {
-
- const char *name = sc_block_name(bl);
- const char *options = sc_block_options(bl);
- if ( (name != NULL) && (strcmp(name, "style")==0)
- && (strcmp(options, style_name)==0) )
- {
- return bl;
+ result = stylesheet_lookup(ss, path, "bggradv");
+ if ( result != NULL ) {
+ GdkRGBA rgba1, rgba2;
+ found = 1;
+ if ( parse_colour_duo(result, &rgba1, &rgba2) == 0 ) {
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba1);
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol2), &rgba2);
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "vert");
+ gtk_widget_set_sensitive(wcol, TRUE);
+ gtk_widget_set_sensitive(wcol2, TRUE);
}
+ }
- bl = sc_block_next(bl);
+ result = stylesheet_lookup(ss, path, "bggradh");
+ if ( result != NULL ) {
+ GdkRGBA rgba1, rgba2;
+ found = 1;
+ if ( parse_colour_duo(result, &rgba1, &rgba2) == 0 ) {
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba1);
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol2), &rgba2);
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "horiz");
+ gtk_widget_set_sensitive(wcol, TRUE);
+ gtk_widget_set_sensitive(wcol2, TRUE);
+ }
+ }
+ if ( !found ) {
+ GdkRGBA rgba;
+ rgba.red = 1.0;
+ rgba.green = 1.0;
+ rgba.blue = 1.0;
+ rgba.alpha = 0.0;
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "flat");
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba);
+ gtk_widget_set_sensitive(wcol, TRUE);
+ gtk_widget_set_sensitive(wcol2, FALSE);
}
+}
- /* Not found -> add style */
- return sc_block_append_inside(p->stylesheet, strdup("style"),
- strdup(style_name), NULL);
+
+static void set_values_from_presentation(StylesheetEditor *se)
+{
+ Stylesheet *ss = se->priv->p->stylesheet;
+
+ /* Narrative */
+ set_font_from_ss(ss, "$.narrative", se->narrative_style_font);
+ set_col_from_ss(ss, "$.narrative", se->narrative_style_fgcol);
+ set_bg_from_ss(ss, "$.narrative", se->narrative_style_bgcol,
+ se->narrative_style_bgcol2,
+ se->narrative_style_bggrad);
+ set_vals_from_ss(ss, "$.narrative", "pad", se->narrative_style_padding_l,
+ se->narrative_style_padding_r,
+ se->narrative_style_padding_t,
+ se->narrative_style_padding_b);
+ set_vals_from_ss(ss, "$.narrative", "paraspace", se->narrative_style_paraspace_l,
+ se->narrative_style_paraspace_r,
+ se->narrative_style_paraspace_t,
+ se->narrative_style_paraspace_b);
+
+ /* Slides */
+ set_size_from_ss(ss, "$.slide", se->slide_size_w, se->slide_size_h);
+ set_bg_from_ss(ss, "$.slide", se->slide_style_bgcol,
+ se->slide_style_bgcol2,
+ se->slide_style_bggrad);
+
+
+ /* Frames */
+ set_font_from_ss(ss, "$.slide.frame", se->frame_style_font);
+ set_col_from_ss(ss, "$.slide.frame", se->frame_style_fgcol);
+ set_bg_from_ss(ss, "$.slide.frame", se->frame_style_bgcol,
+ se->frame_style_bgcol2,
+ se->frame_style_bggrad);
+ set_vals_from_ss(ss, "$.slide.frame", "pad", se->frame_style_padding_l,
+ se->frame_style_padding_r,
+ se->frame_style_padding_t,
+ se->frame_style_padding_b);
+ set_vals_from_ss(ss, "$.slide.frame", "paraspace", se->frame_style_paraspace_l,
+ se->frame_style_paraspace_r,
+ se->frame_style_paraspace_t,
+ se->frame_style_paraspace_b);
}
-static void set_ss(struct presentation *p, const char *style_name,
- const char *find, const char *seti)
+static GradientType id_to_gradtype(const gchar *id)
{
- SCBlock *bl = find_or_create_style(p, style_name);
- if ( bl == NULL ) {
- fprintf(stderr, "WARNING: Couldn't find style\n");
- return;
- }
- find_replace(bl, find, seti);
+ assert(id != NULL);
+ if ( strcmp(id, "flat") == 0 ) return GRAD_NONE;
+ if ( strcmp(id, "horiz") == 0 ) return GRAD_HORIZ;
+ if ( strcmp(id, "vert") == 0 ) return GRAD_VERT;
+ return GRAD_NONE;
}
-static void set_ss_bg_block(SCBlock *bl, GradientType bggrad,
- GdkRGBA col1, GdkRGBA col2)
+static void update_bg(struct presentation *p, const char *style_name,
+ GtkWidget *bggradw, GtkWidget *col1w, GtkWidget*col2w)
{
- char tmp[64];
+ GradientType g;
+ const gchar *id;
+ GdkRGBA rgba;
+ gchar *col1;
+ gchar *col2;
+ gchar *gradient;
- switch ( bggrad ) {
+ id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(bggradw));
+ g = id_to_gradtype(id);
- case GRAD_NONE :
- sc_block_set_name(bl, strdup("bgcol"));
- snprintf(tmp, 63, "#%.2x%.2x%.2x",
- (int)(col1.red*255), (int)(col1.green*255), (int)(col1.blue*255));
- sc_block_set_options(bl, strdup(tmp));
- break;
+ gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(col1w), &rgba);
+ if ( rgba.alpha < 0.000001 ) rgba.alpha = 0.0;
+ col1 = gdk_rgba_to_string(&rgba);
- case GRAD_VERT :
- sc_block_set_name(bl, strdup("bggradv"));
- snprintf(tmp, 63, "#%.2x%.2x%.2x,#%.2x%.2x%.2x",
- (int)(col1.red*255), (int)(col1.green*255), (int)(col1.blue*255),
- (int)(col2.red*255), (int)(col2.green*255), (int)(col2.blue*255));
- sc_block_set_options(bl, strdup(tmp));
+ gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(col2w), &rgba);
+ col2 = gdk_rgba_to_string(&rgba);
+
+ gradient = g_strconcat(col1, ",", col2, NULL);
+
+ switch ( g ) {
+
+ case GRAD_NONE :
+ stylesheet_set(p->stylesheet, style_name, "bgcol",
+ col1);
+ stylesheet_delete(p->stylesheet, style_name, "bggradv");
+ stylesheet_delete(p->stylesheet, style_name, "bggradh");
break;
case GRAD_HORIZ :
- sc_block_set_name(bl, strdup("bggradh"));
- snprintf(tmp, 63, "#%.2x%.2x%.2x,#%.2x%.2x%.2x",
- (int)(col1.red*255), (int)(col1.green*255), (int)(col1.blue*255),
- (int)(col2.red*255), (int)(col2.green*255), (int)(col2.blue*255));
- sc_block_set_options(bl, strdup(tmp));
+ stylesheet_set(p->stylesheet, style_name, "bggradh",
+ gradient);
+ stylesheet_delete(p->stylesheet, style_name, "bggradv");
+ stylesheet_delete(p->stylesheet, style_name, "bgcol");
break;
- case GRAD_NOBG :
- printf("no bg\n");
- sc_block_set_name(bl, NULL);
- sc_block_set_options(bl, NULL);
- sc_block_set_contents(bl, NULL);
+ case GRAD_VERT :
+ stylesheet_set(p->stylesheet, style_name, "bggradv",
+ gradient);
+ stylesheet_delete(p->stylesheet, style_name, "bggradh");
+ stylesheet_delete(p->stylesheet, style_name, "bgcol");
break;
}
-}
-
-
-static int try_set_block(SCBlock **parent, const char *name,
- GradientType bggrad, GdkRGBA col1, GdkRGBA col2)
-{
- SCBlock *ibl;
-
- ibl = find_block(sc_block_child(*parent), name);
- if ( ibl != NULL ) {
- if ( bggrad != GRAD_NOBG ) {
- set_ss_bg_block(ibl, bggrad, col1, col2);
- return 1;
- } else {
- sc_block_delete(parent, ibl);
- return 1;
- }
- }
- return 0;
+ g_free(gradient);
+ g_free(col1);
+ g_free(col2);
}
-static void update_bg(struct presentation *p, const char *style_name,
- GradientType bggrad, GdkRGBA col1, GdkRGBA col2)
+static void update_spacing(struct presentation *p, const char *style_name,
+ const char *key, GtkWidget *wl, GtkWidget *wr,
+ GtkWidget *wt, GtkWidget *wb)
{
- int done;
- SCBlock *bl;
+ int v[4];
+ char tmp[256];
- bl = find_or_create_style(p, style_name);
- if ( bl == NULL ) {
- fprintf(stderr, "WARNING: Couldn't find style\n");
- return;
- }
+ v[0] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wl));
+ v[1] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wr));
+ v[2] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wt));
+ v[3] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wb));
- /* FIXME: What if there are two of these? */
- done = try_set_block(&bl, "bgcol", bggrad, col1, col2);
- if ( !done ) done = try_set_block(&bl, "bggradv", bggrad, col1, col2);
- if ( !done ) done = try_set_block(&bl, "bggradh", bggrad, col1, col2);
- if ( !done && bggrad != GRAD_NOBG ) {
- SCBlock *ibl = sc_block_append_inside(bl, NULL, NULL, NULL);
- set_ss_bg_block(ibl, bggrad, col1, col2);
+ if ( snprintf(tmp, 256, "%i,%i,%i,%i", v[0], v[1], v[2], v[3]) >= 256 ) {
+ fprintf(stderr, _("Spacing too long\n"));
+ } else {
+ stylesheet_set(p->stylesheet, style_name, key, tmp);
}
}
@@ -225,23 +298,13 @@ static void revert_sig(GtkButton *button, StylesheetEditor *widget)
}
-static GradientType id_to_gradtype(const gchar *id)
-{
- assert(id != NULL);
- if ( strcmp(id, "flat") == 0 ) return GRAD_NONE;
- if ( strcmp(id, "horiz") == 0 ) return GRAD_HORIZ;
- if ( strcmp(id, "vert") == 0 ) return GRAD_VERT;
- if ( strcmp(id, "none") == 0 ) return GRAD_NOBG;
- return GRAD_NONE;
-}
-
-
static void set_font(GtkFontButton *widget, StylesheetEditor *se,
const char *style_name)
{
const gchar *font;
font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
- set_ss(se->priv->p, style_name, "font", font);
+
+ stylesheet_set(se->priv->p->stylesheet, style_name, "font", font);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
@@ -254,7 +317,7 @@ static void set_col(GtkColorButton *widget, StylesheetEditor *se,
gchar *col;
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &rgba);
col = gdk_rgba_to_string(&rgba);
- set_ss(se->priv->p, style_name, col_name, col);
+ stylesheet_set(se->priv->p->stylesheet, style_name, "fgcol", col);
g_free(col);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
@@ -263,135 +326,125 @@ static void set_col(GtkColorButton *widget, StylesheetEditor *se,
static void narrative_font_sig(GtkFontButton *widget, StylesheetEditor *se)
{
- set_font(widget, se, "narrative");
+ set_font(widget, se, "$.narrative");
}
static void narrative_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
{
- set_col(widget, se, "narrative", "fgcol");
+ set_col(widget, se, "$.narrative", "fgcol");
}
-static void narrative_bgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void narrative_bg_sig(GtkColorButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->narrative_bgcol);
- update_bg(se->priv->p, "narrative", se->narrative_bggrad,
- se->narrative_bgcol, se->narrative_bgcol2);
-
+ update_bg(se->priv->p, "$.narrative",
+ se->narrative_style_bggrad,
+ se->narrative_style_bgcol,
+ se->narrative_style_bgcol2);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
-static void narrative_bgcol2_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void slide_size_sig(GtkSpinButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->narrative_bgcol2);
- update_bg(se->priv->p, "narrative", se->narrative_bggrad,
- se->narrative_bgcol, se->narrative_bgcol2);
-
- set_values_from_presentation(se);
- g_signal_emit_by_name(se, "changed");
-}
+ int w, h;
+ char tmp[256];
+ w = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(se->slide_size_w));
+ h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(se->slide_size_h));
-static void narrative_bggrad_sig(GtkComboBox *widget, StylesheetEditor *se)
-{
- const gchar *id;
- id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget));
- se->narrative_bggrad = id_to_gradtype(id);
- update_bg(se->priv->p, "narrative", se->narrative_bggrad,
- se->narrative_bgcol, se->narrative_bgcol2);
+ if ( snprintf(tmp, 256, "%ix%i", w, h) >= 256 ) {
+ fprintf(stderr, _("Slide size too long\n"));
+ } else {
+ stylesheet_set(se->priv->p->stylesheet, "$.slide", "size", tmp);
+ se->priv->p->slide_width = w;
+ se->priv->p->slide_height = h;
+ }
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
-static void slide_bgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void slide_bg_sig(GtkColorButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->slide_bgcol);
- update_bg(se->priv->p, "slide", se->slide_bggrad,
- se->slide_bgcol, se->slide_bgcol2);
-
+ update_bg(se->priv->p, "$.slide",
+ se->slide_style_bggrad,
+ se->slide_style_bgcol,
+ se->slide_style_bgcol2);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
-static void slide_bgcol2_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void frame_font_sig(GtkFontButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->slide_bgcol2);
- update_bg(se->priv->p, "slide", se->slide_bggrad,
- se->slide_bgcol, se->slide_bgcol2);
-
- set_values_from_presentation(se);
- g_signal_emit_by_name(se, "changed");
+ set_font(widget, se, "$.slide.frame");
}
-static void slide_bggrad_sig(GtkComboBox *widget, StylesheetEditor *se)
+static void frame_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
{
- const gchar *id;
-
- id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget));
- se->slide_bggrad = id_to_gradtype(id);
- update_bg(se->priv->p, "slide", se->slide_bggrad,
- se->slide_bgcol, se->slide_bgcol2);
-
- set_values_from_presentation(se);
- g_signal_emit_by_name(se, "changed");
+ set_col(widget, se, "$.slide.frame", "fgcol");
}
-static void frame_font_sig(GtkFontButton *widget, StylesheetEditor *se)
+static void frame_bg_sig(GtkColorButton *widget, StylesheetEditor *se)
{
- set_font(widget, se, "frame");
+ update_bg(se->priv->p, "$.slide.frame",
+ se->frame_style_bggrad,
+ se->frame_style_bgcol,
+ se->frame_style_bgcol2);
+ set_values_from_presentation(se);
+ g_signal_emit_by_name(se, "changed");
}
-static void frame_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void frame_padding_sig(GtkSpinButton *widget, StylesheetEditor *se)
{
- set_col(widget, se, "frame", "fgcol");
+ update_spacing(se->priv->p, "$.slide.frame", "pad",
+ se->frame_style_padding_l,
+ se->frame_style_padding_r,
+ se->frame_style_padding_t,
+ se->frame_style_padding_b);
+ set_values_from_presentation(se);
+ g_signal_emit_by_name(se, "changed");
}
-static void frame_bgcol_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void frame_paraspace_sig(GtkSpinButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->frame_bgcol);
- update_bg(se->priv->p, "frame", se->frame_bggrad,
- se->frame_bgcol, se->frame_bgcol2);
-
+ update_spacing(se->priv->p, "$.slide.frame", "paraspace",
+ se->frame_style_paraspace_l,
+ se->frame_style_paraspace_r,
+ se->frame_style_paraspace_t,
+ se->frame_style_paraspace_b);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
-static void frame_bgcol2_sig(GtkColorButton *widget, StylesheetEditor *se)
+static void narrative_padding_sig(GtkSpinButton *widget, StylesheetEditor *se)
{
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget),
- &se->frame_bgcol);
- update_bg(se->priv->p, "frame", se->frame_bggrad,
- se->frame_bgcol, se->frame_bgcol2);
-
+ update_spacing(se->priv->p, "$.narrative", "pad",
+ se->narrative_style_padding_l,
+ se->narrative_style_padding_r,
+ se->narrative_style_padding_t,
+ se->narrative_style_padding_b);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
-static void frame_bggrad_sig(GtkComboBox *widget, StylesheetEditor *se)
+static void narrative_paraspace_sig(GtkSpinButton *widget, StylesheetEditor *se)
{
- const gchar *id;
- id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget));
- se->frame_bggrad = id_to_gradtype(id);
- update_bg(se->priv->p, "frame", se->frame_bggrad,
- se->frame_bgcol, se->frame_bgcol2);
-
+ update_spacing(se->priv->p, "$.narrative", "paraspace",
+ se->narrative_style_paraspace_l,
+ se->narrative_style_paraspace_r,
+ se->narrative_style_paraspace_t,
+ se->narrative_style_paraspace_b);
set_values_from_presentation(se);
g_signal_emit_by_name(se, "changed");
}
@@ -423,21 +476,39 @@ void stylesheet_editor_class_init(StylesheetEditorClass *klass)
/* Narrative style */
SE_BIND_CHILD(narrative_style_font, narrative_font_sig);
SE_BIND_CHILD(narrative_style_fgcol, narrative_fgcol_sig);
- SE_BIND_CHILD(narrative_style_bgcol, narrative_bgcol_sig);
- SE_BIND_CHILD(narrative_style_bgcol2, narrative_bgcol2_sig);
- SE_BIND_CHILD(narrative_style_bggrad, narrative_bggrad_sig);
+ SE_BIND_CHILD(narrative_style_bgcol, narrative_bg_sig);
+ SE_BIND_CHILD(narrative_style_bgcol2, narrative_bg_sig);
+ SE_BIND_CHILD(narrative_style_bggrad, narrative_bg_sig);
+ SE_BIND_CHILD(narrative_style_paraspace_l, narrative_paraspace_sig);
+ SE_BIND_CHILD(narrative_style_paraspace_r, narrative_paraspace_sig);
+ SE_BIND_CHILD(narrative_style_paraspace_t, narrative_paraspace_sig);
+ SE_BIND_CHILD(narrative_style_paraspace_b, narrative_paraspace_sig);
+ SE_BIND_CHILD(narrative_style_padding_l, narrative_padding_sig);
+ SE_BIND_CHILD(narrative_style_padding_r, narrative_padding_sig);
+ SE_BIND_CHILD(narrative_style_padding_t, narrative_padding_sig);
+ SE_BIND_CHILD(narrative_style_padding_b, narrative_padding_sig);
/* Slide style */
- SE_BIND_CHILD(slide_style_bgcol, slide_bgcol_sig);
- SE_BIND_CHILD(slide_style_bgcol2, slide_bgcol2_sig);
- SE_BIND_CHILD(slide_style_bggrad, slide_bggrad_sig);
+ SE_BIND_CHILD(slide_size_w, slide_size_sig);
+ SE_BIND_CHILD(slide_size_h, slide_size_sig);
+ SE_BIND_CHILD(slide_style_bgcol, slide_bg_sig);
+ SE_BIND_CHILD(slide_style_bgcol2, slide_bg_sig);
+ SE_BIND_CHILD(slide_style_bggrad, slide_bg_sig);
/* Slide->frame style */
SE_BIND_CHILD(frame_style_font, frame_font_sig);
SE_BIND_CHILD(frame_style_fgcol, frame_fgcol_sig);
- SE_BIND_CHILD(frame_style_bgcol, frame_bgcol_sig);
- SE_BIND_CHILD(frame_style_bgcol2, frame_bgcol2_sig);
- SE_BIND_CHILD(frame_style_bggrad, frame_bggrad_sig);
+ SE_BIND_CHILD(frame_style_bgcol, frame_bg_sig);
+ SE_BIND_CHILD(frame_style_bgcol2, frame_bg_sig);
+ SE_BIND_CHILD(frame_style_bggrad, frame_bg_sig);
+ SE_BIND_CHILD(frame_style_paraspace_l, frame_paraspace_sig);
+ SE_BIND_CHILD(frame_style_paraspace_r, frame_paraspace_sig);
+ SE_BIND_CHILD(frame_style_paraspace_t, frame_paraspace_sig);
+ SE_BIND_CHILD(frame_style_paraspace_b, frame_paraspace_sig);
+ SE_BIND_CHILD(frame_style_padding_l, frame_padding_sig);
+ SE_BIND_CHILD(frame_style_padding_r, frame_padding_sig);
+ SE_BIND_CHILD(frame_style_padding_t, frame_padding_sig);
+ SE_BIND_CHILD(frame_style_padding_b, frame_padding_sig);
gtk_widget_class_bind_template_callback(widget_class, revert_sig);
@@ -446,103 +517,6 @@ void stylesheet_editor_class_init(StylesheetEditorClass *klass)
}
-static void set_from_interp_col(double *col, GtkWidget *w)
-{
- GdkRGBA rgba;
-
- rgba.red = col[0];
- rgba.green = col[1];
- rgba.blue = col[2];
- rgba.alpha = col[3];
- gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(w), &rgba);
-}
-
-
-static void set_from_interp_bggrad(SCInterpreter *scin, GtkWidget *w)
-{
- GradientType grad;
- const gchar *id;
-
- grad = sc_interp_get_bggrad(scin);
-
- switch ( grad ) {
- case GRAD_NONE : id = "flat"; break;
- case GRAD_HORIZ : id = "horiz"; break;
- case GRAD_VERT : id = "vert"; break;
- case GRAD_NOBG : id = "none"; break;
- default : id = NULL; break;
- }
-
- gtk_combo_box_set_active_id(GTK_COMBO_BOX(w), id);
-}
-
-
-static void set_from_interp_font(SCInterpreter *scin, GtkWidget *w)
-{
- char *fontname;
- PangoFontDescription *fontdesc;
-
- fontdesc = sc_interp_get_fontdesc(scin);
- fontname = pango_font_description_to_string(fontdesc);
- gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), fontname);
- g_free(fontname);
-}
-
-
-static void set_values_from_presentation(StylesheetEditor *se)
-{
- SCInterpreter *scin;
- PangoContext *pc;
-
- pc = gdk_pango_context_get();
-
- scin = sc_interp_new(pc, NULL, NULL, NULL);
- sc_interp_run_stylesheet(scin, se->priv->p->stylesheet); /* NULL stylesheet is OK */
-
- /* Narrative style */
- sc_interp_save(scin);
- sc_interp_run_style(scin, "narrative");
- set_from_interp_font(scin, se->narrative_style_font);
- set_from_interp_col(sc_interp_get_fgcol(scin), se->narrative_style_fgcol);
- set_from_interp_col(sc_interp_get_bgcol(scin), se->narrative_style_bgcol);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->narrative_style_bgcol),
- &se->narrative_bgcol);
- set_from_interp_col(sc_interp_get_bgcol2(scin), se->narrative_style_bgcol2);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->narrative_style_bgcol2),
- &se->narrative_bgcol2);
- set_from_interp_bggrad(scin, se->narrative_style_bggrad);
- sc_interp_restore(scin);
-
- /* Slide style */
- sc_interp_save(scin);
- sc_interp_run_style(scin, "slide");
- set_from_interp_col(sc_interp_get_bgcol(scin), se->slide_style_bgcol);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->slide_style_bgcol),
- &se->slide_bgcol);
- set_from_interp_col(sc_interp_get_bgcol2(scin), se->slide_style_bgcol2);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->slide_style_bgcol2),
- &se->slide_bgcol2);
- set_from_interp_bggrad(scin, se->slide_style_bggrad);
- sc_interp_restore(scin);
-
- /* Slide->Frame style */
- sc_interp_save(scin);
- sc_interp_run_style(scin, "frame");
- set_from_interp_font(scin, se->frame_style_font);
- set_from_interp_col(sc_interp_get_fgcol(scin), se->frame_style_fgcol);
- set_from_interp_col(sc_interp_get_bgcol(scin), se->frame_style_bgcol);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->frame_style_bgcol),
- &se->frame_bgcol);
- set_from_interp_col(sc_interp_get_bgcol2(scin), se->frame_style_bgcol2);
- gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(se->frame_style_bgcol2),
- &se->frame_bgcol2);
- set_from_interp_bggrad(scin, se->frame_style_bggrad);
- sc_interp_restore(scin);
-
- sc_interp_destroy(scin);
-}
-
-
StylesheetEditor *stylesheet_editor_new(struct presentation *p)
{
StylesheetEditor *se;
diff --git a/src/stylesheet_editor.h b/src/stylesheet_editor.h
index 480bd8a..22856da 100644
--- a/src/stylesheet_editor.h
+++ b/src/stylesheet_editor.h
@@ -63,6 +63,16 @@ struct _stylesheeteditor
GtkWidget *narrative_style_bgcol;
GtkWidget *narrative_style_bgcol2;
GtkWidget *narrative_style_bggrad;
+ GtkWidget *narrative_style_paraspace_l;
+ GtkWidget *narrative_style_paraspace_r;
+ GtkWidget *narrative_style_paraspace_t;
+ GtkWidget *narrative_style_paraspace_b;
+ GtkWidget *narrative_style_padding_l;
+ GtkWidget *narrative_style_padding_r;
+ GtkWidget *narrative_style_padding_t;
+ GtkWidget *narrative_style_padding_b;
+ GtkWidget *slide_size_w;
+ GtkWidget *slide_size_h;
GtkWidget *slide_style_bgcol;
GtkWidget *slide_style_bgcol2;
GtkWidget *slide_style_bggrad;
@@ -71,20 +81,17 @@ struct _stylesheeteditor
GtkWidget *frame_style_bgcol;
GtkWidget *frame_style_bgcol2;
GtkWidget *frame_style_bggrad;
+ GtkWidget *frame_style_paraspace_l;
+ GtkWidget *frame_style_paraspace_r;
+ GtkWidget *frame_style_paraspace_t;
+ GtkWidget *frame_style_paraspace_b;
+ GtkWidget *frame_style_padding_l;
+ GtkWidget *frame_style_padding_r;
+ GtkWidget *frame_style_padding_t;
+ GtkWidget *frame_style_padding_b;
StylesheetEditorPrivate *priv;
-
- GdkRGBA narrative_bgcol;
- GdkRGBA narrative_bgcol2;
- GradientType narrative_bggrad;
- GdkRGBA slide_bgcol;
- GdkRGBA slide_bgcol2;
- GradientType slide_bggrad;
- GdkRGBA frame_bgcol;
- GdkRGBA frame_bgcol2;
- GradientType frame_bggrad;
};
-
struct _stylesheeteditorclass
{
GtkDialogClass parent_class;
diff --git a/src/utils.c b/src/utils.c
index 9033466..277b3f1 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -54,90 +54,30 @@ int safe_strcmp(const char *a, const char *b)
}
-static char *fgets_long(FILE *fh, size_t *lp)
+int parse_double(const char *a, float v[2])
{
- char *line;
- size_t la;
- size_t l = 0;
-
- la = 1024;
- line = malloc(la);
- if ( line == NULL ) return NULL;
-
- do {
-
- int r;
-
- r = fgetc(fh);
- if ( r == EOF ) {
- if ( l == 0 ) {
- free(line);
- *lp = 0;
- return NULL;
- } else {
- line[l++] = '\0';
- *lp = l;
- return line;
- }
- }
-
- line[l++] = r;
-
- if ( r == '\n' ) {
- line[l++] = '\0';
- *lp = l;
- return line;
- }
-
- if ( l == la ) {
+ int nn;
- char *ln;
-
- la += 1024;
- ln = realloc(line, la);
- if ( ln == NULL ) {
- free(line);
- *lp = 0;
- return NULL;
- }
-
- line = ln;
-
- }
+ nn = sscanf(a, "%fx%f", &v[0], &v[1]);
+ if ( nn != 2 ) {
+ fprintf(stderr, _("Invalid size '%s'\n"), a);
+ return 1;
+ }
- } while ( 1 );
+ return 0;
}
-char *load_everything(const char *filename)
+int parse_tuple(const char *a, float v[4])
{
- FILE *fh;
- size_t el = 1;
- char *everything = strdup("");
-
- fh = fopen(filename, "r");
- if ( fh == NULL ) return NULL;
-
- while ( !feof(fh) ) {
-
- size_t len = 0;
- char *line = fgets_long(fh, &len);
-
- if ( line != NULL ) {
-
- everything = realloc(everything, el+len);
- if ( everything == NULL ) {
- fprintf(stderr, _("Failed to allocate memory\n"));
- return NULL;
- }
- el += len;
-
- strcat(everything, line);
- }
+ int nn;
+ nn = sscanf(a, "%f,%f,%f,%f", &v[0], &v[1], &v[2], &v[3]);
+ if ( nn != 4 ) {
+ fprintf(stderr, _("Invalid tuple '%s'\n"), a);
+ return 1;
}
- fclose(fh);
-
- return everything;
+ return 0;
}
+
diff --git a/src/utils.h b/src/utils.h
index bfc04c2..fc843c3 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -30,7 +30,8 @@
extern void chomp(char *s);
extern int safe_strcmp(const char *a, const char *b);
-extern char *load_everything(const char *filename);
+extern int parse_double(const char *a, float v[2]);
+extern int parse_tuple(const char *a, float v[4]);
#include <libintl.h>
#define _(x) gettext(x)
diff --git a/tests/json_test.c b/tests/json_test.c
new file mode 100644
index 0000000..96323cb
--- /dev/null
+++ b/tests/json_test.c
@@ -0,0 +1,102 @@
+/*
+ * storycode_test.c
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * 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
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <json-glib/json-glib.h>
+
+#include "../src/sc_parse.h"
+
+typedef struct {
+ JsonNode *root;
+} Stylesheet;
+
+
+Stylesheet *stylesheet_load(const char *filename)
+{
+ JsonParser *parser;
+ gboolean r;
+ GError *err = NULL;
+ Stylesheet *ss;
+
+ ss = calloc(1, sizeof(Stylesheet));
+ if ( ss == NULL ) return NULL;
+
+ parser = json_parser_new();
+
+ r = json_parser_load_from_file(parser, filename, &err);
+ if ( r == FALSE ) {
+ fprintf(stderr, "Failed to load style sheet: '%s'\n", err->message);
+ return NULL;
+ }
+
+ ss->root = json_parser_steal_root(parser);
+ g_object_unref(parser);
+
+ return ss;
+}
+
+
+char *stylesheet_lookup(Stylesheet *ss, const char *path)
+{
+ JsonNode *node;
+ JsonArray *array;
+ GError *err = NULL;
+ char *ret;
+ const gchar *v;
+
+ node = json_path_query(path, ss->root, &err);
+ array = json_node_get_array(node);
+
+ v = json_array_get_string_element(array, 0);
+ if ( v == NULL ) return NULL;
+
+ ret = strdup(v);
+ json_node_unref(node);
+ return ret;
+}
+
+
+int main(int argc, char *argv[])
+{
+ SCBlock *bl;
+ Stylesheet *ss;
+
+ ss = stylesheet_load("test.ss");
+ printf("Frame background: '%s'\n", stylesheet_lookup(ss, "$.slide.frame.bgcol1"));
+
+ bl = sc_parse("\\wibble{}\\f{wibble \\bg[muhu]{wobble\nwibble\nwabble}}\\frib[\\f] f");
+ if ( bl == NULL ) {
+ printf("Failed to parse SC\n");
+ return 1;
+ }
+
+ show_sc_blocks(bl);
+
+ return 0;
+}
diff --git a/tests/meson.build b/tests/meson.build
index 427faae..dee9a47 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,15 +1,20 @@
basic_rendering = ['../src/render.c', '../src/frame.c',
'../src/sc_parse.c', '../src/imagestore.c',
- '../src/sc_interp.c', '../src/utils.c']
+ '../src/sc_interp.c', '../src/utils.c',
+ '../src/stylesheet.c']
e = executable('storycode_test', 'storycode_test.c', '../src/sc_parse.c',
dependencies : [gtkdep])
test('Simple StoryCode parsing', e)
e = executable('render_test', 'render_test.c', basic_rendering,
- dependencies : [gtkdep, mdep])
+ dependencies : [gtkdep, mdep, jsondep])
test('Simple rendering', e)
e = executable('render_test_sc1', 'render_test_sc1.c', basic_rendering,
- dependencies : [gtkdep, mdep])
+ dependencies : [gtkdep, mdep, jsondep])
test('Simple StoryCode rendering', e)
+
+e = executable('json_test', 'json_test.c', '../src/sc_parse.c',
+ dependencies : [mdep, jsondep])
+test('JSON parsing', e)