[geany/geany-plugins] c620c7: markdown: Re-write preferences and templates

Matthew Brush git-noreply at xxxxx
Sun Aug 26 09:16:26 UTC 2012


Branch:      refs/heads/master
Author:      Matthew Brush <matt at geany.org>
Committer:   Matthew Brush <matt at geany.org>
Date:        Mon, 16 Jul 2012 07:31:08
Commit:      c620c79f3442581a282e00518a8544b14fb7e235
             https://github.com/geany/geany-plugins/commit/c620c79f3442581a282e00518a8544b14fb7e235

Log Message:
-----------
markdown: Re-write preferences and templates

Massive changes, including:
* Uses a single template specified in the conf file or by GUI.
* Allows setting the font, code font, their sizes and the FG/BG colors
  for the WebKit view.
* Make a GObject MarkdownConfig to manage the config and prefs GUI.
* Delete all old templates stuff.


Modified Paths:
--------------
    build/markdown.m4
    markdown/Makefile.am
    markdown/README
    markdown/docs/Makefile.am
    markdown/docs/README.md
    markdown/src/Makefile.am
    markdown/src/conf.c
    markdown/src/conf.h
    markdown/src/plugin.c
    markdown/src/tmpl.c
    markdown/src/tmpl.h
    markdown/src/tmplmgr.c
    markdown/src/tmplmgr.h
    markdown/src/viewer.c
    markdown/src/viewer.h
    markdown/templates/Alternate/Kreon.ttf
    markdown/templates/Alternate/LICENSE.kreon
    markdown/templates/Alternate/LICENSE.pointfree
    markdown/templates/Alternate/Makefile.am
    markdown/templates/Alternate/Pointfree.ttf
    markdown/templates/Alternate/alternate.css
    markdown/templates/Alternate/background.png
    markdown/templates/Alternate/index.html
    markdown/templates/Default/Makefile.am
    markdown/templates/Default/index.html
    markdown/templates/Makefile.am

Modified: build/markdown.m4
4 files changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -16,9 +16,5 @@ AC_DEFUN([GP_CHECK_MARKDOWN],
         markdown/Makefile
         markdown/discount/Makefile
         markdown/src/Makefile
-        markdown/templates/Makefile
-        markdown/templates/Default/Makefile
-        markdown/templates/Alternate/Makefile
-        markdown/docs/Makefile
     ])
 ])


Modified: markdown/Makefile.am
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,4 +1,4 @@
 include $(top_srcdir)/build/vars.auxfiles.mk
 
-SUBDIRS = discount src templates docs
+SUBDIRS = discount src
 plugin = markdown


Modified: markdown/README
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-See the ``docs/README.md`` file for more information.
+


Modified: markdown/docs/Makefile.am
2 files changed, 0 insertions(+), 2 deletions(-)
===================================================================
@@ -1,2 +0,0 @@
-plugindocdir = $(docdir)/markdown
-plugindoc_DATA = README.md


Modified: markdown/docs/README.md
60 files changed, 0 insertions(+), 60 deletions(-)
===================================================================
@@ -1,60 +0,0 @@
-Geany Markdown Plugin
-=====================
-
-The Markdown plugin shows a live preview of Markdown documents in a WebKit
-view. The Markdown is converted to HTML and then replaced into a
-user-configurable HTML template, the result of which is loaded directly
-into the WebKit view.
-
-There are a few settings which can be chosen from the Tools menu and they
-will persist between instances of Geany.
-
-Template
---------
-
-This option is accessible from the `Tools->Markdown->Template` menu. Templates
-are read from the system-wide configuration directory and then from the user
-configuration directory. Templates are just special directories containing
-an `index.html` file which defines the template to use for the live preview.
-
-For example, the Default template's `index.html` file consists of the
-following contents:
-
-    <html>
-      <body>
-        <!-- @markdown_document@ -->
-      </body>
-    </html>
-
-The special HTML comment `<!-- @markdown_document@ -->` is replaced
-with the Markdown contents of the editor buffer after the contents have been
-converted to HTML. You can put whatever you want in the HTML template, for
-example a header and/or footer or some CSS styling.
-
-### Template Paths
-
-User templates are read from Geany's configuration directory (usually
-`$HOME/.config/geany/plugins/markdown/templates`. System-wide templates,
-including the default `Default` and `Alternate` templates are read from
-`$PREFIX/share/geany-plugins/markdown/templates`.
-
-### Custom Templates
-
-To add your own template, just copy one of the existing ones from the
-system-wide templates directory into your user configuration directory. The
-name of the template is taken from the name of the directory holding the
-`index.html`. For example if you wanted the template to be named `FooBar`
-then the `index.html` file path would be
-`$HOME/.config/geany/plugins/markdown/templates/FooBar/index.html`.
-
-Position
---------
-
-This option specifies which notebook the Markdown preview tab will appear in.
-The two choices are `Sidebar` or `Message Window` for Geany's sidebar and
-message window notebooks, respectively.
-
-Acknowledgements
-----------------
-This product includes software developed by
-David Loren Parsons <http://www.pell.portland.or.us/~orc>


Modified: markdown/src/Makefile.am
4 files changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -8,15 +8,11 @@ markdown_la_SOURCES = \
 	conf.c \
 	md.c \
 	plugin.c \
-	tmpl.c \
-	tmplmgr.c \
 	viewer.c
 
 noinst_HEADERS = \
 	conf.h \
 	md.h \
-	tmpl.h \
-	tmplmgr.h \
 	viewer.h
 
 markdown_la_CFLAGS = \


Modified: markdown/src/conf.c
701 files changed, 604 insertions(+), 97 deletions(-)
===================================================================
@@ -1,177 +1,684 @@
 /*
- * conf.c - Part of the Geany Markdown plugin
- *
+ * markdownconfig.c
+ * 
  * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
+ * 
  * 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 2 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, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
+ * 
+ * 
  */
 
-#include <glib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <geanyplugin.h>
 #include "conf.h"
-#include "tmpl.h"
-#include "tmplmgr.h"
 
-#define MARKDOWN_CONF_DEFAULT "[general]\n" \
-                              "template=Default\n" \
-                              "readme_shown=false\n" \
-                              "position=0\n"
+#define FONT_NAME_MAX  256
+#define COLOR_CODE_MAX 8
+#define DEFAULT_CONF \
+  "[general]\n" \
+  "template=\n" \
+  "\n" \
+  "[view]\n" \
+  "position=0\n" \
+  "font_name=Serif\n" \
+  "code_font_name=Mono\n" \
+  "font_point_size=12\n" \
+  "code_font_point_size=12\n" \
+  "bg_color=#fff\n" \
+  "fg_color=#000\n"
 
-struct MarkdownConf {
-  gchar *filename;
-  GKeyFile *keyfile;
+#define MARKDOWN_HTML_TEMPLATE \
+  "<html>\n" \
+  "  <head>\n" \
+  "    <style type=\"text/css\">\n" \
+  "      body {\n" \
+  "        font-family: @@font_name@@;\n" \
+  "        font-size: @@font_point_size@@pt;\n" \
+  "        background-color: @@bg_color@@;\n" \
+  "        color: @@fg_color@@;\n" \
+  "      }\n" \
+  "      code {\n" \
+  "        font-family: @@code_font_name@@;\n" \
+  "        font-size: @@code_font_point_size@@pt;\n" \
+  "      }\n" \
+  "    </style>\n" \
+  "  </head>\n" \
+  "  <body>\n" \
+  "    @@markdown@@\n" \
+  "  </body>\n" \
+  "</html>\n"
+
+enum
+{
+  PROP_0,
+  PROP_TEMPLATE_FILE,
+  PROP_FONT_NAME,
+  PROP_CODE_FONT_NAME,
+  PROP_FONT_POINT_SIZE,
+  PROP_CODE_FONT_POINT_SIZE,
+  PROP_BG_COLOR,
+  PROP_FG_COLOR,
+  PROP_VIEW_POS,
+  PROP_LAST
 };
 
-static void markdown_conf_init_defaults(MarkdownConf *conf)
+static GParamSpec *md_props[PROP_LAST] = { NULL };
+
+struct _MarkdownConfigPrivate
 {
-  if (!g_key_file_has_group(conf->keyfile, "general") ||
-      !g_key_file_has_key(conf->keyfile, "general", "template", NULL))
-  {
-    g_key_file_set_string(conf->keyfile, "general", "template", "Default");
-  }
+  gchar filename[PATH_MAX];
+  GKeyFile *kf;
+  guint handle;
+  gboolean initialized;
+  gchar *tmpl_text;
+  gsize tmpl_text_len;
+  struct {
+    GtkWidget *table;
+    GtkWidget *pos_sb_radio;
+    GtkWidget *pos_mw_radio;
+    GtkWidget *font_button;
+    GtkWidget *code_font_button;
+    GtkWidget *bg_color_button;
+    GtkWidget *fg_color_button;
+    GtkWidget *tmpl_file_button;
+  } widgets;
+};
+
+static void markdown_config_finalize(GObject *object);
+
+G_DEFINE_TYPE(MarkdownConfig, markdown_config, G_TYPE_OBJECT)
+
+static gboolean on_idle_timeout(MarkdownConfig *conf)
+{
+  markdown_config_save(conf);
+  conf->priv->handle = 0;
+  return FALSE;
 }
 
-static void markdown_conf_init_file(MarkdownConf *conf)
+static void 
+init_conf_file(MarkdownConfig *conf)
 {
-  gchar *dirname = g_path_get_dirname(conf->filename);
-  if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
-    g_mkdir_with_parents(dirname, 0755);
+  GError *error = NULL;
+  gchar *def_tmpl, *dirn;
+  
+  dirn = g_path_get_dirname(conf->priv->filename);
+  if (!g_file_test(dirn, G_FILE_TEST_IS_DIR)) {
+    g_mkdir_with_parents(dirn, 0755);
   }
-  if (!g_file_test(conf->filename, G_FILE_TEST_EXISTS)) {
-    g_file_set_contents(conf->filename, MARKDOWN_CONF_DEFAULT, -1, NULL);
+  
+  if (!g_file_test(conf->priv->filename, G_FILE_TEST_EXISTS)) {
+    if (!g_file_set_contents(conf->priv->filename, DEFAULT_CONF, -1, &error)) {
+      g_warning("Unable to write default configuration file: %s", error->message);
+      g_error_free(error); error = NULL;
+    }
   }
-  g_free(dirname);
-}
 
-MarkdownConf *markdown_conf_new(const gchar *conf_filename)
-{
-  MarkdownConf *conf = g_slice_new0(MarkdownConf);
-  if (conf) {
-    GError *error = NULL;
-    conf->filename = g_strdup(conf_filename);
-    markdown_conf_init_file(conf);
-    conf->keyfile = g_key_file_new();
-    if (!g_key_file_load_from_file(conf->keyfile, conf->filename,
-        G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
-    {
-      g_warning("Error loading configuration file '%s': %s", conf->filename,
-        error->message);
+  def_tmpl = g_build_filename(dirn, "template.html", NULL);
+
+  if (!g_file_test(def_tmpl, G_FILE_TEST_EXISTS)) {
+    if (!g_file_set_contents(def_tmpl, MARKDOWN_HTML_TEMPLATE, -1, &error)) {
+      g_warning("Unable to write default template file: %s", error->message);
       g_error_free(error); error = NULL;
     }
-    markdown_conf_init_defaults(conf);
   }
-  return conf;
+  
+  g_free(dirn);
+  g_free(def_tmpl);
 }
 
-void markdown_conf_free(MarkdownConf *conf)
+static void
+markdown_config_load_template_text(MarkdownConfig *conf)
 {
-  g_return_if_fail(conf);
-  g_free(conf->filename);
-  g_key_file_free(conf->keyfile);
+  GError *error = NULL;
+  gchar *tmpl_file = NULL;
+  
+  g_object_get(conf, "template-file", &tmpl_file, NULL);
+  
+  g_free(conf->priv->tmpl_text);
+  conf->priv->tmpl_text = NULL;
+  conf->priv->tmpl_text_len = 0;
+  
+  if (!g_file_get_contents(tmpl_file, &(conf->priv->tmpl_text), 
+      &(conf->priv->tmpl_text_len), &error))
+  {
+    g_warning("Error reading template file: %s", error->message);
+    g_error_free(error); error = NULL;
+  }
 }
 
-void markdown_conf_save(MarkdownConf *conf)
+static void
+markdown_config_set_property(GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
-  g_return_if_fail(conf);
+  gboolean save_later = FALSE;
+  MarkdownConfig *conf = MARKDOWN_CONFIG(obj);
+  
+  /* FIXME: Prevent writing to keyfile until it's ready */
+  if (!conf->priv->initialized)
+    return;
+  
+  switch (prop_id) {
+    case PROP_TEMPLATE_FILE:
+      g_key_file_set_string(conf->priv->kf, "general", "template",
+        g_value_get_string(value));
+      /*markdown_config_load_template_text(conf);*/
+      save_later = TRUE;
+      break;
+    case PROP_FONT_NAME:
+      g_key_file_set_string(conf->priv->kf, "view", "font_name",
+        g_value_get_string(value));
+      save_later = TRUE;
+      break;
+    case PROP_CODE_FONT_NAME:
+      g_key_file_set_string(conf->priv->kf, "view", "code_font_name",
+        g_value_get_string(value));
+      save_later = TRUE;
+      break;
+    case PROP_FONT_POINT_SIZE:
+      g_key_file_set_integer(conf->priv->kf, "view", "font_point_size",
+        (gint) g_value_get_uint(value));
+      save_later = TRUE;
+      break;
+    case PROP_CODE_FONT_POINT_SIZE:
+      g_key_file_set_integer(conf->priv->kf, "view", "code_font_point_size",
+        (gint) g_value_get_uint(value));
+      save_later = TRUE;
+      break;
+    case PROP_BG_COLOR:
+      g_key_file_set_string(conf->priv->kf, "view", "bg_color",
+        g_value_get_string(value));
+      save_later = TRUE;
+      break;
+    case PROP_FG_COLOR:
+      g_key_file_set_string(conf->priv->kf, "view", "fg_color",
+        g_value_get_string(value));
+      save_later = TRUE;
+      break;
+    case PROP_VIEW_POS:
+      g_key_file_set_integer(conf->priv->kf, "view", "position", 
+        (gint) g_value_get_uint(value));
+      save_later = TRUE;
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
+      break;
+  }
+  
+  if (save_later && conf->priv->handle == 0) {
+    conf->priv->handle = g_idle_add((GSourceFunc) on_idle_timeout, conf);
+  }
+}
 
+static gchar *
+markdown_config_get_string_key(MarkdownConfig *conf, const gchar *group,
+  const gchar *key, const gchar *default_value)
+{
+  gchar *out_str;
   GError *error = NULL;
-  gchar *contents = NULL;
-  gsize len = 0;
-
-  contents = g_key_file_to_data(conf->keyfile, &len, &error);
-
+  
+  out_str = g_key_file_get_string(conf->priv->kf, group, key, &error);
   if (error) {
-    g_warning("Error getting config file data: %s", error->message);
+    g_debug("Config read failed: %s", error->message);
     g_error_free(error); error = NULL;
-    return;
+    out_str = g_strdup(default_value);
   }
+  
+  return out_str; 
+}
 
-  if (!g_file_set_contents(conf->filename, contents, len, &error)) {
-    g_warning("Error saving config file: %s", error->message);
+static guint
+markdown_config_get_uint_key(MarkdownConfig *conf, const gchar *group,
+  const gchar *key, uint default_value)
+{
+  guint out_uint;
+  GError *error = NULL;
+  
+  out_uint = (guint) g_key_file_get_integer(conf->priv->kf, group, key, &error);
+  if (error) {
+    g_debug("Config read failed: %s", error->message);
     g_error_free(error); error = NULL;
+    out_uint = 12;
   }
+  
+  return out_uint; 
+}
 
-  g_free(contents);
+static void
+markdown_config_get_property(GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  MarkdownConfig *conf = MARKDOWN_CONFIG(obj);
+  
+  switch (prop_id) {
+    case PROP_TEMPLATE_FILE:
+    {
+      gchar *tmpl_file;
+      tmpl_file = markdown_config_get_string_key(conf, "general", "template", "");
+      /* If empty, use default template.html file. */
+      if (!tmpl_file || !tmpl_file[0]) {
+        gchar *dn;
+        g_free(tmpl_file);
+        dn = g_path_get_dirname(conf->priv->filename);
+        tmpl_file = g_build_filename(dn, "template.html", NULL);
+        g_free(dn);
+      }
+      g_value_set_string(value, tmpl_file);
+      g_free(tmpl_file);
+      break;
+    }
+    case PROP_FONT_NAME:
+    {
+      gchar *font_name;
+      font_name = markdown_config_get_string_key(conf, "view", "font_name", "Serif");
+      g_value_set_string(value, font_name);
+      g_free(font_name);
+      break;
+    }
+    case PROP_CODE_FONT_NAME:
+    {
+      gchar *font_name;
+      font_name = markdown_config_get_string_key(conf, "view", "code_font_name", "Monospace");
+      g_value_set_string(value, font_name);
+      g_free(font_name);
+      break;
+    }
+    case PROP_FONT_POINT_SIZE:
+    {
+      guint font_size;
+      font_size = markdown_config_get_uint_key(conf, "view", "font_point_size", 12);
+      g_value_set_uint(value, font_size);
+      break;
+    }
+    case PROP_CODE_FONT_POINT_SIZE:
+    {
+      guint font_size;
+      font_size = markdown_config_get_uint_key(conf, "view", "code_font_point_size", 12);
+      g_value_set_uint(value, font_size);
+      break;
+    }
+    case PROP_BG_COLOR:
+    {
+      gchar *bg_color;
+      bg_color = markdown_config_get_string_key(conf, "view", "bg_color", "#ffffff");
+      g_value_set_string(value, bg_color);
+      g_free(bg_color);
+      break;
+    }
+    case PROP_FG_COLOR:
+    {
+      gchar *fg_color;
+      fg_color = markdown_config_get_string_key(conf, "view", "fg_color", "#000000");
+      g_value_set_string(value, fg_color);
+      g_free(fg_color);
+      break;
+    }
+    case PROP_VIEW_POS:
+    {
+      guint view_pos;
+      view_pos = markdown_config_get_uint_key(conf, "view", "position", 0);
+      g_value_set_uint(value, view_pos);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
+      break;
+  }
 }
 
-gchar *markdown_conf_get_template_name(MarkdownConf *conf)
+static void
+markdown_config_class_init(MarkdownConfigClass *klass)
 {
-  gchar *res;
-  GError *error = NULL;
+  GObjectClass *g_object_class;
 
-  g_return_val_if_fail(conf, NULL);
+  g_object_class = G_OBJECT_CLASS(klass);
+  g_object_class->finalize = markdown_config_finalize;
+  g_object_class->set_property = markdown_config_set_property;
+  g_object_class->get_property = markdown_config_get_property;
+  g_type_class_add_private((gpointer)klass, sizeof(MarkdownConfigPrivate));
 
-  res = g_key_file_get_string(conf->keyfile, "general", "template", &error);
-  if (error) {
-    g_warning("Unable to get template from config file: %s", error->message);
-    g_error_free(error); error = NULL;
+  md_props[PROP_TEMPLATE_FILE] = g_param_spec_string("template-file", "TemplateFile",
+    "HTML template file for preview", "", G_PARAM_READWRITE);
+  md_props[PROP_FONT_NAME] = g_param_spec_string("font-name", "FontName",
+    "Font family name", "Serif", G_PARAM_READWRITE);
+  md_props[PROP_CODE_FONT_NAME] = g_param_spec_string("code-font-name", "CodeFontName",
+    "Font family for code blocks", "Monospace", G_PARAM_READWRITE);
+  md_props[PROP_FONT_POINT_SIZE] = g_param_spec_uint("font-point-size", "FontPointSize",
+    "Size in points of the font", 2, 100, 12, G_PARAM_READWRITE);
+  md_props[PROP_CODE_FONT_POINT_SIZE] = g_param_spec_uint("code-font-point-size",
+    "CodeFontPointSize", "Size in points of the font for code blocks", 2, 100, 12,
+    G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+  md_props[PROP_BG_COLOR] = g_param_spec_string("bg-color", "BackgroundColor",
+    "Background colour of the page", "#ffffff", G_PARAM_READWRITE);
+  md_props[PROP_FG_COLOR] = g_param_spec_string("fg-color", "ForegroundColor",
+    "Foreground colour of the page", "#000000", G_PARAM_READWRITE);
+  md_props[PROP_VIEW_POS] = g_param_spec_uint("view-pos", "ViewPosition",
+    "Notebook where the view will be positioned", 0, 
+    MARKDOWN_CONFIG_VIEW_POS_MAX-1, (guint) MARKDOWN_CONFIG_VIEW_POS_SIDEBAR,
+    G_PARAM_READWRITE);
+  
+  g_object_class_install_properties(g_object_class, PROP_LAST, md_props);
+}
+
+
+static void
+markdown_config_finalize(GObject *object)
+{
+  MarkdownConfig *self;
+
+  g_return_if_fail(MARKDOWN_IS_CONFIG(object));
+
+  self = MARKDOWN_CONFIG(object);
+  
+  if (self->priv->handle != 0) {
+    g_source_remove(self->priv->handle);
+    markdown_config_save(self);
   }
 
-  return res;
+  g_key_file_free(self->priv->kf);
+
+  G_OBJECT_CLASS(markdown_config_parent_class)->finalize (object);
 }
 
-void markdown_conf_set_template_name(MarkdownConf *conf, const gchar *tmpl_name)
+
+static void
+markdown_config_init(MarkdownConfig *self)
 {
-  g_return_if_fail(conf);
-  if (!tmpl_name)
-    g_key_file_set_string(conf->keyfile, "general", "template", "Default");
-  else
-    g_key_file_set_string(conf->keyfile, "general", "template", tmpl_name);
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, MARKDOWN_TYPE_CONFIG, MarkdownConfigPrivate);
 }
 
-gboolean markdown_conf_get_readme_shown(MarkdownConf *conf)
+
+MarkdownConfig *
+markdown_config_new(const gchar *filename)
 {
-  gboolean res;
+  MarkdownConfig *conf = g_object_new(MARKDOWN_TYPE_CONFIG, NULL);
   GError *error = NULL;
+  
+  g_return_val_if_fail(filename, conf);
+  
+  strncpy(conf->priv->filename, filename, PATH_MAX);
+  init_conf_file(conf);
+  conf->priv->kf = g_key_file_new();
+  if (!g_key_file_load_from_file(conf->priv->kf, conf->priv->filename,
+    G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
+  {
+    g_warning("Error loading configuration file: %s", error->message);
+    g_error_free(error); error = NULL;
+  }
+  
+  conf->priv->initialized = TRUE;
 
-  g_return_val_if_fail(conf, FALSE);
+  return conf;
+}
 
-  res = g_key_file_get_boolean(conf->keyfile, "general", "readme_shown", &error);
+gboolean
+markdown_config_save(MarkdownConfig *conf)
+{
+  gchar *contents;
+  gsize len;
+  gboolean success = FALSE;
+  GError *error = NULL;
+  
+  contents = g_key_file_to_data(conf->priv->kf, &len, &error);
+  
+  g_debug("Saving: %s\n%s", conf->priv->filename, contents);
+  
   if (error) {
-    g_warning("Unable to get whether the README.md file has been shown: %s",
-      error->message);
+    g_warning("Error getting config data as string: %s", error->message);
     g_error_free(error); error = NULL;
+    return success;
   }
+  
+  success = g_file_set_contents(conf->priv->filename, contents, len, &error);
+  g_free(contents);
 
-  return res;
+  if (!success) {
+    g_warning("Error writing config data to disk: %s", error->message);
+    g_error_free(error); error = NULL;
+  }
+  
+  return success;
 }
 
-void markdown_conf_set_readme_shown(MarkdownConf *conf, gboolean shown)
+gchar *
+color_button_get_color(GtkColorButton *color_button)
 {
-  g_return_if_fail(conf);
-  g_key_file_set_boolean(conf->keyfile, "general", "readme_shown", shown);
+  GdkColor color;
+  guint r, g, b;
+  gchar *color_str;
+
+  gtk_color_button_get_color(color_button, &color);
+
+  r = color.red / 256;
+  g = color.green / 256;
+  b = color.blue / 256;
+  color_str = g_strdup_printf("#%02x%02x%02x", r, g, b);
+  
+  return color_str;
 }
 
-MarkdownViewPosition markdown_conf_get_view_position(MarkdownConf *conf)
+static gboolean
+get_font_info(const gchar *font_desc, gchar **font_name, guint *font_size)
 {
-  gint conf_val = (gint) MARKDOWN_VIEW_POS_SIDEBAR;
-  GError *error = NULL;
+  gboolean success = FALSE;
+  PangoFontDescription *pfd;
+  
+  pfd = pango_font_description_from_string(font_desc);
+  if (pfd) {
+    *font_name = g_strdup(pango_font_description_get_family(pfd));
+    *font_size = (guint) (pango_font_description_get_size(pfd) / PANGO_SCALE);
+    success = TRUE;
+    pango_font_description_free(pfd);
+  }
+  
+  return success;
+}
 
-  g_return_val_if_fail(conf, MARKDOWN_VIEW_POS_SIDEBAR);
+static void
+on_dialog_response(MarkdownConfig *conf, gint response_id, GtkDialog *dialog)
+{
+  if (response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK) {
+    GtkWidget *wid = conf->priv->widgets.pos_sb_radio;
+    gboolean pos_sidebar = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
+    gchar *bg_color, *fg_color;
+    gchar *tmpl_file = NULL, *fnt = NULL, *code_fnt = NULL;
+    guint fnt_size = 0, code_fnt_size = 0;
+    const gchar *font_desc;
+    MarkdownConfigViewPos view_pos;
+    
+    view_pos = pos_sidebar ? MARKDOWN_CONFIG_VIEW_POS_SIDEBAR : MARKDOWN_CONFIG_VIEW_POS_MSGWIN;
+    
+    bg_color = color_button_get_color(GTK_COLOR_BUTTON(conf->priv->widgets.bg_color_button));
+    fg_color = color_button_get_color(GTK_COLOR_BUTTON(conf->priv->widgets.fg_color_button));
 
-  conf_val = g_key_file_get_integer(conf->keyfile, "general", "position", &error);
-  if (error) {
-    g_warning("Unable to get the WebKit view position: %s", error->message);
-    g_error_free(error); error = NULL;
+    font_desc = gtk_font_button_get_font_name(GTK_FONT_BUTTON(conf->priv->widgets.font_button));
+    get_font_info(font_desc, &fnt, &fnt_size);
+    
+    font_desc = gtk_font_button_get_font_name(GTK_FONT_BUTTON(conf->priv->widgets.code_font_button));
+    get_font_info(font_desc, &code_fnt, &code_fnt_size);
+    
+    tmpl_file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(conf->priv->widgets.tmpl_file_button));
+    
+    g_object_set(conf, 
+                 "font-name", fnt,
+                 "font-point-size", fnt_size,
+                 "code-font-name", code_fnt,
+                 "code-font-point-size", code_fnt_size,
+                 "view-pos", view_pos,
+                 "bg-color", bg_color,
+                 "fg-color", fg_color,
+                 "template-file", tmpl_file,
+                 NULL);
+    
+    g_free(fnt);
+    g_free(code_fnt);
+    g_free(bg_color);
+    g_free(fg_color);
+    g_free(tmpl_file);
   }
+}
 
-  return (MarkdownViewPosition) conf_val;
+GtkWidget *markdown_config_gui(MarkdownConfig *conf, GtkDialog *dialog)
+{
+  GSList *grp = NULL;
+  GtkWidget *table, *label, *hbox, *wid;
+  gchar *tmpl_file=NULL, *fnt=NULL, *code_fnt=NULL, *bg=NULL, *fg=NULL;
+  guint view_pos=0, fnt_sz=0, code_fnt_sz=0;
+  
+  g_object_get(conf,
+               "view-pos", &view_pos,
+               "font-name", &fnt,
+               "code-font-name", &code_fnt,
+               "font-point-size", &fnt_sz,
+               "code-font-point-size", &code_fnt_sz,
+               "bg-color", &bg,
+               "fg-color", &fg,
+               "template-file", &tmpl_file,
+               NULL);
+  
+  table = gtk_table_new(6, 2, FALSE);
+  gtk_table_set_col_spacings(GTK_TABLE(table), 6);
+  gtk_table_set_row_spacings(GTK_TABLE(table), 6);
+  conf->priv->widgets.table = table;
+  
+  { /* POSITION OF VIEW */
+    label = gtk_label_new(_("Position:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+    
+    hbox = gtk_hbox_new(FALSE, 6);
+    
+    wid = gtk_radio_button_new_with_label(grp, _("Sidebar"));
+    grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(wid));
+    gtk_box_pack_start(GTK_BOX(hbox), wid, FALSE, TRUE, 0);
+    conf->priv->widgets.pos_sb_radio = wid;
+    if (((MarkdownConfigViewPos) view_pos) == MARKDOWN_CONFIG_VIEW_POS_SIDEBAR) {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wid), TRUE);
+    }
+    
+    wid = gtk_radio_button_new_with_label(grp, _("Message Window"));
+    grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(wid));
+    gtk_box_pack_start(GTK_BOX(hbox), wid, FALSE, TRUE, 0);
+    conf->priv->widgets.pos_mw_radio = wid;
+    if (((MarkdownConfigViewPos) view_pos) == MARKDOWN_CONFIG_VIEW_POS_MSGWIN) {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wid), TRUE);
+    }
+    
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+  }
+  
+  { /* FONT BUTTON */
+    gchar *font_desc;
+    
+    label = gtk_label_new(_("Font:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+    
+    font_desc = g_strdup_printf("%s %d", fnt, fnt_sz);
+    wid = gtk_font_button_new_with_font(font_desc);
+    conf->priv->widgets.font_button = wid;
+    g_free(font_desc);
+    
+    gtk_table_attach(GTK_TABLE(table), wid, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND,
+      GTK_FILL, 0, 0);
+    
+    g_free(fnt);
+  }
+  
+  { /* CODE FONT BUTTON */
+    gchar *font_desc;
+    
+    label = gtk_label_new(_("Code Font:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
+    
+    font_desc = g_strdup_printf("%s %d", code_fnt, code_fnt_sz);
+    wid = gtk_font_button_new_with_font(font_desc);
+    conf->priv->widgets.code_font_button = wid;
+    g_free(font_desc);
+    
+    gtk_table_attach(GTK_TABLE(table), wid, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND,
+      GTK_FILL, 0, 0);
+    
+    g_free(code_fnt);
+  }
+  
+  { /* BG COLOR */
+    GdkColor bgclr;
+    
+    label = gtk_label_new(_("BG Color:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+    
+    gdk_color_parse(bg, &bgclr);
+    
+    wid = gtk_color_button_new_with_color(&bgclr);
+    conf->priv->widgets.bg_color_button = wid;
+    gtk_table_attach(GTK_TABLE(table), wid, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND,
+      GTK_FILL, 0, 0);
+    
+    g_free(bg);
+  }
+  
+  { /* FG COLOR */
+    GdkColor fgclr;
+    
+    label = gtk_label_new(_("FG Color:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
+    
+    gdk_color_parse(fg, &fgclr);
+    
+    wid = gtk_color_button_new_with_color(&fgclr);
+    conf->priv->widgets.fg_color_button = wid;
+    gtk_table_attach(GTK_TABLE(table), wid, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND,
+      GTK_FILL, 0, 0); 
+    
+    g_free(fg);
+  }
+  
+  { /* TEMPLATE FILE */
+    label = gtk_label_new(_("Template:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+    
+    wid = gtk_file_chooser_button_new(_("Select Template File"),
+      GTK_FILE_CHOOSER_ACTION_OPEN);
+    conf->priv->widgets.tmpl_file_button = wid;
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(wid), g_get_home_dir());
+    if (tmpl_file && tmpl_file[0]) {
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(wid), tmpl_file);
+    }
+    gtk_table_attach(GTK_TABLE(table), wid, 1, 2, 5, 6, GTK_FILL | GTK_EXPAND,
+      GTK_FILL, 0, 0);
+    
+    g_free(tmpl_file);
+  }
+  
+  g_signal_connect_swapped(dialog, "response", G_CALLBACK(on_dialog_response), conf);
+  
+  gtk_widget_show_all(table);
+  
+  return table;  
 }
 
-void markdown_conf_set_view_position(MarkdownConf *conf, MarkdownViewPosition pos)
+const gchar *
+markdown_config_get_template_text(MarkdownConfig *conf)
 {
-  g_return_if_fail(conf);
-  g_key_file_set_integer(conf->keyfile, "general", "position", (gint) pos);
+  g_return_val_if_fail(conf, NULL);
+  if (!conf->priv->tmpl_text) {
+    markdown_config_load_template_text(conf);
+  }
+  return (const gchar *) conf->priv->tmpl_text;
 }


Modified: markdown/src/conf.h
66 files changed, 43 insertions(+), 23 deletions(-)
===================================================================
@@ -1,52 +1,72 @@
 /*
- * conf.h - Part of the Geany Markdown plugin
- *
+ * markdownconfig.h
+ * 
  * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
+ * 
  * 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 2 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, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
+ * 
+ * 
  */
 
-#ifndef MARKDOWN_CONF_H
-#define MARKDOWN_CONF_H 1
 
-#include <glib.h>
+#ifndef __MARKDOWNCONFIG_H__
+#define __MARKDOWNCONFIG_H__
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-typedef enum {
-  MARKDOWN_VIEW_POS_SIDEBAR=0,
-  MARKDOWN_VIEW_POS_MSGWIN=1
-} MarkdownViewPosition;
 
-typedef struct MarkdownConf MarkdownConf;
+#define MARKDOWN_TYPE_CONFIG             (markdown_config_get_type ())
+#define MARKDOWN_CONFIG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MARKDOWN_TYPE_CONFIG, MarkdownConfig))
+#define MARKDOWN_CONFIG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), MARKDOWN_TYPE_CONFIG, MarkdownConfigClass))
+#define MARKDOWN_IS_CONFIG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MARKDOWN_TYPE_CONFIG))
+#define MARKDOWN_IS_CONFIG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), MARKDOWN_TYPE_CONFIG))
+#define MARKDOWN_CONFIG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), MARKDOWN_TYPE_CONFIG, MarkdownConfigClass))
+
+typedef struct _MarkdownConfig         MarkdownConfig;
+typedef struct _MarkdownConfigClass    MarkdownConfigClass;
+typedef struct _MarkdownConfigPrivate  MarkdownConfigPrivate;
+
+typedef enum {
+  MARKDOWN_CONFIG_VIEW_POS_SIDEBAR=0,
+  MARKDOWN_CONFIG_VIEW_POS_MSGWIN=1,
+  MARKDOWN_CONFIG_VIEW_POS_MAX
+} MarkdownConfigViewPos;
 
-MarkdownConf *markdown_conf_new(const gchar *conf_filename);
-void markdown_conf_free(MarkdownConf *conf);
-void markdown_conf_save(MarkdownConf *conf);
+struct _MarkdownConfig
+{
+  GObject parent;
+  MarkdownConfigPrivate *priv;
+};
 
-gchar *markdown_conf_get_template_name(MarkdownConf *conf);
-void markdown_conf_set_template_name(MarkdownConf *conf, const gchar *tmpl_name);
+struct _MarkdownConfigClass
+{
+  GObjectClass parent_class;
+};
 
-gboolean markdown_conf_get_readme_shown(MarkdownConf *conf);
-void markdown_conf_set_readme_shown(MarkdownConf *conf, gboolean shown);
 
-MarkdownViewPosition markdown_conf_get_view_position(MarkdownConf *conf);
-void markdown_conf_set_view_position(MarkdownConf *conf, MarkdownViewPosition pos);
+GType markdown_config_get_type(void);
+MarkdownConfig *markdown_config_new(const gchar *filename);
+gboolean markdown_config_save(MarkdownConfig *conf);
+GtkWidget *markdown_config_gui(MarkdownConfig *conf, GtkDialog *dialog);
 
+const gchar *markdown_config_get_template_text(MarkdownConfig *conf);
 
 G_END_DECLS
 
-#endif /* MARKDOWN_CONF_H */
+#endif /* __MARKDOWNCONFIG_H__ */


Modified: markdown/src/plugin.c
237 files changed, 41 insertions(+), 196 deletions(-)
===================================================================
@@ -21,7 +21,6 @@
 
 #include <geanyplugin.h>
 #include "viewer.h"
-#include "tmplmgr.h"
 #include "conf.h"
 
 GeanyData      *geany_data;
@@ -51,118 +50,49 @@
   } handler_ids;
   GtkWidget *menu_item;
   MarkdownViewer *viewer;
-  MarkdownConf *conf;
+  MarkdownConfig *config;
 } MarkdownPlugin;
 MarkdownPlugin markdown_plugin = { { 0, 0 }, NULL, NULL, NULL };
 
 /* Forward declarations */
-static gboolean on_conf_idle_handler(MarkdownPlugin *plugin);
-static void handle_conf_save_later(MarkdownPlugin *plugin);
 static gboolean on_idle_handler(MarkdownPlugin *plugin);
 static void handle_update_later(MarkdownPlugin *plugin);
 static gboolean on_editor_notify(GObject *obj, GeanyEditor *editor, SCNotification *notif, MarkdownPlugin *plugin);
 static void on_document_signal(GObject *obj, GeanyDocument *doc, MarkdownPlugin *plugin);
 static void on_document_filetype_set(GObject *obj, GeanyDocument *doc, GeanyFiletype *ft_old, MarkdownPlugin *plugin);
-static void on_template_menu_item_activate(GtkCheckMenuItem *item, MarkdownPlugin *plugin);
-static void on_view_position_menu_item_activate(GtkCheckMenuItem *item, MarkdownPlugin *plugin);
-static void on_view_readme_activate(GtkMenuItem *item, MarkdownPlugin *plugin);
-static GSList *get_all_templates(void);
+
+static void 
+on_conf_prop_notify(GObject *obj, GParamSpec *pspec, MarkdownPlugin *plugin)
+{
+  handle_update_later(plugin);
+}
 
 /* Main plugin entry point on plugin load. */
 void plugin_init(GeanyData *data)
 {
-  GtkMenu *menu, *tmpl_menu, *pos_menu;
-  GtkWidget *itm, *tmpl_item, *pos_item;
-  GSList *iter, *templates;
-  GSList *radio_group = NULL;
-  gchar *conf_fn, *conf_tmpl_name, *readme_fn;
-  MarkdownViewPosition view_pos;
+  gchar *conf_fn;
+  MarkdownConfigViewPos view_pos;
 
-  conf_fn = g_build_filename(geany->app->configdir, "plugins", "markdown",
-    "markdown.conf", NULL);
-  markdown_plugin.conf = markdown_conf_new(conf_fn);
+  conf_fn = g_build_filename(geany->app->configdir, "plugins", "markdown", "markdown.conf", NULL);
+  markdown_plugin.config = markdown_config_new(conf_fn);
   g_free(conf_fn);
-  conf_tmpl_name = markdown_conf_get_template_name(markdown_plugin.conf);
-  view_pos = markdown_conf_get_view_position(markdown_plugin.conf);
+  
+  g_signal_connect(markdown_plugin.config, "notify",
+    G_CALLBACK(on_conf_prop_notify), &markdown_plugin);
+
+  g_object_get(markdown_plugin.config, "view-pos", &view_pos, NULL);
 
   switch (view_pos) {
-    case MARKDOWN_VIEW_POS_MSGWIN:
+    case MARKDOWN_CONFIG_VIEW_POS_MSGWIN:
       markdown_plugin.viewer = markdown_viewer_new(
         GTK_NOTEBOOK(geany->main_widgets->message_window_notebook));
       break;
-    case MARKDOWN_VIEW_POS_SIDEBAR:
+    case MARKDOWN_CONFIG_VIEW_POS_SIDEBAR:
     default:
       markdown_plugin.viewer = markdown_viewer_new(
         GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
       break;
   }
-  markdown_conf_set_view_position(markdown_plugin.conf, view_pos);
-  handle_conf_save_later(&markdown_plugin);
-
-  markdown_plugin.menu_item = gtk_menu_item_new_with_label(_("Markdown"));
-  menu = GTK_MENU(gtk_menu_new());
-  gtk_menu_item_set_submenu(GTK_MENU_ITEM(markdown_plugin.menu_item), GTK_WIDGET(menu));
-  gtk_menu_shell_append(GTK_MENU_SHELL(geany->main_widgets->tools_menu), markdown_plugin.menu_item);
-
-  pos_item = gtk_menu_item_new_with_label(_("Position"));
-  pos_menu = GTK_MENU(gtk_menu_new());
-  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pos_item), GTK_WIDGET(pos_menu));
-  gtk_menu_shell_append(GTK_MENU_SHELL(menu), pos_item);
-
-  itm = gtk_radio_menu_item_new_with_label(radio_group, _("Sidebar"));
-  radio_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(itm));
-  gtk_menu_shell_append(GTK_MENU_SHELL(pos_menu), itm);
-  g_object_set_data(G_OBJECT(itm), "pos",
-    GINT_TO_POINTER((gint) MARKDOWN_VIEW_POS_SIDEBAR));
-  g_signal_connect(G_OBJECT(itm), "activate",
-    G_CALLBACK(on_view_position_menu_item_activate), &markdown_plugin);
-  if (view_pos == MARKDOWN_VIEW_POS_SIDEBAR)
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(itm), TRUE);
-
-  itm = gtk_radio_menu_item_new_with_label(radio_group, _("Message Window"));
-  radio_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(itm));
-  gtk_menu_shell_append(GTK_MENU_SHELL(pos_menu), itm);
-  g_object_set_data(G_OBJECT(itm), "pos",
-    GINT_TO_POINTER((gint) MARKDOWN_VIEW_POS_MSGWIN));
-  g_signal_connect(G_OBJECT(itm), "activate",
-    G_CALLBACK(on_view_position_menu_item_activate), &markdown_plugin);
-  if (view_pos == MARKDOWN_VIEW_POS_MSGWIN)
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(itm), TRUE);
-  /* ... */
-  radio_group = NULL; /* for tmpl items */
-
-  tmpl_item = gtk_menu_item_new_with_label(_("Template"));
-  tmpl_menu = GTK_MENU(gtk_menu_new());
-  gtk_menu_item_set_submenu(GTK_MENU_ITEM(tmpl_item), GTK_WIDGET(tmpl_menu));
-  gtk_menu_shell_append(GTK_MENU_SHELL(menu), tmpl_item);
-
-  templates = get_all_templates();
-  for (iter = templates; iter != NULL; iter = g_slist_next(iter)) {
-    MarkdownTemplate *t = (MarkdownTemplate*) iter->data;
-    itm = gtk_radio_menu_item_new_with_label(radio_group,
-      markdown_template_get_name(t));
-    radio_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(itm));
-    /* Menu items take ownership of the templates */
-    g_object_set_data_full(G_OBJECT(itm), "tmpl", t, (GDestroyNotify) markdown_template_free);
-    gtk_menu_shell_append(GTK_MENU_SHELL(tmpl_menu), itm);
-    g_signal_connect(G_OBJECT(itm), "activate", G_CALLBACK(on_template_menu_item_activate),
-      &markdown_plugin);
-    if (g_strcmp0(markdown_template_get_name(t), conf_tmpl_name) == 0) {
-      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(itm), TRUE);
-      markdown_viewer_set_template(markdown_plugin.viewer, t);
-      ui_set_statusbar(TRUE, _("Activated Markdown template: %s"),
-        markdown_template_get_name(t));
-    }
-  }
-  g_slist_free(templates);
-  g_free(conf_tmpl_name);
-
-  itm = gtk_menu_item_new_with_label("README.md");
-  gtk_menu_shell_append(GTK_MENU_SHELL(menu), itm);
-  g_signal_connect(G_OBJECT(itm), "activate", G_CALLBACK(on_view_readme_activate),
-    &markdown_plugin);
-
-  gtk_widget_show_all(markdown_plugin.menu_item);
 
   plugin_signal_connect(geany_plugin, NULL, "editor-notify", TRUE,
     G_CALLBACK(on_editor_notify), &markdown_plugin);
@@ -181,42 +111,19 @@ void plugin_init(GeanyData *data)
 
   /* Prevent segmentation fault when plugin is reloaded. */
   plugin_module_make_resident(geany_plugin);
-
-  /* On the first load show the README.md file */
-  if (!markdown_conf_get_readme_shown(markdown_plugin.conf)) {
-    readme_fn = g_build_filename(MARKDOWN_DOC_DIR, "README.md", NULL);
-    document_open_file(readme_fn, TRUE, NULL, NULL);
-    g_free(readme_fn);
-    markdown_conf_set_readme_shown(markdown_plugin.conf, TRUE);
-    handle_conf_save_later(&markdown_plugin);
-  }
 }
 
 /* Cleanup resources on plugin unload. */
 void plugin_cleanup(void)
 {
-  markdown_conf_save(markdown_plugin.conf);
-  markdown_conf_free(markdown_plugin.conf);
-  gtk_widget_destroy(markdown_plugin.menu_item);
+  g_object_unref(markdown_plugin.config);
   markdown_viewer_free(markdown_plugin.viewer);
   return;
 }
 
-/* Save configuration file when idle. */
-static gboolean on_conf_idle_handler(MarkdownPlugin *plugin)
+GtkWidget *plugin_configure(GtkDialog *dialog)
 {
-  markdown_conf_save(plugin->conf);
-  plugin->handler_ids.save_conf = 0;
-  return FALSE;
-}
-
-/* Queue a configuration file save later if one isn't queued. */
-static void handle_conf_save_later(MarkdownPlugin *plugin)
-{
-  if (plugin->handler_ids.save_conf == 0) {
-    plugin->handler_ids.save_conf = plugin_idle_add(geany_plugin,
-      (GSourceFunc) on_conf_idle_handler, plugin);
-  }
+  return markdown_config_gui(markdown_plugin.config, dialog);
 }
 
 /* Update markdown preview when idle. */
@@ -224,18 +131,35 @@ static gboolean on_idle_handler(MarkdownPlugin *plugin)
 {
   gchar *md_text;
   GeanyDocument *doc = document_get_current();
+  MarkdownConfigViewPos view_pos;
+
+  g_object_get(plugin->config, "view-pos", &view_pos, NULL);
+  
+  switch (view_pos) {
+    case MARKDOWN_CONFIG_VIEW_POS_MSGWIN:
+      markdown_viewer_set_notebook(plugin->viewer,
+        GTK_NOTEBOOK(geany->main_widgets->message_window_notebook));
+      break;
+    case MARKDOWN_CONFIG_VIEW_POS_SIDEBAR:
+    default:
+      markdown_viewer_set_notebook(plugin->viewer,
+        GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
+      break;
+  }
 
   /* Only handle valid Markdown documents */
   if (!DOC_VALID(doc) || g_strcmp0(doc->file_type->name, "Markdown") != 0) {
-    markdown_viewer_update_content(plugin->viewer,
-      _("The current document does not have a Markdown filetype."), "UTF-8");
+    markdown_viewer_load_markdown_string(plugin->viewer,
+      _("The current document does not have a Markdown filetype."), "UTF-8",
+      plugin->config);
     plugin->handler_ids.update_view = 0;
     return FALSE;
   }
 
   md_text = (gchar*) scintilla_send_message(doc->editor->sci,
     SCI_GETCHARACTERPOINTER, 0, 0);
-  markdown_viewer_update_content(plugin->viewer, md_text, doc->encoding);
+  markdown_viewer_load_markdown_string(plugin->viewer, md_text,
+    doc->encoding, plugin->config);
 
   plugin->handler_ids.update_view = 0;
 
@@ -281,82 +205,3 @@ static void on_document_filetype_set(GObject *obj, GeanyDocument *doc, GeanyFile
 {
   handle_update_later(plugin);
 }
-
-/* Change the active markdown preview template when the menu item is clicked. */
-static void on_template_menu_item_activate(GtkCheckMenuItem *item, MarkdownPlugin *plugin)
-{
-  MarkdownTemplate *tmpl;
-
-  { /* FIXME: this is stupid */
-    static gboolean inhibit = FALSE;
-    if (inhibit) { return; }
-    inhibit = TRUE;
-    gtk_check_menu_item_set_active(item, !gtk_check_menu_item_get_active(item));
-    inhibit = FALSE;
-  }
-
-  tmpl = (MarkdownTemplate *) g_object_get_data(G_OBJECT(item), "tmpl");
-  markdown_viewer_set_template(plugin->viewer, tmpl);
-
-  handle_update_later(plugin);
-
-  ui_set_statusbar(TRUE, _("Activated Markdown template: %s"),
-    markdown_template_get_name(tmpl));
-
-  markdown_conf_set_template_name(plugin->conf, markdown_template_get_name(tmpl));
-  handle_conf_save_later(plugin);
-}
-
-/* Change the position/location of the view (ex. sidebar, msgwin, etc.) */
-static void on_view_position_menu_item_activate(GtkCheckMenuItem *item, MarkdownPlugin *plugin)
-{
-  gpointer pos_as_ptr = g_object_get_data(G_OBJECT(item), "pos");
-  gint pos = GPOINTER_TO_INT(pos_as_ptr);
-  MarkdownViewPosition old_pos = markdown_conf_get_view_position(plugin->conf);
-
-  /* It hasn't changed positions */
-  if ((gint) old_pos == pos)
-    return;
-
-  switch (pos) {
-    case MARKDOWN_VIEW_POS_MSGWIN:
-      markdown_viewer_set_notebook(plugin->viewer,
-        GTK_NOTEBOOK(geany->main_widgets->message_window_notebook));
-      break;
-    case MARKDOWN_VIEW_POS_SIDEBAR:
-    default:
-      markdown_viewer_set_notebook(plugin->viewer,
-        GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
-      break;
-  }
-
-  markdown_conf_set_view_position(plugin->conf, (MarkdownViewPosition) pos);
-  handle_conf_save_later(plugin);
-}
-
-static void on_view_readme_activate(GtkMenuItem *item, MarkdownPlugin *plugin)
-{
-  gchar *readme_fn = g_build_filename(MARKDOWN_DOC_DIR, "README.md", NULL);
-  document_open_file(readme_fn, TRUE, NULL, NULL);
-  g_free(readme_fn);
-}
-
-/* Retrieve a list of all templates in user config dir and sys config dir */
-static GSList *get_all_templates(void)
-{
-  GSList *list;
-  gchar *usr_dir, *sys_dir;
-  MarkdownTemplateManager *mgr;
-
-  usr_dir = g_build_filename(geany->app->configdir, "plugins", "markdown", "templates", NULL);
-  sys_dir = g_build_filename(MARKDOWN_DATA_DIR, "templates", NULL);
-
-  mgr = markdown_template_manager_new(usr_dir, sys_dir);
-  list = markdown_template_manager_list_templates(mgr);
-  markdown_template_manager_free(mgr);
-
-  g_free(usr_dir);
-  g_free(sys_dir);
-
-  return list;
-}


Modified: markdown/src/tmpl.c
143 files changed, 0 insertions(+), 143 deletions(-)
===================================================================
@@ -1,143 +0,0 @@
-/*
- * tmpl.c - Part of the Geany Markdown plugin
- *
- * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <glib.h>
-#include <string.h>
-#include "tmpl.h"
-
-struct MarkdownTemplate {
-  gchar *name;
-  gchar *filename;
-  gchar *base_dir;
-  gchar *text;
-  gsize  text_len;
-};
-
-static void markdown_template_load_file(MarkdownTemplate *tmpl)
-{
-  GError *error = NULL;
-
-  g_return_if_fail(tmpl);
-
-  g_free(tmpl->text);
-  tmpl->text = NULL;
-  tmpl->text_len = 0;
-
-  if (!g_file_get_contents(tmpl->filename, &(tmpl->text), &(tmpl->text_len), &error)) {
-    g_warning("Unable to load template file '%s': %s", tmpl->filename,
-      error->message);
-    g_error_free(error); error = NULL;
-    tmpl->text = g_strdup("");
-    tmpl->text_len = 0;
-  }
-}
-
-MarkdownTemplate *markdown_template_new(const gchar *tmpl_name,
-  const gchar *tmpl_file)
-{
-  MarkdownTemplate *tmpl = g_slice_new0(MarkdownTemplate);
-  if (tmpl) {
-    markdown_template_set_name(tmpl, tmpl_name);
-    markdown_template_set_filename(tmpl, tmpl_file);
-  }
-  return tmpl;
-}
-
-void markdown_template_free(MarkdownTemplate *tmpl)
-{
-  if (tmpl) {
-    g_free(tmpl->name);
-    g_free(tmpl->filename);
-    g_free(tmpl->base_dir);
-    g_free(tmpl->text);
-    g_slice_free1(sizeof(MarkdownTemplate), tmpl);
-  }
-}
-
-const gchar *markdown_template_get_name(MarkdownTemplate *tmpl)
-{
-  g_return_val_if_fail(tmpl, NULL);
-  return (const gchar *) tmpl->name;
-}
-
-void markdown_template_set_name(MarkdownTemplate *tmpl, const gchar *name)
-{
-  g_return_if_fail(tmpl);
-  g_free(tmpl->name);
-  tmpl->name = name ? g_strdup(name) : g_strdup("");
-}
-
-const gchar *markdown_template_get_filename(MarkdownTemplate *tmpl)
-{
-  g_return_val_if_fail(tmpl, NULL);
-  return (const gchar *) tmpl->filename;
-}
-
-const gchar *markdown_template_get_base_dir(MarkdownTemplate *tmpl)
-{
-  g_return_val_if_fail(tmpl, NULL);
-  return (const gchar *) tmpl->base_dir;
-}
-
-void markdown_template_set_filename(MarkdownTemplate *tmpl, const gchar *filename)
-{
-  g_return_if_fail(tmpl);
-  g_free(tmpl->filename);
-  tmpl->filename = filename ? g_strdup(filename) : g_strdup("");
-  tmpl->base_dir = filename ? g_path_get_dirname(tmpl->filename) : g_strdup("");
-}
-
-const gchar *markdown_template_get_text(MarkdownTemplate *tmpl, gsize *len)
-{
-  g_return_val_if_fail(tmpl, NULL);
-
-  /* This is here to delay loading the file and allocating a bunch of
-   * memory until the template text actually needs to be read. */
-  if (tmpl->text == NULL || tmpl->text_len == 0) {
-    markdown_template_load_file(tmpl);
-  }
-
-  if (len) {
-    *len = tmpl->text_len;
-  }
-
-  return (const gchar *) tmpl->text;
-}
-
-gchar *markdown_template_replace(MarkdownTemplate *tmpl, const gchar *replacement,
-  gsize *replaced_len)
-{
-  gchar *repl, **parts;
-  const gchar *tmpl_text;
-
-  g_return_val_if_fail(tmpl, NULL);
-
-  tmpl_text = markdown_template_get_text(tmpl, NULL);
-  parts = g_strsplit(tmpl_text, MARKDOWN_TEMPLATE_STRING, 0);
-  repl = g_strjoinv(replacement, parts);
-  g_strfreev(parts);
-
-  if (replaced_len) {
-    *replaced_len = strlen(repl);
-  }
-
-  return repl;
-}


Modified: markdown/src/tmpl.h
51 files changed, 0 insertions(+), 51 deletions(-)
===================================================================
@@ -1,51 +0,0 @@
-/*
- * tmpl.h - Part of the Geany Markdown plugin
- *
- * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef MARKDOWN_TEMPLATE_H
-#define MARKDOWN_TEMPLATE_H 1
-
-G_BEGIN_DECLS
-
-#include <glib.h>
-
-#define MARKDOWN_TEMPLATE_STRING "<!-- @markdown_document@ -->"
-
-typedef struct MarkdownTemplate MarkdownTemplate;
-
-MarkdownTemplate *markdown_template_new(const gchar *tmpl_name,
-  const gchar *tmpl_file);
-
-void markdown_template_free(MarkdownTemplate *tmpl);
-
-const gchar *markdown_template_get_name(MarkdownTemplate *tmpl);
-const gchar *markdown_template_get_filename(MarkdownTemplate *tmpl);
-const gchar *markdown_template_get_base_dir(MarkdownTemplate *tmpl);
-const gchar *markdown_template_get_text(MarkdownTemplate *tmpl, gsize *len);
-
-void markdown_template_set_name(MarkdownTemplate *tmpl, const gchar *name);
-void markdown_template_set_filename(MarkdownTemplate *tmpl, const gchar *filename);
-
-gchar *markdown_template_replace(MarkdownTemplate *tmpl, const gchar *replacement,
-  gsize *replaced_len);
-
-G_END_DECLS
-
-#endif /* MARKDOWN_TEMPLATE_H */


Modified: markdown/src/tmplmgr.c
149 files changed, 0 insertions(+), 149 deletions(-)
===================================================================
@@ -1,149 +0,0 @@
-/*
- * tmplmgr.c - Part of the Geany Markdown plugin
- *
- * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <string.h>
-#include <glib.h>
-#include "tmpl.h"
-#include "tmplmgr.h"
-
-struct MarkdownTemplateManager {
-  gchar *user_path;
-  gchar *system_path;
-  MarkdownTemplate *template;
-};
-
-MarkdownTemplateManager *markdown_template_manager_new(const gchar *user_path,
-  const gchar *system_path)
-{
-  MarkdownTemplateManager *tmplmgr = g_slice_new0(MarkdownTemplateManager);
-  if (tmplmgr) {
-    tmplmgr->user_path = g_strdup(user_path);
-    tmplmgr->system_path = g_strdup(system_path);
-  }
-  return tmplmgr;
-}
-
-void markdown_template_manager_free(MarkdownTemplateManager *mgr)
-{
-  g_return_if_fail(mgr);
-  g_free(mgr->user_path);
-  g_free(mgr->system_path);
-  g_slice_free(MarkdownTemplateManager, mgr);
-}
-
-static GSList *markdown_template_manager_read_templates_from_dir(
-  MarkdownTemplateManager *mgr, const gchar *dirpath)
-{
-  GError *error = NULL;
-  GSList *list = NULL;
-  GDir *dir;
-  const gchar *ent;
-
-  dir = g_dir_open(dirpath, 0, &error);
-
-  if (!dir) {
-    /*g_warning("Error opening directory '%s': %s", dirpath, error->message);*/
-    g_error_free(error); error = NULL;
-    return NULL;
-  }
-
-  while ((ent = g_dir_read_name(dir)) != NULL) {
-    MarkdownTemplate *tmpl;
-    gchar *path, *tmpl_name, *tmpl_file;
-    if (g_strcmp0(ent, ".") == 0 || g_strcmp0(ent, "..") == 0)
-      continue;
-    path = g_build_filename(dirpath, ent, NULL);
-    tmpl_file = g_build_filename(path, "index.html", NULL);
-    tmpl_name = g_path_get_dirname(tmpl_file);
-    gchar *last_slash = strrchr(tmpl_name, '/');
-    if (last_slash) {
-      last_slash++;
-      g_memmove(tmpl_name, last_slash, strlen(last_slash) + 1);
-    }
-    if (g_file_test(tmpl_file, G_FILE_TEST_EXISTS)) {
-      tmpl = markdown_template_new(tmpl_name, tmpl_file);
-      list = g_slist_prepend(list, tmpl);
-    }
-    g_free(path);
-    g_free(tmpl_name);
-    g_free(tmpl_file);
-  }
-
-  return list;
-}
-
-static gboolean markdown_template_manager_list_has_template(
-  MarkdownTemplateManager *mgr, GSList *list, const gchar *tmpl_name)
-{
-  GSList *iter;
-  gboolean result = FALSE;
-
-  for (iter = list; iter != NULL; iter = g_slist_next(iter)) {
-    MarkdownTemplate *tmpl = (MarkdownTemplate*) iter->data;
-    if (g_strcmp0(markdown_template_get_name(tmpl), tmpl_name) == 0) {
-      result = TRUE;
-      break;
-    }
-  }
-
-  return result;
-}
-
-static GSList *markdown_template_manager_combine_lists(MarkdownTemplateManager *mgr,
-  GSList *user_list, GSList *system_list)
-{
-  GSList *list = NULL, *iter;
-
-  for (iter = user_list; iter != NULL; iter = g_slist_next(iter)) {
-    MarkdownTemplate *tmpl = (MarkdownTemplate*) iter->data;
-    if (!markdown_template_manager_list_has_template(mgr, list,
-      markdown_template_get_name(tmpl))) {
-      list = g_slist_prepend(list, tmpl);
-    }
-  }
-
-  for (iter = system_list; iter != NULL; iter = g_slist_next(iter)) {
-    MarkdownTemplate *tmpl = (MarkdownTemplate*) iter->data;
-    if (!markdown_template_manager_list_has_template(mgr, list,
-      markdown_template_get_name(tmpl))) {
-      list = g_slist_prepend(list, tmpl);
-    }
-  }
-
-  return list;
-}
-
-GSList *markdown_template_manager_list_templates(MarkdownTemplateManager *mgr)
-{
-  GSList *list, *user_list, *system_list;
-
-  g_return_val_if_fail(mgr, NULL);
-
-  user_list = markdown_template_manager_read_templates_from_dir(mgr, mgr->user_path);
-  system_list = markdown_template_manager_read_templates_from_dir(mgr, mgr->system_path);
-
-  list = markdown_template_manager_combine_lists(mgr, user_list, system_list);
-
-  g_slist_free(user_list);
-  g_slist_free(system_list);
-
-  return list;
-}


Modified: markdown/src/tmplmgr.h
40 files changed, 0 insertions(+), 40 deletions(-)
===================================================================
@@ -1,40 +0,0 @@
-/*
- * tmplmgr.h - Part of the Geany Markdown plugin
- *
- * Copyright 2012 Matthew Brush <mbrush at codebrainz.ca>
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef MARKDOWN_TEMPLATE_MANAGER_H
-#define MARKDOWN_TEMPLATE_MANAGER_H 1
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#include "tmpl.h"
-
-typedef struct MarkdownTemplateManager MarkdownTemplateManager;
-
-MarkdownTemplateManager *markdown_template_manager_new(const gchar *user_path,
-  const gchar *system_path);
-void markdown_template_manager_free(MarkdownTemplateManager *mgr);
-GSList *markdown_template_manager_list_templates(MarkdownTemplateManager *mgr);
-
-G_END_DECLS
-
-#endif /* MARKDOWN_TEMPLATE_MANAGER_H */


Modified: markdown/src/viewer.c
93 files changed, 73 insertions(+), 20 deletions(-)
===================================================================
@@ -24,6 +24,7 @@
 #include <webkit/webkitwebview.h>
 #include "viewer.h"
 #include "md.h"
+#include "conf.h"
 
 #define MARKDOWN_VIEWER_TAB_LABEL _("Markdown Preview")
 
@@ -31,7 +32,6 @@ struct MarkdownViewer {
   GtkScrolledWindow *scrolled_win; /* The GtkScrolledWindow containing the WebKitView */
   WebKitWebView     *webview;      /* The Webkit preview widget */
   GtkNotebook       *notebook;     /* Either the sidebar notebook or the msgwin notebook */
-  MarkdownTemplate  *template;     /* The active preview template */
   gdouble old_pos; /* Position before reload, used to reset scroll pos. */
 };
 
@@ -83,23 +83,11 @@ void markdown_viewer_set_notebook(MarkdownViewer *viewer, GtkNotebook *nb)
   page_num = gtk_notebook_append_page(viewer->notebook, GTK_WIDGET(viewer->scrolled_win),
     gtk_label_new(MARKDOWN_VIEWER_TAB_LABEL));
 
-  /*gtk_notebook_set_current_page(viewer->notebook, page_num);*/
+  gtk_notebook_set_current_page(viewer->notebook, page_num);
 
   g_object_unref(G_OBJECT(viewer->scrolled_win));
 }
 
-MarkdownTemplate *markdown_viewer_get_template(MarkdownViewer *viewer)
-{
-  g_return_val_if_fail(viewer, NULL);
-  return viewer->template;
-}
-
-void markdown_viewer_set_template(MarkdownViewer *viewer, MarkdownTemplate *tmpl)
-{
-  g_return_if_fail(viewer && tmpl);
-  viewer->template = tmpl;
-}
-
 void on_viewer_load_status_notify(GObject *obj, GParamSpec *pspec, MarkdownViewer *viewer)
 {
   GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(viewer->scrolled_win);
@@ -109,18 +97,83 @@ void on_viewer_load_status_notify(GObject *obj, GParamSpec *pspec, MarkdownViewe
   }
 }
 
-void markdown_viewer_update_content(MarkdownViewer *viewer, const gchar *text,
-  const gchar *encoding)
+
+
+static gchar *
+str_replace(const gchar *haystack, const gchar *needle, const gchar *repl)
+{
+  gchar *out_str, **parts;
+  
+  parts = g_strsplit(haystack, needle, 0);
+  out_str = g_strjoinv(repl, parts);
+  g_strfreev(parts);
+  
+  return out_str;
+}
+
+static gchar *
+markdown_viewer_replace(const gchar *html_text, MarkdownConfig *config)
+{
+  MarkdownConfigViewPos view_pos;
+  guint font_point_size = 0;
+  gchar *out_str, *tmp;
+  gchar *font_pt_size, *code_font_pt_size;
+  gchar *font_name = NULL, *code_font_name = NULL;
+  gchar *bg_color = NULL, *fg_color = NULL;
+  guint code_font_point_size = 0;
+  
+  g_object_get(config,
+               "view-pos", &view_pos,
+               "font-name", &font_name,
+               "code-font-name", &code_font_name,
+               "font-point-size", &font_point_size,
+               "code-font-point-size", &code_font_point_size,
+               "bg-color", &bg_color,
+               "fg-color", &fg_color,
+               NULL);
+  
+  font_pt_size = g_strdup_printf("%d", font_point_size);
+  code_font_pt_size = g_strdup_printf("%d", code_font_point_size);
+  
+  tmp = str_replace(markdown_config_get_template_text(config),
+    "@@font_name@@", font_name);
+  out_str = tmp;
+  tmp = str_replace(out_str, "@@code_font_name@@", code_font_name);
+  g_free(out_str); out_str = tmp;
+  tmp = str_replace(out_str, "@@font_point_size@@", font_pt_size);
+  g_free(out_str); out_str = tmp;
+  tmp = str_replace(out_str, "@@code_font_point_size@@", code_font_pt_size);
+  g_free(out_str); out_str = tmp;
+  tmp = str_replace(out_str, "@@bg_color@@", bg_color);
+  g_free(out_str); out_str = tmp;
+  tmp = str_replace(out_str, "@@fg_color@@", fg_color);
+  g_free(out_str); out_str = tmp;
+  tmp = str_replace(out_str, "@@markdown@@", html_text);
+  g_free(out_str); out_str = tmp;
+  
+  g_free(font_name);
+  g_free(code_font_name);
+  g_free(font_pt_size);
+  g_free(code_font_pt_size);
+  g_free(bg_color);
+  g_free(fg_color);
+  
+  /*g_debug("Replaced:\n%s", out_str);*/
+  
+  return out_str;
+}
+
+void markdown_viewer_load_markdown_string(MarkdownViewer *viewer,
+  const gchar *md_str, const gchar *encoding, MarkdownConfig *config)
 {
   g_return_if_fail(viewer);
-  gchar *html = markdown_to_html(text);
-  gchar *new_text = markdown_template_replace(viewer->template, html, NULL);
+  gchar *html = markdown_to_html(md_str);
+  gchar *new_text = markdown_viewer_replace(html, config);
   GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(viewer->scrolled_win);
   viewer->old_pos = gtk_adjustment_get_value(vadj);
   g_free(html);
   if (new_text) {
-    gchar *base_uri = g_strdup_printf("file://%s",
-      markdown_template_get_filename(viewer->template));
+    gchar *base_uri = g_strdup_printf("file://.");
     g_signal_connect(viewer->webview, "notify::load-status",
       G_CALLBACK(on_viewer_load_status_notify), viewer);
     webkit_web_view_load_string(viewer->webview, new_text, "text/html",


Modified: markdown/src/viewer.h
9 files changed, 3 insertions(+), 6 deletions(-)
===================================================================
@@ -25,7 +25,7 @@
 G_BEGIN_DECLS
 
 #include <gtk/gtk.h>
-#include "tmpl.h"
+#include "conf.h"
 
 typedef struct MarkdownViewer MarkdownViewer;
 
@@ -35,14 +35,11 @@
 GtkNotebook *markdown_viewer_get_notebook(MarkdownViewer *viewer);
 void markdown_viewer_set_notebook(MarkdownViewer *viewer, GtkNotebook *nb);
 
-MarkdownTemplate *markdown_viewer_get_template(MarkdownViewer *viewer);
-void markdown_viewer_set_template(MarkdownViewer *viewer, MarkdownTemplate *tmpl);
-
 void markdown_viewer_show(MarkdownViewer *viewer);
 void markdown_viewer_hide(MarkdownViewer *viewer);
 
-void markdown_viewer_update_content(MarkdownViewer *viewer, const gchar *text,
-  const gchar *encoding);
+void markdown_viewer_load_markdown_string(MarkdownViewer *viewer,
+  const gchar *md_str, const gchar *encoding, MarkdownConfig *config);
 
 G_END_DECLS
 


Modified: markdown/templates/Alternate/Kreon.ttf
0 files changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: markdown/templates/Alternate/LICENSE.kreon
93 files changed, 0 insertions(+), 93 deletions(-)
===================================================================
@@ -1,93 +0,0 @@
-Copyright (c) 2012, Julia Petretta, with Reserved Font Name Kreon.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.


Modified: markdown/templates/Alternate/LICENSE.pointfree
24 files changed, 0 insertions(+), 24 deletions(-)
===================================================================
@@ -1,24 +0,0 @@
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or
-distribute this software, either in source code form or as a compiled
-binary, for any purpose, commercial or non-commercial, and by any
-means.
-
-In jurisdictions that recognize copyright laws, the author or authors
-of this software dedicate any and all copyright interest in the
-software to the public domain. We make this dedication for the benefit
-of the public at large and to the detriment of our heirs and
-successors. We intend this dedication to be an overt act of
-relinquishment in perpetuity of all present and future rights to this
-software under copyright law.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-For more information, please refer to <http://unlicense.org/>
\ No newline at end of file


Modified: markdown/templates/Alternate/Makefile.am
10 files changed, 0 insertions(+), 10 deletions(-)
===================================================================
@@ -1,10 +0,0 @@
-
-alttmpldir = $(pkgdatadir)/markdown/templates/Alternate
-alttmpl_DATA = \
-	index.html \
-	alternate.css \
-	background.png \
-	Kreon.ttf \
-	LICENSE.kreon \
-	Pointfree.ttf \
-	LICENSE.pointfree


Modified: markdown/templates/Alternate/Pointfree.ttf
0 files changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: markdown/templates/Alternate/alternate.css
80 files changed, 0 insertions(+), 80 deletions(-)
===================================================================
@@ -1,80 +0,0 @@
- at font-face {
-  font-family: Kreon;
-  src: url('Kreon.ttf');
-}
-
- at font-face {
-  font-family: Pointfree;
-  src: url('Pointfree.ttf');
-}
-
-body { 
-  background: url('background.png');
-  background-attachment: fixed;
-  color: #141414;
-  font-family: Kreon, serif;
-  font-size: 14pt;
-}
-
-p {
-  text-shadow: 1px 1px 1px #fff;
-}
-
-h1 {
-  text-align: center;
-  padding-bottom: 1.0em;
-}
-
-h2, h3, h4, h5, h6 {
-  color: #53C20D;
-}
-
-h1, h2, h3, h4, h5, h6 {
-  font-family: Pointfree;
-}
-
-a:link {
-  color: #143300;
-  text-decoration: none;
-}
-
-a:visited {
-  color: #143300;
-  text-decoration: underline;
-}
-
-a:hover {
-  color: #53C20D;
-  text-decoration: none;
-}
-
-a:active {
-  color: #53C20D;
-  text-decoration: underline;
-}
-
-pre {
-  background-color: #FFFFFF;
-  padding-top: 10px;
-  padding-right: 25px;
-  padding-left: 25px;
-  padding-bottom: 10px;
-  border: 3px solid #000;
-  border-radius: 10px;
-}
-
-code {
-  background-color: #FFFFFF;
-  font-family: Pointfree, monospace;
-  font-size: 0.8em;
-}
-
-#container {
-  margin: 0 auto;
-  width: 32.0em;
-  padding: 2.0em;
-  background-color: #E3E3E3;
-  border: 3px solid #000;
-  border-radius: 10px;
-  box-shadow: 0 0 10px 2px #5A5A5A;
-}


Modified: markdown/templates/Alternate/background.png
0 files changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: markdown/templates/Alternate/index.html
10 files changed, 0 insertions(+), 10 deletions(-)
===================================================================
@@ -1,10 +0,0 @@
-<html>
-  <head>
-    <link rel="stylesheet" type="text/css" href="alternate.css"/>
-  </head>
-  <body>
-    <div id="container">
-      <!-- @markdown_document@ -->
-    </div>
-  </body>
-</html>


Modified: markdown/templates/Default/Makefile.am
3 files changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -1,3 +0,0 @@
-
-deftmpldir = $(pkgdatadir)/markdown/templates/Default
-deftmpl_DATA = index.html


Modified: markdown/templates/Default/index.html
5 files changed, 0 insertions(+), 5 deletions(-)
===================================================================
@@ -1,5 +0,0 @@
-<html>
-  <body>
-    <!-- @markdown_document@ -->
-  </body>
-</html>


Modified: markdown/templates/Makefile.am
1 files changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +0,0 @@
-SUBDIRS = Default Alternate


@@ Diff output truncated at 100000 characters. @@


--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).



More information about the Plugins-Commits mailing list