gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Thu Jul 13 20:12:18 EDT 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/f28ea50a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8655dbc5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/85d868f8 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cb06e0e7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b9cb2a22 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1f31ca62 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3d12dd9c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9f844fe3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/890f6993 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/55a30978 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9d2a4b2e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/92549209 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4774332f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/489d0513 (commit)
	from  https://github.com/Gnucash/gnucash/commit/48948c5c (commit)



commit f28ea50aaf30990a173bafcb37881bceb1e6ec70
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jul 11 08:53:20 2017 -0700

    Conditionally build for Webkit1 on Win32 and Webkit2 everywhere else.

diff --git a/src/html/CMakeLists.txt b/src/html/CMakeLists.txt
index e9fd16a..f2aec95 100644
--- a/src/html/CMakeLists.txt
+++ b/src/html/CMakeLists.txt
@@ -4,9 +4,9 @@ SET (html_HEADERS
   gnc-html.h
   gnc-html-p.h
   gnc-html-factory.h
-  gnc-html-webkit.h
   gnc-html-extras.h
   gnc-html-webkit-p.h
+  gnc-html-webkit.h
 )
 
 IF (BUILDING_FROM_VCS)
@@ -21,9 +21,16 @@ SET (html_SOURCES
   gnc-html.c
   gnc-html-history.c
   gnc-html-factory.c
-  gnc-html-webkit.c
 )
 
+IF (WEBKIT1)
+  LIST(APPEND html_HEADERS gnc-html-webkit1.h)
+  LIST(APPEND html_SOURCES gnc-html-webkit1.c)
+ELSE ()
+  LIST(APPEND html_HEADERS gnc-html-webkit2.h)
+  LIST(APPEND html_SOURCES gnc-html-webkit2.c)
+ENDIF ()
+
 SET_DIST_LIST(html_DIST CMakeLists.txt Makefile.am ${html_HEADERS} ${html_SOURCES} gnc-html.i)
 
 ADD_LIBRARY (gncmod-html
diff --git a/src/html/gnc-html-webkit.h b/src/html/gnc-html-webkit.h
index c2cec58..6fd443d 100644
--- a/src/html/gnc-html-webkit.h
+++ b/src/html/gnc-html-webkit.h
@@ -1,6 +1,6 @@
 /********************************************************************
  * gnc-html-webkit.h -- display html with gnc special tags          *
- * Copyright (C) 2009 Phil Longstaff <plongstaff at rogers.com>        *
+ * Copyright (C) 2017 John Ralls <jralls at ceridwen.us>               *
  *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
@@ -20,42 +20,9 @@
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
 
-#ifndef GNC_HTML_WEBKIT_H
-#define GNC_HTML_WEBKIT_H
-
-#include <glib-object.h>
-#include "gnc-html.h"
-
-G_BEGIN_DECLS
-
-#define GNC_TYPE_HTML_WEBKIT       (gnc_html_webkit_get_type())
-#define GNC_HTML_WEBKIT(o)         (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_HTML_WEBKIT, GncHtmlWebkit))
-#define GNC_HTML_WEBKIT_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_HTML_WEBKIT, GncHtmlWebkitClass))
-#define GNC_IS_HTML_WEBKIT(o)      (G_TYPE_CHECK_INSTANCE_TYPE((o), GNC_TYPE_HTML_WEBKIT))
-#define GNC_IS_HTML_WEBKIT_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE((k), GNC_TYPE_HTML_WEBKIT))
-#define GNC_HTML_WEBKIT_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS((o), GNC_TYPE_HTML_WEBKIT, GncHtmlWebkitClass))
-
-typedef struct _GncHtmlWebkit GncHtmlWebkit;
-typedef struct _GncHtmlWebkitClass GncHtmlWebkitClass;
-typedef struct _GncHtmlWebkitPrivate GncHtmlWebkitPrivate;
-
-struct _GncHtmlWebkit
-{
-    GncHtml parent_instance;
-
-    /*< private >*/
-    GncHtmlWebkitPrivate* priv;
-};
-
-struct _GncHtmlWebkitClass
-{
-    GncHtmlClass parent_class;
-};
-
-GType gnc_html_webkit_get_type( void );
-
-GncHtml* gnc_html_webkit_new( void );
-
-G_END_DECLS
-
+#include <config.h>
+#ifdef WEBKIT1
+#include "gnc-html-webkit1.h"
+#else
+#include "gnc-html-webkit2.h"
 #endif
diff --git a/src/html/gnc-html-webkit1.c b/src/html/gnc-html-webkit1.c
new file mode 100644
index 0000000..b7b1570
--- /dev/null
+++ b/src/html/gnc-html-webkit1.c
@@ -0,0 +1,1318 @@
+/********************************************************************
+ * gnc-html-webkit.c -- gnucash report renderer using webkit        *
+ *                                                                  *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * Copyright (C) 2001 Linas Vepstas <linas at linas.org>               *
+ * Copyright (C) 2009 Phil Longstaff <plongstaff at rogers.com>        *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ ********************************************************************/
+
+#include "config.h"
+#include "platform.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <regex.h>
+
+#include <webkit/webkit.h>
+
+#include "Account.h"
+#include "gnc-prefs.h"
+#include "gnc-gui-query.h"
+#include "gnc-engine.h"
+#include "gnc-html.h"
+#include "gnc-html-webkit.h"
+#include "gnc-html-history.h"
+#include "print-session.h"
+
+G_DEFINE_TYPE(GncHtmlWebkit, gnc_html_webkit, GNC_TYPE_HTML )
+
+static void gnc_html_webkit_dispose( GObject* obj );
+static void gnc_html_webkit_finalize( GObject* obj );
+static void gnc_html_webkit_class_init( GncHtmlWebkitClass* klass );
+static void gnc_html_webkit_init( GncHtmlWebkit* gs );
+
+#define GNC_HTML_WEBKIT_GET_PRIVATE(o) (GNC_HTML_WEBKIT(o)->priv)
+
+#include "gnc-html-webkit-p.h"
+
+/* indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_HTML;
+
+/* hashes for URLType -> protocol and protocol -> URLType */
+//extern GHashTable* gnc_html_type_to_proto_hash;
+//extern GHashTable* gnc_html_proto_to_type_hash;
+
+/* hashes an HTML <object classid="ID"> classid to a handler function */
+extern GHashTable* gnc_html_object_handlers;
+
+/* hashes handlers for loading different URLType data */
+extern GHashTable* gnc_html_stream_handlers;
+
+/* hashes handlers for handling different URLType data */
+extern GHashTable* gnc_html_url_handlers;
+
+static char error_404_format[] = "<html><body><h3>%s</h3><p>%s</body></html>";
+static char error_404_title[] = N_("Not found");
+static char error_404_body[] = N_("The specified URL could not be loaded.");
+
+#define BASE_URI_NAME "base-uri"
+#define GNC_PREF_RPT_DFLT_ZOOM "default-zoom"
+
+static WebKitNavigationResponse webkit_navigation_requested_cb(
+    WebKitWebView* web_view,
+    WebKitWebFrame* frame,
+    WebKitNetworkRequest* request,
+    gpointer user_data );
+static void webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url,
+                              gpointer data );
+static gchar* handle_embedded_object( GncHtmlWebkit* self, gchar* html_str );
+#if 0
+static void gnc_html_set_base_cb( GtkHTML* gtkhtml, const gchar* base, gpointer data );
+static void gnc_html_link_clicked_cb( GtkHTML* html, const gchar* url, gpointer data );
+static gboolean gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
+        gpointer data );
+#endif
+#if 0 /* Not Used */
+static int gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
+                                     gpointer user_data );
+#endif /* Not Used */
+static void impl_webkit_show_url( GncHtml* self, URLType type,
+                                  const gchar* location, const gchar* label,
+                                  gboolean new_window_hint );
+static void impl_webkit_show_data( GncHtml* self, const gchar* data, int datalen );
+static void impl_webkit_reload( GncHtml* self, gboolean force_rebuild );
+static void impl_webkit_copy_to_clipboard( GncHtml* self );
+static gboolean impl_webkit_export_to_file( GncHtml* self, const gchar* filepath );
+static void impl_webkit_print( GncHtml* self, const gchar* jobname, gboolean export_pdf );
+static void impl_webkit_cancel( GncHtml* self );
+static void impl_webkit_set_parent( GncHtml* self, GtkWindow* parent );
+static void impl_webkit_default_zoom_changed(gpointer prefs, gchar *pref, gpointer user_data);
+
+static void
+gnc_html_webkit_init( GncHtmlWebkit* self )
+{
+    GncHtmlWebkitPrivate* priv;
+    GncHtmlWebkitPrivate* new_priv;
+
+    WebKitWebSettings* webkit_settings = NULL;
+    const char* default_font_family = NULL;
+    gdouble zoom = 1.0;
+
+    new_priv = g_realloc( GNC_HTML(self)->priv, sizeof(GncHtmlWebkitPrivate) );
+    priv = self->priv = new_priv;
+    GNC_HTML(self)->priv = (GncHtmlPrivate*)priv;
+
+    priv->html_string = NULL;
+    priv->web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+
+
+    /* Get the default font family from GtkStyle of a GtkWidget(priv-web_view). */
+    default_font_family = pango_font_description_get_family( gtk_rc_get_style(GTK_WIDGET(priv->web_view))->font_desc );
+
+    /* Set default webkit settings */
+    webkit_settings = webkit_web_view_get_settings (priv->web_view);
+    g_object_set (G_OBJECT(webkit_settings), "default-encoding", "utf-8", NULL);
+    if (default_font_family == NULL)
+    {
+        PWARN("webkit_settings: Cannot get default font family.");
+    }
+    else
+    {
+        g_object_set (G_OBJECT(webkit_settings),
+                      "default-font-family", default_font_family,
+                      NULL);
+        PINFO("webkit_settings: Set default font to [%s]", default_font_family);
+    }
+    /* Scale everything up */
+    zoom = gnc_prefs_get_float (GNC_PREFS_GROUP_GENERAL_REPORT, GNC_PREF_RPT_DFLT_ZOOM);
+    webkit_web_view_set_full_content_zoom (priv->web_view, TRUE);
+    webkit_web_view_set_zoom_level (priv->web_view, zoom);
+
+
+    gtk_container_add( GTK_CONTAINER(priv->base.container),
+                       GTK_WIDGET(priv->web_view) );
+
+    g_object_ref_sink( priv->base.container );
+
+    /* signals */
+    g_signal_connect( priv->web_view, "navigation-requested",
+                      G_CALLBACK(webkit_navigation_requested_cb),
+                      self);
+
+    g_signal_connect( priv->web_view, "hovering-over-link",
+                      G_CALLBACK(webkit_on_url_cb),
+                      self );
+
+#if 0
+    g_signal_connect( priv->html, "set_base",
+                      G_CALLBACK(gnc_html_set_base_cb),
+                      self);
+
+    g_signal_connect(priv->html, "link_clicked",
+                     G_CALLBACK(gnc_html_link_clicked_cb),
+                     self);
+
+    g_signal_connect (priv->html, "object_requested",
+                      G_CALLBACK (gnc_html_object_requested_cb),
+                      self);
+
+    g_signal_connect (priv->html, "button_press_event",
+                      G_CALLBACK (gnc_html_button_press_cb),
+                      self);
+
+    g_signal_connect (priv->html, "submit",
+                      G_CALLBACK(gnc_html_submit_cb),
+                      self);
+#endif
+
+    gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL_REPORT,
+            GNC_PREF_RPT_DFLT_ZOOM,
+            impl_webkit_default_zoom_changed,
+                           self);
+
+    LEAVE("retval %p", self);
+}
+
+static void
+gnc_html_webkit_class_init( GncHtmlWebkitClass* klass )
+{
+    GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+    GncHtmlClass* html_class = GNC_HTML_CLASS(klass);
+
+    gobject_class->dispose = gnc_html_webkit_dispose;
+    gobject_class->finalize = gnc_html_webkit_finalize;
+
+    html_class->show_url = impl_webkit_show_url;
+    html_class->show_data = impl_webkit_show_data;
+    html_class->reload = impl_webkit_reload;
+    html_class->copy_to_clipboard = impl_webkit_copy_to_clipboard;
+    html_class->export_to_file = impl_webkit_export_to_file;
+    html_class->print = impl_webkit_print;
+    html_class->cancel = impl_webkit_cancel;
+    html_class->set_parent = impl_webkit_set_parent;
+}
+
+static void
+gnc_html_webkit_dispose( GObject* obj )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(obj);
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    if ( priv->web_view != NULL )
+    {
+        gtk_container_remove( GTK_CONTAINER(priv->base.container),
+                              GTK_WIDGET(priv->web_view) );
+        priv->web_view = NULL;
+    }
+
+    if ( priv->html_string != NULL )
+    {
+        g_free( priv->html_string );
+        priv->html_string = NULL;
+    }
+
+    gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL_REPORT,
+            GNC_PREF_RPT_DFLT_ZOOM,
+            impl_webkit_default_zoom_changed,
+                                 obj);
+
+    G_OBJECT_CLASS(gnc_html_webkit_parent_class)->dispose( obj );
+}
+
+static void
+gnc_html_webkit_finalize( GObject* obj )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(obj);
+
+//	if( self->priv != NULL ) {
+//		g_free( self->priv );
+    self->priv = NULL;
+//	}
+
+    G_OBJECT_CLASS(gnc_html_webkit_parent_class)->finalize( obj );
+}
+
+/*****************************************************************************/
+
+static char*
+extract_base_name(URLType type, const gchar* path)
+{
+    gchar       machine_rexp[] = "^(//[^/]*)/*(/.*)?$";
+    gchar       path_rexp[] = "^/*(.*)/+([^/]*)$";
+    regex_t    compiled_m, compiled_p;
+    regmatch_t match[4];
+    gchar       * machine = NULL, * location = NULL, * base = NULL;
+    gchar       * basename = NULL;
+
+    DEBUG(" ");
+    if (!path) return NULL;
+
+    regcomp(&compiled_m, machine_rexp, REG_EXTENDED);
+    regcomp(&compiled_p, path_rexp, REG_EXTENDED);
+
+    if (!g_strcmp0 (type, URL_TYPE_HTTP) ||
+            !g_strcmp0 (type, URL_TYPE_SECURE) ||
+            !g_strcmp0 (type, URL_TYPE_FTP))
+    {
+
+        /* step 1: split the machine name away from the path
+         * components */
+        if (!regexec(&compiled_m, path, 4, match, 0))
+        {
+            /* $1 is the machine name */
+            if (match[1].rm_so != -1)
+            {
+                machine = g_strndup(path + match[1].rm_so,
+                                    match[1].rm_eo - match[1].rm_so);
+            }
+            /* $2 is the path */
+            if (match[2].rm_so != -1)
+            {
+                location = g_strndup(path + match[2].rm_so,
+                                     match[2].rm_eo - match[2].rm_so);
+            }
+        }
+
+    }
+    else
+    {
+        location = g_strdup(path);
+    }
+    /* step 2: split up the path into prefix and file components */
+    if (location)
+    {
+        if (!regexec(&compiled_p, location, 4, match, 0))
+        {
+            if (match[1].rm_so != -1)
+            {
+                base = g_strndup(location + match[1].rm_so,
+                                 match[1].rm_eo - match[1].rm_so);
+            }
+            else
+            {
+                base = NULL;
+            }
+        }
+    }
+
+    regfree(&compiled_m);
+    regfree(&compiled_p);
+
+    if (machine)
+    {
+        if (base && (strlen(base) > 0))
+        {
+            basename = g_strconcat(machine, "/", base, "/", NULL);
+        }
+        else
+        {
+            basename = g_strconcat(machine, "/", NULL);
+        }
+    }
+    else
+    {
+        if (base && (strlen(base) > 0))
+        {
+            basename = g_strdup(base);
+        }
+        else
+        {
+            basename = NULL;
+        }
+    }
+
+    g_free(machine);
+    g_free(base);
+    g_free(location);
+    return basename;
+}
+
+static gboolean
+http_allowed()
+{
+    return TRUE;
+}
+
+static gboolean
+https_allowed()
+{
+    return TRUE;
+}
+
+static gchar*
+handle_embedded_object( GncHtmlWebkit* self, gchar* html_str )
+{
+    // Find the <object> tag and get the classid from it.  This will provide the correct
+    // object callback handler.  Pass the <object> entity text to the handler.  What should
+    // come back is embedded image information.
+    gchar* remainder_str = html_str;
+    gchar* object_tag;
+    gchar* end_object_tag;
+    gchar* object_contents;
+    gchar* html_str_start = NULL;
+    gchar* html_str_middle;
+    gchar* html_str_result = NULL;
+    gchar* classid_start;
+    gchar* classid_end;
+    gchar* classid_str;
+    gchar* new_chunk;
+    GncHTMLObjectCB h;
+
+    object_tag = g_strstr_len( remainder_str, -1, "<object classid=" );
+    while (object_tag)
+    {
+
+        classid_start = object_tag + strlen( "<object classid=" ) + 1;
+        classid_end = g_strstr_len( classid_start, -1, "\"" );
+        classid_str = g_strndup( classid_start, (classid_end - classid_start) );
+
+        end_object_tag = g_strstr_len( object_tag, -1, "</object>" );
+        if ( end_object_tag == NULL )
+        {
+            /*  Hmmm... no object end tag
+                Return the original html string because we can't properly parse it */
+            g_free (classid_str);
+            g_free (html_str_result);
+            return g_strdup (html_str);
+        }
+        end_object_tag += strlen( "</object>" );
+        object_contents = g_strndup( object_tag, (end_object_tag - object_tag) );
+
+        h = g_hash_table_lookup( gnc_html_object_handlers, classid_str );
+        if ( h != NULL )
+        {
+            (void)h( GNC_HTML(self), object_contents, &html_str_middle );
+        }
+        else
+        {
+            html_str_middle = g_strdup_printf( "No handler found for classid \"%s\"", classid_str );
+        }
+
+        html_str_start = html_str_result;
+        new_chunk = g_strndup (remainder_str, (object_tag - remainder_str));
+        if (!html_str_start)
+            html_str_result = g_strconcat (new_chunk, html_str_middle, NULL);
+        else
+            html_str_result = g_strconcat (html_str_start, new_chunk, html_str_middle, NULL);
+
+        g_free( html_str_start );
+        g_free( new_chunk );
+        g_free( html_str_middle );
+
+        remainder_str = end_object_tag;
+        object_tag = g_strstr_len( remainder_str, -1, "<object classid=" );
+    }
+
+    if (html_str_result)
+    {
+        html_str_start =  html_str_result;
+        html_str_result = g_strconcat (html_str_start, remainder_str, NULL);
+        g_free (html_str_start);
+    }
+    else
+        html_str_result = g_strdup (remainder_str);
+
+    return html_str_result;
+}
+
+/********************************************************************
+ * load_to_stream : actually do the work of loading the HTML
+ * or binary data referenced by a URL and feeding it into the webkit
+ * widget.
+ ********************************************************************/
+
+static void
+load_to_stream( GncHtmlWebkit* self, URLType type,
+                const gchar* location, const gchar* label )
+{
+    gchar* fdata = NULL;
+    int fdata_len = 0;
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    DEBUG( "type %s, location %s, label %s", type ? type : "(null)",
+           location ? location : "(null)", label ? label : "(null)");
+
+    g_return_if_fail( self != NULL );
+
+    if ( gnc_html_stream_handlers != NULL )
+    {
+        GncHTMLStreamCB stream_handler;
+
+        stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
+        if ( stream_handler )
+        {
+            gboolean ok = stream_handler( location, &fdata, &fdata_len );
+
+            if ( ok )
+            {
+                fdata = fdata ? fdata : g_strdup( "" );
+
+                // Until webkitgtk supports download requests, look for "<object classid="
+                // indicating the beginning of an embedded graph.  If found, handle it
+                if ( g_strstr_len( fdata, -1, "<object classid=" ) != NULL )
+                {
+                    gchar* new_fdata;
+                    new_fdata = handle_embedded_object( self, fdata );
+                    g_free( fdata );
+                    fdata = new_fdata;
+                }
+
+                // Save a copy for export purposes
+                if ( priv->html_string != NULL )
+                {
+                    g_free( priv->html_string );
+                }
+                priv->html_string = g_strdup( fdata );
+                impl_webkit_show_data( GNC_HTML(self), fdata, strlen(fdata) );
+//                webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
+            }
+            else
+            {
+                fdata = fdata ? fdata :
+                        g_strdup_printf( error_404_format,
+                                         _(error_404_title), _(error_404_body) );
+                webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
+            }
+
+            g_free( fdata );
+
+            if ( label )
+            {
+                while ( gtk_events_pending() )
+                {
+                    gtk_main_iteration();
+                }
+                /* No action required: Webkit jumps to the anchor on its own. */
+            }
+
+            return;
+        }
+    }
+
+    do
+    {
+        if ( !g_strcmp0( type, URL_TYPE_SECURE ) ||
+                !g_strcmp0( type, URL_TYPE_HTTP ) )
+        {
+
+            if ( !g_strcmp0( type, URL_TYPE_SECURE ) )
+            {
+                if ( !https_allowed() )
+                {
+                    gnc_error_dialog( priv->base.parent, "%s",
+                                      _("Secure HTTP access is disabled. "
+                                        "You can enable it in the Network section of "
+                                        "the Preferences dialog."));
+                    break;
+                }
+            }
+
+            if ( !http_allowed() )
+            {
+                gnc_error_dialog( priv->base.parent, "%s",
+                                  _("Network HTTP access is disabled. "
+                                    "You can enable it in the Network section of "
+                                    "the Preferences dialog."));
+            }
+            else
+            {
+                gnc_build_url( type, location, label );
+            }
+
+        }
+        else
+        {
+            PWARN( "load_to_stream for inappropriate type\n"
+                   "\turl = '%s#%s'\n",
+                   location ? location : "(null)",
+                   label ? label : "(null)" );
+            fdata = g_strdup_printf( error_404_format,
+                                     _(error_404_title), _(error_404_body) );
+            webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
+            g_free( fdata );
+        }
+
+    }
+    while ( FALSE );
+}
+
+#if 0
+/********************************************************************
+ * gnc_html_link_clicked_cb - called when user left-clicks on html
+ * anchor.
+ ********************************************************************/
+
+static void
+gnc_html_link_clicked_cb( GtkHTML* html, const gchar* url, gpointer data )
+{
+    URLType type;
+    gchar* location = NULL;
+    gchar* label = NULL;
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+
+    DEBUG("Clicked %s", url);
+    type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
+    gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
+    g_free( location );
+    g_free( label );
+}
+#endif
+
+/********************************************************************
+ * webkit_navigation_requested_cb - called when a URL needs to be
+ * loaded within the loading of a page (embedded image).
+ ********************************************************************/
+
+static WebKitNavigationResponse
+webkit_navigation_requested_cb( WebKitWebView* web_view, WebKitWebFrame* frame,
+                                WebKitNetworkRequest* request,
+                                gpointer data )
+{
+    URLType type;
+    gchar* location = NULL;
+    gchar* label = NULL;
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+    const gchar* url = webkit_network_request_get_uri( request );
+
+    ENTER( "requesting %s", url );
+    if ( strcmp( url, BASE_URI_NAME ) == 0 )
+    {
+        LEAVE("URI is %s", BASE_URI_NAME);
+        return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
+    }
+
+    type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
+    if ( strcmp( type, "file" ) == 0 )
+    {
+        LEAVE("URI type is 'file'");
+        return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
+    }
+    gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
+//	load_to_stream( self, type, location, label );
+    g_free( location );
+    g_free( label );
+
+    LEAVE("");
+    return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
+}
+
+#if 0
+/********************************************************************
+ * gnc_html_object_requested_cb - called when an applet needs to be
+ * loaded.
+ ********************************************************************/
+
+static gboolean
+gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
+                              gpointer data )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+    GncHTMLObjectCB h;
+
+    DEBUG( " " );
+    if ( !eb || !(eb->classid) || !gnc_html_object_handlers ) return FALSE;
+
+    h = g_hash_table_lookup( gnc_html_object_handlers, eb->classid );
+    if ( h )
+    {
+        return h( GNC_HTML(self), eb, data );
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+#endif
+
+/********************************************************************
+ * webkit_on_url_cb - called when user rolls over html anchor
+ ********************************************************************/
+
+static void
+webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url, gpointer data )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    DEBUG( "Rollover %s", url ? url : "(null)" );
+    g_free( priv->base.current_link );
+    priv->base.current_link = g_strdup( url );
+    if ( priv->base.flyover_cb )
+    {
+        (priv->base.flyover_cb)( GNC_HTML(self), url, priv->base.flyover_cb_data );
+    }
+}
+
+#if 0
+/********************************************************************
+ * gnc_html_set_base_cb
+ ********************************************************************/
+
+static void
+gnc_html_set_base_cb( GtkHTML* gtkhtml, const gchar* base,
+                      gpointer data )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    URLType type;
+    gchar* location = NULL;
+    gchar* label = NULL;
+
+    DEBUG( "Setting base location to %s", base );
+    type = gnc_html_parse_url( GNC_HTML(self), base, &location, &label );
+
+    g_free( priv->base.base_location );
+    g_free( label );
+
+    priv->base.base_type = type;
+    priv->base.base_location = location;
+}
+#endif
+
+/********************************************************************
+ * gnc_html_button_press_cb
+ * mouse button callback (if any)
+ ********************************************************************/
+
+#if 0 /* Not Used */
+static int
+gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
+                          gpointer user_data )
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    DEBUG( "Button Press" );
+    if ( priv->base.button_cb != NULL )
+    {
+        (priv->base.button_cb)( GNC_HTML(self), event, priv->base.button_cb_data );
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+#endif /* Not Used */
+
+/********************************************************************
+ * gnc_html_open_scm
+ * insert some scheme-generated HTML
+ ********************************************************************/
+
+static void
+gnc_html_open_scm( GncHtmlWebkit* self, const gchar * location,
+                   const gchar * label, int newwin )
+{
+    PINFO("location='%s'", location ? location : "(null)");
+}
+
+
+/********************************************************************
+ * gnc_html_show_data
+ * display some HTML that the creator of the gnc-html got from
+ * somewhere.
+ ********************************************************************/
+
+static void
+impl_webkit_show_data( GncHtml* self, const gchar* data, int datalen )
+{
+    GncHtmlWebkitPrivate* priv;
+#define TEMPLATE_REPORT_FILE_NAME "gnc-report-XXXXXX.html"
+    int fd;
+    gchar* uri;
+    gchar *filename;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+
+    ENTER( "datalen %d, data %20.20s", datalen, data );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    /* Export the HTML to a file and load the file URI.   On Linux, this seems to get around some
+       security problems (otherwise, it can complain that embedded images aren't permitted to be
+       viewed because they are local resources).  On Windows, this allows the embedded images to
+       be viewed (maybe for the same reason as on Linux, but I haven't found where it puts those
+       messages. */
+    filename = g_build_filename(g_get_tmp_dir(), TEMPLATE_REPORT_FILE_NAME, (gchar *)NULL);
+    fd = g_mkstemp( filename );
+    impl_webkit_export_to_file( self, filename );
+    close( fd );
+    uri = g_strdup_printf( "file:///%s", filename );
+    g_free(filename);
+    DEBUG("Loading uri '%s'", uri);
+    webkit_web_view_load_uri( priv->web_view, uri );
+    g_free( uri );
+
+    LEAVE("");
+}
+
+/********************************************************************
+ * gnc_html_show_url
+ *
+ * open a URL.  This is called when the user clicks a link or
+ * for the creator of the gnc_html window to explicitly request
+ * a URL.
+ ********************************************************************/
+
+static void
+impl_webkit_show_url( GncHtml* self, URLType type,
+                      const gchar* location, const gchar* label,
+                      gboolean new_window_hint )
+{
+    GncHTMLUrlCB url_handler;
+    gboolean new_window;
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+    g_return_if_fail( location != NULL );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    /* make sure it's OK to show this URL type in this window */
+    if ( new_window_hint == 0 )
+    {
+        if ( priv->base.urltype_cb )
+        {
+            new_window = !((priv->base.urltype_cb)( type ));
+        }
+        else
+        {
+            new_window = FALSE;
+        }
+    }
+    else
+    {
+        new_window = TRUE;
+    }
+
+    if ( !new_window )
+    {
+        gnc_html_cancel( GNC_HTML(self) );
+    }
+
+    if ( gnc_html_url_handlers )
+    {
+        url_handler = g_hash_table_lookup( gnc_html_url_handlers, type );
+    }
+    else
+    {
+        url_handler = NULL;
+    }
+
+    if ( url_handler )
+    {
+        GNCURLResult result;
+        gboolean ok;
+
+        result.load_to_stream = FALSE;
+        result.url_type = type;
+        result.location = NULL;
+        result.label = NULL;
+        result.base_type = URL_TYPE_FILE;
+        result.base_location = NULL;
+        result.error_message = NULL;
+
+        ok = url_handler( location, label, new_window, &result );
+        if ( !ok )
+        {
+            if ( result.error_message )
+            {
+                gnc_error_dialog( priv->base.parent, "%s", result.error_message );
+            }
+            else
+            {
+                /* %s is a URL (some location somewhere). */
+                gnc_error_dialog( priv->base.parent, _("There was an error accessing %s."), location );
+            }
+
+            if ( priv->base.load_cb )
+            {
+                priv->base.load_cb( GNC_HTML(self), result.url_type,
+                                    location, label, priv->base.load_cb_data );
+            }
+        }
+        else if ( result.load_to_stream )
+        {
+            gnc_html_history_node *hnode;
+            const char *new_location;
+            const char *new_label;
+
+            new_location = result.location ? result.location : location;
+            new_label = result.label ? result.label : label;
+            hnode = gnc_html_history_node_new( result.url_type, new_location, new_label );
+
+            gnc_html_history_append( priv->base.history, hnode );
+
+            g_free( priv->base.base_location );
+            priv->base.base_type = result.base_type;
+            priv->base.base_location =
+                g_strdup( extract_base_name( result.base_type, new_location ) );
+            DEBUG( "resetting base location to %s",
+                   priv->base.base_location ? priv->base.base_location : "(null)" );
+
+            load_to_stream( GNC_HTML_WEBKIT(self), result.url_type,
+                            new_location, new_label );
+
+            if ( priv->base.load_cb != NULL )
+            {
+                priv->base.load_cb( GNC_HTML(self), result.url_type,
+                                    new_location, new_label, priv->base.load_cb_data );
+            }
+        }
+
+        g_free( result.location );
+        g_free( result.label );
+        g_free( result.base_location );
+        g_free( result.error_message );
+
+        return;
+    }
+
+    if ( g_strcmp0( type, URL_TYPE_SCHEME ) == 0 )
+    {
+        gnc_html_open_scm( GNC_HTML_WEBKIT(self), location, label, new_window );
+
+    }
+    else if ( g_strcmp0( type, URL_TYPE_JUMP ) == 0 )
+    {
+        /* Webkit jumps to the anchor on its own */
+    }
+    else if ( g_strcmp0( type, URL_TYPE_SECURE ) == 0 ||
+              g_strcmp0( type, URL_TYPE_HTTP ) == 0 ||
+              g_strcmp0( type, URL_TYPE_FILE ) == 0 )
+    {
+
+        do
+        {
+            if ( g_strcmp0( type, URL_TYPE_SECURE ) == 0 )
+            {
+                if ( !https_allowed() )
+                {
+                    gnc_error_dialog( priv->base.parent, "%s",
+                                      _("Secure HTTP access is disabled. "
+                                        "You can enable it in the Network section of "
+                                        "the Preferences dialog.") );
+                    break;
+                }
+            }
+
+            if ( g_strcmp0( type, URL_TYPE_HTTP ) == 0 )
+            {
+                if ( !http_allowed() )
+                {
+                    gnc_error_dialog( priv->base.parent, "%s",
+                                      _("Network HTTP access is disabled. "
+                                        "You can enable it in the Network section of "
+                                        "the Preferences dialog.") );
+                    break;
+                }
+            }
+
+            priv->base.base_type = type;
+
+            if ( priv->base.base_location != NULL ) g_free( priv->base.base_location );
+            priv->base.base_location = extract_base_name( type, location );
+
+            /* FIXME : handle new_window = 1 */
+            gnc_html_history_append( priv->base.history,
+                                     gnc_html_history_node_new( type, location, label ) );
+            load_to_stream( GNC_HTML_WEBKIT(self), type, location, label );
+
+        }
+        while ( FALSE );
+
+    }
+    else
+    {
+        PERR( "URLType %s not supported.", type );
+    }
+
+    if ( priv->base.load_cb != NULL )
+    {
+        (priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
+    }
+}
+
+
+/********************************************************************
+ * gnc_html_reload
+ * reload the current page
+ * if force_rebuild is TRUE, the report is recreated, if FALSE, report
+ * is reloaded by webkit
+ ********************************************************************/
+
+static void
+impl_webkit_reload( GncHtml* self, gboolean force_rebuild )
+{
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    if ( force_rebuild )
+    {
+        gnc_html_history_node *n = gnc_html_history_get_current( priv->base.history );
+        if ( n != NULL )
+            gnc_html_show_url( self, n->type, n->location, n->label, 0 );
+    }
+    else
+        webkit_web_view_reload( priv->web_view );
+}
+
+
+/********************************************************************
+ * gnc_html_new
+ * create and set up a new webkit widget.
+ ********************************************************************/
+
+GncHtml*
+gnc_html_webkit_new( void )
+{
+    GncHtmlWebkit* self = g_object_new( GNC_TYPE_HTML_WEBKIT, NULL );
+    return GNC_HTML(self);
+}
+
+/********************************************************************
+ * gnc_html_cancel
+ * cancel any outstanding HTML fetch requests.
+ ********************************************************************/
+
+static gboolean
+webkit_cancel_helper(gpointer key, gpointer value, gpointer user_data)
+{
+    g_free(key);
+    g_list_free((GList *)value);
+    return TRUE;
+}
+
+static void
+impl_webkit_cancel( GncHtml* self )
+{
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    /* remove our own references to requests */
+    //gnc_http_cancel_requests( priv->http );
+
+    g_hash_table_foreach_remove( priv->base.request_info, webkit_cancel_helper, NULL );
+}
+
+static void
+impl_webkit_copy_to_clipboard( GncHtml* self )
+{
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    if ( webkit_web_view_can_copy_clipboard( priv->web_view ) )
+    {
+        webkit_web_view_copy_clipboard( priv->web_view );
+    }
+}
+
+/**************************************************************
+ * gnc_html_export_to_file
+ *
+ * @param self GncHtmlWebkit object
+ * @param filepath Where to write the HTML
+ * @return TRUE if successful, FALSE if unsuccessful
+ **************************************************************/
+static gboolean
+impl_webkit_export_to_file( GncHtml* self, const char *filepath )
+{
+    FILE *fh;
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_val_if_fail( self != NULL, FALSE );
+    g_return_val_if_fail( GNC_IS_HTML_WEBKIT(self), FALSE );
+    g_return_val_if_fail( filepath != NULL, FALSE );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    if ( priv->html_string == NULL )
+    {
+        return FALSE;
+    }
+    fh = g_fopen( filepath, "w" );
+    if ( fh != NULL )
+    {
+        gint written;
+        gint len = strlen( priv->html_string );
+
+        written = fwrite( priv->html_string, 1, len, fh );
+        fclose (fh);
+
+        if ( written != len )
+        {
+            return FALSE;
+        }
+
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+/**
+ * Prints the current page.
+ *
+ * If printing on WIN32, in order to prevent the font from being tiny, (see bug #591177),
+ * A GtkPrintOperation object needs to be created so that the unit can be set, and then
+ * webkit_web_frame_print_full() needs to be called to use that GtkPrintOperation.  On
+ * other platforms (specifically linux - not sure about MacOSX), the version of webkit may
+ * not contain the function webkit_web_frame_print_full(), so webkit_web_frame_print() is
+ * called instead (the font size problem doesn't show up on linux).
+ *
+ * @param self HTML renderer object
+ */
+static void
+impl_webkit_print( GncHtml* self, const gchar* jobname, gboolean export_pdf )
+{
+    gchar *export_filename = NULL;
+    GncHtmlWebkitPrivate* priv;
+    WebKitWebFrame* frame;
+    GtkPrintOperation* op = gtk_print_operation_new();
+    GError* error = NULL;
+    GtkPrintSettings *print_settings;
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    frame = webkit_web_view_get_main_frame( priv->web_view );
+
+    gnc_print_operation_init( op, jobname );
+    print_settings = gtk_print_operation_get_print_settings (op);
+    if (!print_settings)
+    {
+        print_settings = gtk_print_settings_new();
+        gtk_print_operation_set_print_settings(op, print_settings);
+    }
+#ifdef G_OS_WIN32
+    gtk_print_operation_set_unit( op, GTK_UNIT_POINTS );
+#endif
+
+    // Make sure to generate a full export filename
+    if (g_str_has_suffix(jobname, ".pdf"))
+    {
+        export_filename = g_strdup(jobname);
+    }
+    else
+    {
+        export_filename = g_strconcat(jobname, ".pdf", NULL);
+    }
+
+    // Two different modes of operation. Either export to PDF, or run the
+    // normal print dialog
+    if (export_pdf)
+    {
+        GtkWidget *dialog;
+        gint result;
+        gchar *export_dirname = NULL;
+        gchar* basename;
+
+        // Before we save the PDF file, we always as the user for the export
+        // file name. We will store the chosen directory in the gtk print settings
+        // as well.
+        dialog = gtk_file_chooser_dialog_new (_("Export to PDF File"),
+                                              NULL,
+                                              GTK_FILE_CHOOSER_ACTION_SAVE,
+                                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                              GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                              NULL);
+        gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+        // Does the jobname look like a valid full file path?
+        basename = g_path_get_basename(jobname);
+        if (strcmp(basename, jobname) != 0)
+        {
+            gchar *tmp_basename;
+            gchar *tmp_dirname = g_path_get_dirname(jobname);
+
+            if (g_file_test(tmp_dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
+            {
+                // Yes, the jobname starts with a directory name that actually
+                // exists. Hence we use this as output directory.
+                export_dirname = tmp_dirname;
+                tmp_dirname = NULL;
+
+                // As the prefix part of the "jobname" is the directory path, we
+                // need to extract the suffix part for the filename.
+                tmp_basename = g_path_get_basename(export_filename);
+                g_free(export_filename);
+                export_filename = tmp_basename;
+            }
+            g_free(tmp_dirname);
+        }
+        g_free(basename);
+
+        // Set the output file name from the given jobname
+        gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(dialog), export_filename);
+
+        // Do we have a stored output directory?
+        if (!export_dirname && gtk_print_settings_has_key(print_settings, GNC_GTK_PRINT_SETTINGS_EXPORT_DIR))
+        {
+            const char* tmp_dirname = gtk_print_settings_get(print_settings,
+                                      GNC_GTK_PRINT_SETTINGS_EXPORT_DIR);
+            // Only use the directory subsequently if it exists.
+            if (g_file_test(tmp_dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
+            {
+                export_dirname = g_strdup(tmp_dirname);
+            }
+        }
+
+        // If we have an already existing directory, propose it now.
+        if (export_dirname)
+        {
+            gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), export_dirname);
+        }
+        g_free(export_dirname);
+
+        result = gtk_dialog_run (GTK_DIALOG (dialog));
+        // Weird. In gtk_dialog_run, the gtk code will run a fstat() on the
+        // proposed new output filename, which of course fails with "file not
+        // found" as this file doesn't exist. It will still show a warning output
+        // in the trace file, though.
+
+        if (result == GTK_RESPONSE_ACCEPT)
+        {
+            // The user pressed "Ok", so use the file name for the actual file output.
+            gchar *dirname;
+            char *tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+            g_free(export_filename);
+            export_filename = tmp;
+
+            // Store the directory part of the file for later
+            dirname = g_path_get_dirname(export_filename);
+            if (g_file_test(dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
+            {
+                gtk_print_settings_set(print_settings, GNC_GTK_PRINT_SETTINGS_EXPORT_DIR, dirname);
+            }
+            g_free(dirname);
+        }
+        gtk_widget_destroy (dialog);
+
+        if (result != GTK_RESPONSE_ACCEPT)
+        {
+            // User pressed cancel - no saving of the PDF file here.
+            g_free(export_filename);
+            g_object_unref( op );
+            return;
+        }
+
+        // This function expects the full filename including (absolute?) path
+        gtk_print_operation_set_export_filename(op, export_filename);
+
+        // Run the "Export to PDF" print operation
+        webkit_web_frame_print_full( frame, op, GTK_PRINT_OPERATION_ACTION_EXPORT, &error );
+    }
+    else
+    {
+
+        // Also store this export file name as output URI in the settings
+        if (gtk_print_settings_has_key(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI))
+        {
+            // Get the previous output URI, extract the directory part, and
+            // append the current filename.
+            const gchar *olduri = gtk_print_settings_get(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
+            gchar *dirname = g_path_get_dirname(olduri);
+            gchar *newuri = (g_strcmp0(dirname, ".") == 0)
+                            ? g_strdup(export_filename)
+                            : g_build_filename(dirname, export_filename, NULL);
+            //g_warning("olduri=%s newuri=%s", olduri, newuri);
+
+            // This function expects the full filename including protocol, path, and name
+            gtk_print_settings_set(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI, newuri);
+
+            g_free(newuri);
+            g_free(dirname);
+        }
+        else
+        {
+            // No stored output URI from the print settings, so just set our export filename
+            gtk_print_settings_set(print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI, export_filename);
+        }
+
+        // Run the normal printing dialog
+        webkit_web_frame_print_full( frame, op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, &error );
+    }
+
+    if ( error != NULL )
+    {
+        GtkWidget* window = gtk_widget_get_toplevel( GTK_WIDGET(priv->web_view) );
+        GtkWidget* dialog = gtk_message_dialog_new( gtk_widget_is_toplevel(window) ? GTK_WINDOW(window) : NULL,
+                            GTK_DIALOG_DESTROY_WITH_PARENT,
+                            GTK_MESSAGE_ERROR,
+                            GTK_BUTTONS_CLOSE,
+                            "%s", error->message );
+        g_error_free( error );
+
+        g_signal_connect( dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+        gtk_widget_show( dialog );
+    }
+
+    // Remember to save the printing settings after this print job
+    gnc_print_operation_save_print_settings(op);
+    g_object_unref( op );
+    g_free(export_filename);
+}
+
+static void
+impl_webkit_set_parent( GncHtml* self, GtkWindow* parent )
+{
+    GncHtmlWebkitPrivate* priv;
+
+    g_return_if_fail( self != NULL );
+    g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
+
+    priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    priv->base.parent = GTK_WIDGET(parent);
+}
+
+static void
+impl_webkit_default_zoom_changed(gpointer prefs, gchar *pref, gpointer user_data)
+{
+    gdouble zoom = 1.0;
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+    GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+    g_return_if_fail(user_data != NULL);
+
+    zoom = gnc_prefs_get_float (GNC_PREFS_GROUP_GENERAL_REPORT, GNC_PREF_RPT_DFLT_ZOOM);
+    webkit_web_view_set_zoom_level (priv->web_view, zoom);
+
+}
diff --git a/src/html/gnc-html-webkit.h b/src/html/gnc-html-webkit1.h
similarity index 100%
copy from src/html/gnc-html-webkit.h
copy to src/html/gnc-html-webkit1.h
diff --git a/src/html/gnc-html-webkit.c b/src/html/gnc-html-webkit2.c
similarity index 100%
rename from src/html/gnc-html-webkit.c
rename to src/html/gnc-html-webkit2.c
diff --git a/src/html/gnc-html-webkit.h b/src/html/gnc-html-webkit2.h
similarity index 100%
copy from src/html/gnc-html-webkit.h
copy to src/html/gnc-html-webkit2.h
diff --git a/src/html/gnc-html.c b/src/html/gnc-html.c
index 2512bb2..6283749 100644
--- a/src/html/gnc-html.c
+++ b/src/html/gnc-html.c
@@ -530,16 +530,24 @@ gnc_html_export_to_file( GncHtml* self, const gchar* filepath )
         return FALSE;
     }
 }
-
+#ifdef WEBKIT1
+void
+gnc_html_print (GncHtml* self, const char *jobname, gboolean export_pdf)
+#else
 void
 gnc_html_print (GncHtml* self)
+#endif
 {
     g_return_if_fail( self != NULL );
     g_return_if_fail( GNC_IS_HTML(self) );
 
     if ( GNC_HTML_GET_CLASS(self)->print != NULL )
     {
+#ifdef WEBKIT1
+      GNC_HTML_GET_CLASS(self)->print (self, jobname, export_pdf);
+#else
         GNC_HTML_GET_CLASS(self)->print (self);
+#endif
     }
     else
     {
diff --git a/src/html/gnc-html.h b/src/html/gnc-html.h
index ca424c5..8f32a3b 100644
--- a/src/html/gnc-html.h
+++ b/src/html/gnc-html.h
@@ -135,7 +135,11 @@ struct _GncHtmlClass
     void (*reload)( GncHtml* html, gboolean force_rebuild );
     void (*copy_to_clipboard)( GncHtml* html );
     gboolean (*export_to_file)( GncHtml* html, const gchar* file );
+#ifdef WEBKIT1
+  void (*print) (GncHtml* html, const gchar* jobname, gboolean export_pdf);
+#else
     void (*print) (GncHtml* html);
+#endif
     void (*cancel)( GncHtml* html );
     URLType (*parse_url)( GncHtml* html, const gchar* url,
                           gchar** url_location, gchar** url_label );
@@ -196,13 +200,25 @@ void gnc_html_copy_to_clipboard( GncHtml* html );
  */
 gboolean gnc_html_export_to_file( GncHtml* html, const gchar* filename );
 
+#ifdef WEBKIT1
+/**
+ * Prints the report.
+ *
+ * @param html GncHtml object
+ * @param jobname A jobname fo identifying the print job or to provide
+ *                an output filename.
+ * @param export_pdf If TRUE write a PDF file using the jobname for a
+ *                   filename; otherwise put up a print dialog.
+ */
+void gnc_html_print (GncHtml* html, const char* jobname, gboolean export_pdf);
+#else
 /**
  * Prints the report.
  *
  * @param html GncHtml object
  */
 void gnc_html_print (GncHtml* html);
-
+#endif
 /**
  * Cancels the current operation
  *
diff --git a/src/report/report-gnome/gnc-plugin-page-report.c b/src/report/report-gnome/gnc-plugin-page-report.c
index 58d1353..c4de711 100644
--- a/src/report/report-gnome/gnc-plugin-page-report.c
+++ b/src/report/report-gnome/gnc-plugin-page-report.c
@@ -1838,7 +1838,11 @@ gnc_plugin_page_report_print_cb( GtkAction *action, GncPluginPageReport *report
 
     //g_warning("Setting job name=%s", job_name);
 
+#ifdef WEBKIT1
+    gnc_html_print (priv->html, job_name, TRUE);
+#else
     gnc_html_print (priv->html);
+#endif
 
     g_free (job_name);
 }
@@ -1877,7 +1881,11 @@ gnc_plugin_page_report_exportpdf_cb( GtkAction *action, GncPluginPageReport *rep
 
     //g_warning("Setting job name=%s", job_name);
 
+#ifdef WEBKIT1
+    gnc_html_print (priv->html, job_name, TRUE);
+#else
     gnc_html_print (priv->html);
+#endif
 
     if (owner)
     {

commit 8655dbc55c7bc127b94c3caa86ae4267ce1ef974
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jul 9 10:04:35 2017 -0700

    Check for package webkitgtk-3.0 (webkit1 API) on Windows.
    
    Webkit2 isn't supported on Windows.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index be5aa4b..e9ead23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -170,17 +170,18 @@ GNC_PKG_CHECK_MODULES (GTHREAD REQUIRED gthread-2.0>=2.20)
 
 GNC_PKG_CHECK_MODULES (LIBXML2 REQUIRED libxml-2.0>=2.7.0)
 GNC_PKG_CHECK_MODULES (LIBXSLT REQUIRED libxslt)
-GNC_PKG_CHECK_MODULES (WEBKIT webkit2gtk-4.0)
-IF (NOT WEBKIT_FOUND)
-  GNC_PKG_CHECK_MODULES (WEBKIT REQUIRED webkit2gtk-3.0)
-  IF (WIN32)
+IF (WIN32)
+    GNC_PKG_CHECK_MODULES (WEBKIT REQUIRED webkitgtk-3.0)
     SET(WEBKIT1 1)
-  ELSE (WIN32)
+ELSE (WIN32)
+  GNC_PKG_CHECK_MODULES (WEBKIT webkit2gtk-4.0)
+  IF (NOT WEBKIT_FOUND)
+    GNC_PKG_CHECK_MODULES (WEBKIT REQUIRED webkit2gtk-3.0)
     SET(WEBKIT2_3 1)
-  ENDIF (WIN32)
-ELSE (NOT WEBKIT_FOUND)
+  ELSE (NOT WEBKIT_FOUND)
     SET(WEBKIT2_4 1)
-ENDIF (NOT WEBKIT_FOUND)
+  ENDIF (NOT WEBKIT_FOUND)
+ENDIF (WIN32)
 
 IF (WITH_GNUCASH)
   GNC_PKG_CHECK_MODULES (GTK3 REQUIRED gtk+-3.0>=3.14.0)

commit 85d868f826ef515a32ab8ed374e42f111fa3f194
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Jul 3 12:17:12 2017 -0700

    Use GStatBuf to match newer GLib API

diff --git a/src/backend/xml/test/test-file-stuff.cpp b/src/backend/xml/test/test-file-stuff.cpp
index a6bbf80..8e99a07 100644
--- a/src/backend/xml/test/test-file-stuff.cpp
+++ b/src/backend/xml/test/test-file-stuff.cpp
@@ -383,7 +383,7 @@ test_files_in_dir (int argc, char** argv, gxpf_callback cb,
 
     for (count = 1; count < argc; count++)
     {
-        struct stat file_info;
+        GStatBuf file_info;
         const char* to_open = argv[count];
         if (g_stat (to_open, &file_info) != 0)
         {
diff --git a/src/backend/xml/test/test-load-xml2.cpp b/src/backend/xml/test/test-load-xml2.cpp
index 3df9861..9d0ce80 100644
--- a/src/backend/xml/test/test-load-xml2.cpp
+++ b/src/backend/xml/test/test-load-xml2.cpp
@@ -31,6 +31,8 @@ extern "C"
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <string.h>
@@ -62,7 +64,7 @@ remove_files_pattern (const char* begining, const char* ending)
 static void
 remove_locks (const char* filename)
 {
-    struct stat buf;
+    GStatBuf buf;
     char* to_remove;
 
     {

commit cb06e0e763c561631d9747dcad5a3cc1a2a2e83b
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:57:22 2017 -0700

    Include winsock2.h before windows.h to silence a compile warning.

diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp
index 380687f..a6978e1 100644
--- a/src/backend/dbi/gnc-backend-dbi.cpp
+++ b/src/backend/dbi/gnc-backend-dbi.cpp
@@ -41,6 +41,7 @@ extern "C"
 #undef _UWIN
 #endif
 #if PLATFORM(WINDOWS)
+#include <winsock2.h>
 #include <windows.h>
 #define __STDC_FORMAT_MACROS 1
 #endif

commit b9cb2a22d5c9369fa00fd014deca46400e441b89
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:56:38 2017 -0700

    Disable Guile's GnuLib broken redefinition of 'close'.
    
    To a GnuLib function that isn't built or installed.

diff --git a/src/app-utils/guile-util.c b/src/app-utils/guile-util.c
index 24c7b7f..043f5c7 100644
--- a/src/app-utils/guile-util.c
+++ b/src/app-utils/guile-util.c
@@ -23,15 +23,22 @@
 #include "swig-runtime.h"
 #include <platform.h>
 #if PLATFORM(WINDOWS)
+#include <winsock.h>
 #include <windows.h>
 #endif
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <string.h>
+#ifdef __MINGW32__
+#define _GL_UNISTD_H //Deflect poisonous define of close in Guile's GnuLib
+#endif
 #include <libguile.h>
 #include <errno.h>
 #ifdef HAVE_UNISTD_H
+# ifdef close
+#  undef close
+# endif
 # include <unistd.h>
 #else
 # include <io.h>
diff --git a/src/gnome-utils/gnc-main-window.c b/src/gnome-utils/gnc-main-window.c
index c60add5..274f52e 100644
--- a/src/gnome-utils/gnc-main-window.c
+++ b/src/gnome-utils/gnc-main-window.c
@@ -76,6 +76,7 @@
 #include <gtkmacintegration/gtkosxapplication.h>
 #endif
 #ifdef HAVE_SYS_STAT_H
+# define __need_system_sys_stat_h //To block Guile-2.0's evil substitute
 # include <sys/types.h>
 # include <sys/stat.h> // for stat(2)
 #endif
diff --git a/src/html/gnc-html-webkit.c b/src/html/gnc-html-webkit.c
index 31b7a93..aae4dde 100644
--- a/src/html/gnc-html-webkit.c
+++ b/src/html/gnc-html-webkit.c
@@ -26,6 +26,9 @@
 #include "config.h"
 
 #include <platform.h>
+#ifdef __MINGW32__
+#define _GL_UNISTD_H //Deflect poisonous define of close in Guile's GnuLib
+#endif
 #include <libguile.h>
 #if PLATFORM(WINDOWS)
 #include <windows.h>
diff --git a/src/report/report-system/gnc-report.c b/src/report/report-system/gnc-report.c
index 40c5090..b491140 100644
--- a/src/report/report-system/gnc-report.c
+++ b/src/report/report-system/gnc-report.c
@@ -23,7 +23,9 @@
  ********************************************************************/
 
 #include "config.h"
-
+#ifdef __MINGW32__
+#define _GL_UNISTD_H //Deflect poisonous define in Guile's GnuLib
+#endif
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <gtk/gtk.h>

commit 1f31ca620e53ba6ddb0d4258e58c5e6d25ebc405
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:45:53 2017 -0700

    Change the dll lookup directory when building with CMake on Win32.

diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in
index bcd435d..71d2e9c 100644
--- a/src/config.h.cmake.in
+++ b/src/config.h.cmake.in
@@ -1,5 +1,7 @@
 /* Template file for processing by the cmake command CONFIGURE_FILE */
 
+/* If we're using this file it's a CMAKE build, so say so */
+#define CMAKE_BUILD 1
 
 /* Define if building universal (internal helper macro) */
 #cmakedefine AC_APPLE_UNIVERSAL_BUILD
diff --git a/src/engine/gnc-engine.c b/src/engine/gnc-engine.c
index 28c8eb6..f732750 100644
--- a/src/engine/gnc-engine.c
+++ b/src/engine/gnc-engine.c
@@ -86,8 +86,17 @@ gnc_engine_init_part2()
     }, *lib;
 
     if (uninstalled)
+#ifdef CMAKE_BUILD
+	pkglibdir = g_build_path (G_DIR_SEPARATOR_S, builddir, NULL);
+#ifdef WIN32
+#define LIBDIR "bin"
+#else
+#define LIBDIR "lib"
+#endif
+#else
         pkglibdir = g_build_path (G_DIR_SEPARATOR_S, builddir,
                                   "src", "backend", NULL);
+#endif
     else
         pkglibdir = gnc_path_get_pkglibdir ();
 
@@ -95,8 +104,12 @@ gnc_engine_init_part2()
     {
         gchar *libdir;
         if (uninstalled)
+#ifdef CMAKE_BUILD
+	    libdir = g_build_path (G_DIR_SEPARATOR_S, pkglibdir, LIBDIR, NULL);
+#else
             libdir = g_build_path (G_DIR_SEPARATOR_S, pkglibdir,
                                    lib->subdir, ".libs", NULL);
+#endif
         else
             libdir = pkglibdir;
         if (qof_load_backend_library(libdir, lib->lib))

commit 3d12dd9cf91e0af96afde79ecd2cc99b6c3afc3f
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:42:15 2017 -0700

    Win32 doesn't use the fake backend links, it just uses the regular dlls.

diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
index af14e11..4bf6add 100644
--- a/src/engine/CMakeLists.txt
+++ b/src/engine/CMakeLists.txt
@@ -181,13 +181,18 @@ SET (engine_SCHEME_1
     engine-utilities.scm
     gnc-numeric.scm
 )
-
-SET(BACKEND_DEPENDS gncmod-backend-xml-link)
-
-
-IF(WITH_SQL)
-  LIST(APPEND BACKEND_DEPENDS gncmod-backend-dbi-link)
-ENDIF(WITH_SQL)
+IF (NOT WIN32)
+  SET(BACKEND_DEPENDS gncmod-backend-xml-link)
+
+  IF(WITH_SQL)
+    LIST(APPEND BACKEND_DEPENDS gncmod-backend-dbi-link)
+  ENDIF(WITH_SQL)
+ELSE (NOT WIN32)
+   SET(BACKEND_DEPENDS gncmod-backend-xml)
+   IF (WITH_SQL)
+      LIST(APPEND BACKEND_DEPENDS gncmod-backend-dbi)
+   ENDIF(WITH_SQL)
+ENDIF (NOT WIN32)
 
 SET(GUILE_MODULES      "")
 SET(GUILE_LOAD_DIRS    src/gnc-module)

commit 9f844fe36263fea21d417b807a16f01f1ebfaee6
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:41:25 2017 -0700

    Link libws32 to the DBI backend on MINGW64

diff --git a/src/backend/dbi/CMakeLists.txt b/src/backend/dbi/CMakeLists.txt
index 949889a..61a5649 100644
--- a/src/backend/dbi/CMakeLists.txt
+++ b/src/backend/dbi/CMakeLists.txt
@@ -30,7 +30,11 @@ ADD_LIBRARY	(gncmod-backend-dbi
   ${backend_dbi_noinst_HEADERS}
 )
 
-TARGET_LINK_LIBRARIES(gncmod-backend-dbi gnc-backend-sql gncmod-engine gnc-qof ${Boost_REGEX_LIBRARY} ${LIBDBI_LIBRARY})
+SET(WINSOCK_LIB "")
+IF(MINGW64)
+  SET(WINSOCK_LIB "-lws2_32")
+ENDIF(MINGW64)
+TARGET_LINK_LIBRARIES(gncmod-backend-dbi gnc-backend-sql gncmod-engine gnc-qof ${GTK2_LDFLAGS} ${Boost_REGEX_LIBRARY} ${LIBDBI_LIBRARY} ${WINSOCK_LIB})
 
 TARGET_COMPILE_DEFINITIONS(gncmod-backend-dbi PRIVATE -DG_LOG_DOMAIN=\"gnc.backend.dbi\")
 

commit 890f69933f6c56669f1640ca6153257d761640d4
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 15 15:39:04 2017 -0700

    Set deprecated-declarations to no-error for WIN32 so that it will work with Guile2.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ddca3e5..be5aa4b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,8 @@ SET(GETTEXT_PACKAGE "gnucash")
 
 # Extra cmake macros
 SET (CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/src/cmake_modules;${CMAKE_MODULE_PATH}")
+# CMake does a non-recursive build that puts the final build product directories in the build root. Some code needs to know this.
+
 INCLUDE (MacroAppendForeach)
 INCLUDE (MacroAddSourceFileCompileFlags)
 INCLUDE (GncAddSwigCommand)
@@ -465,7 +467,7 @@ IF (UNIX)
   SET( CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2")
 ENDIF (UNIX)
 IF (MINGW)
-  SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations  -Wno-unused -std=gnu11")
+  SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations  -Wno-unused -Wno-error=deprecated-declarations -std=gnu11")
   SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWINVER=0x0500 -D_EMULATE_GLIBC=0") # Workaround for bug in gtest on mingw, see https://github.com/google/googletest/issues/893 and https://github.com/google/googletest/issues/920
 ENDIF (MINGW)
 IF (APPLE)

commit 55a30978b3618bbf77cd329d795599ba5e91213e
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Jun 5 14:56:18 2017 -0700

    Replace use of CMAKE_PREFIX_PATH
    
    Because it was assumed that it contains only a single path; it's specified
    to be a semi-colon-separated list of paths.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8016d5..ddca3e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -138,8 +138,9 @@ IF (WIN32)
   #SET(PKG_CONFIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/gnome/bin/pkg-config.exe)
   SET(SWIG_EXECUTABLE swig)
   #SET(SWIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/swig/swig.exe)
-  SET(REGEX_INCLUDE_PATH ${CMAKE_PREFIX_PATH}/mingw32/include)
-  SET(REGEX_LDFLAGS "-L${CMAKE_PREFIX_PATH}/mingw32/lib -lregex")
+  FIND_PATH(REGEX_INCLUDE_PATH regex.h)
+  FIND_PATH(REGEX_LIB_PATH libregex.dll.a)
+  SET(REGEX_LDFLAGS "-L${REGEX_LIB_PATH} -lregex")
   #SET(LIBXSLT_INCLUDE_DIR ${CMAKE_PREFIX_PATH}/libxslt/include)
   #SET(LIBXSLT_XSLTPROC_EXECUTABLE ${CMAKE_PREFIX_PATH}/libxslt/bin/xsltproc)
   # I have not yet debugged the intltool-merge file generation process on Windows.
@@ -710,7 +711,9 @@ INSTALL(CODE
 #For windows, copy in some DLLs from Mingw
 
 IF (WIN32)
-  SET(MINGW_DLLS ${CMAKE_PREFIX_PATH}/mingw32/bin/libstdc++-6.dll ${CMAKE_PREFIX_PATH}/mingw32/bin/libgcc_s_dw2-1.dll)
+  FIND_LIBRARY(LIBSTDC++ libstdc++-6.dll)
+  FIND_LIBRARY(LIBDW2 libgcc_s_dw2-1.dll)
+  SET(MINGW_DLLS ${LIBSTDC++} ${LIBDW2})
   INSTALL(PROGRAMS ${MINGW_DLLS} DESTINATION bin)
   FILE(COPY ${MINGW_DLLS} DESTINATION ${BINDIR_BUILD}
     # Do permissions matter for windows?
diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt
index 70e3775..bd661ce 100644
--- a/src/bin/CMakeLists.txt
+++ b/src/bin/CMakeLists.txt
@@ -149,17 +149,17 @@ IF (WIN32)
     LIST(APPEND CMD_LINES "set PATH=${INSTALL_PATH_ITEM}\;%PATH%\n")
     LIST(APPEND BUILD_CMD_LINES "set PATH=${BUILD_PATH_ITEM}\;%PATH%\n")
   ENDFOREACH(dir)
-
-  FOREACH(dir ${lib_directories})
-    FILE(TO_NATIVE_PATH ${CMAKE_PREFIX_PATH}/${dir}/lib PATH_ITEM)
-    LIST(APPEND CMD_LINES "set PATH=${PATH_ITEM}\;%PATH%\n")
-  ENDFOREACH(dir)
-
-  FOREACH(dir ${bin_directories})
-    FILE(TO_NATIVE_PATH ${CMAKE_PREFIX_PATH}/${dir}/bin PATH_ITEM)
-    LIST(APPEND CMD_LINES "set PATH=${PATH_ITEM}\;%PATH%\n")
-  ENDFOREACH(dir)
-
+  IF (NOT ${MINGW64})
+    FOREACH(dir ${lib_directories})
+      FILE(TO_NATIVE_PATH ${CMAKE_PREFIX_PATH}/${dir}/lib PATH_ITEM)
+      LIST(APPEND CMD_LINES "set PATH=${PATH_ITEM}\;%PATH%\n")
+    ENDFOREACH(dir)
+
+    FOREACH(dir ${bin_directories})
+      FILE(TO_NATIVE_PATH ${CMAKE_PREFIX_PATH}/${dir}/bin PATH_ITEM)
+      LIST(APPEND CMD_LINES "set PATH=${PATH_ITEM}\;%PATH%\n")
+    ENDFOREACH(dir)
+  ENDIF (NOT ${MINGW64})
   SET(CMD_FILE ${CMAKE_CURRENT_BINARY_DIR}/gnucash-launcher.cmd)
   FILE(WRITE ${CMD_FILE} "@echo off\nsetlocal\n\n")
   FOREACH(line ${CMD_LINES})

commit 9d2a4b2ef08beda734514a820e3061ee810ac8b2
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Jun 5 14:52:29 2017 -0700

    [Mingw64] Set command variables correctly for Guile2 compilation.
    
    Mingw-w64 linker uses $PATH instead of $LD_LIBRARY_PATH for finding
    shared libraries. Both the linker and Guile itself need MSys/Unix style
    paths with the drive letter as a top-level directory, forward slashes,
    and separated with ':' while CMake wants Windows-style paths separated
    with ';'.

diff --git a/src/cmake_modules/GncAddSchemeTargets.cmake b/src/cmake_modules/GncAddSchemeTargets.cmake
index 052849a..def3ac3 100644
--- a/src/cmake_modules/GncAddSchemeTargets.cmake
+++ b/src/cmake_modules/GncAddSchemeTargets.cmake
@@ -1,33 +1,76 @@
+# GncAddSchemeTargets.cmake Define a command to compile Scheme programs with Guile
 # Copyright (c) 2015, Rob Gowin
+# Copyright 2017 John Ralls <jralls at ceridwen.us>
+#
+# 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, contact:
+# Free Software Foundation           Voice:  +1-617-542-5942
+# 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+# Boston, MA  02110-1301,  USA       gnu at gnu.org
 
-MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES _GUILE_LOAD_DIRS _GUILE_LIBRARY_DIRS _GUILE_DEPENDS_IN MAKE_LINKS_IN)
-  SET(__DEBUG FALSE)
+#Guile and ltdl require MSYS paths on MinGW-w64; this function transforms them.
+FUNCTION(MAKE_UNIX_PATH PATH)
+    STRING(REGEX REPLACE "^([A-Za-z]):" "/\\1" newpath ${${PATH}})
+    string(REGEX REPLACE "\\\\" "/" newpath ${newpath})
+    SET(${PATH} ${newpath} PARENT_SCOPE)
+ENDFUNCTION()
+
+#PATH variables in the environment are separated by colons, but CMake lists are separated by semicolons. This function transforms the separators.
+FUNCTION(MAKE_UNIX_PATH_LIST PATH)
+    STRING(REPLACE ";" ":" newpath "${${PATH}}")
+    SET(${PATH} ${newpath} PARENT_SCOPE)
+ENDFUNCTION()
+
+FUNCTION(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR
+                                _GUILE_MODULES _GUILE_LOAD_DIRS
+				_GUILE_LIBRARY_DIRS _GUILE_DEPENDS
+				MAKE_LINKS)
+  SET(__DEBUG TRUE)
   IF (__DEBUG)
     MESSAGE("Parameters to COMPILE_SCHEME for target ${_TARGET}")
     MESSAGE("   SOURCE_FILES: ${_SOURCE_FILES}")
     MESSAGE("   GUILE_MODULES: ${_GUILE_MODULES}")
     MESSAGE("   GUILE_LOAD_DIRS: ${_GUILE_LOAD_DIRS}")
     MESSAGE("   GUILE_LIBRARY_DIRS: ${_GUILE_LIBRARY_DIRS}")
-    MESSAGE("   GUILE_DEPENDS_IN: ${_GUILE_DEPENDS_IN}")
+    MESSAGE("   GUILE_DEPENDS: ${_GUILE_DEPENDS}")
+    MESSAGE("   DIRECTORIES: ${BINDIR_BUILD}, ${LIBDIR_BUILD}, ${DATADIR_BUILD}")
   ENDIF(__DEBUG)
   SET(_CMD "create_symlink")
   IF(WIN32)
     SET(_CMD "copy")
   ENDIF(WIN32)
-  SET(MAKE_LINKS ${MAKE_LINKS_IN})
-  SET(_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${_OUTPUT_DIR_IN})
-  SET(_OUTPUT_DIR ${DATADIR_BUILD}/gnucash/scm/${_OUTPUT_DIR_IN})
-  FILE(MAKE_DIRECTORY ${_OUTPUT_DIR})
+  SET(current_srcdir ${CMAKE_CURRENT_SOURCE_DIR})
+  SET(current_bindir ${CMAKE_CURRENT_BINARY_DIR})
+  SET(build_bindir ${BINDIR_BUILD})
+  SET(build_libdir ${LIBDIR_BUILD})
+  SET(build_datadir ${DATADIR_BUILD})
+  IF(MINGW64)
+    MAKE_UNIX_PATH(build_bindir)
+    MAKE_UNIX_PATH(build_libdir)
+    MAKE_UNIX_PATH(build_datadir)
+    MAKE_UNIX_PATH(current_bindir)
+    MAKE_UNIX_PATH(current_srcdir)
+    MAKE_UNIX_PATH(CMAKE_BINARY_DIR)
+    MAKE_UNIX_PATH(CMAKE_SOURCE_DIR)
+  ENDIF(MINGW64)
+
   # For guile 1, we simple link (or copy, for Windows) each source file to the dest directory
   IF(HAVE_GUILE1 OR MAKE_LINKS)
+    SET(_LINK_DIR ${DATADIR_BUILD}/gnucash/scm/${_OUTPUT_DIR})
+    FILE(MAKE_DIRECTORY ${_LINK_DIR})
     SET(_SCHEME_LINKS "")
     FOREACH(scheme_file ${_SOURCE_FILES})
-      SET(_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${scheme_file})
+      SET(_SOURCE_FILE ${current_srcdir}/${scheme_file})
       IF(IS_ABSOLUTE ${scheme_file})
         SET(_SOURCE_FILE ${scheme_file})
       ENDIF()
       GET_FILENAME_COMPONENT(name ${scheme_file} NAME)
-      SET(_OUTPUT_FILE ${_OUTPUT_DIR}/${name})
+      SET(_OUTPUT_FILE ${_LINK_DIR}/${name})
       IF(NOT EXISTS ${_OUTPUT_FILE})
         LIST(APPEND _SCHEME_LINKS ${_OUTPUT_FILE})
         ADD_CUSTOM_COMMAND(
@@ -45,56 +88,31 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES
 
   IF(HAVE_GUILE2)
     # Construct the guile source and compiled load paths
-    SET(_GUILE_LOAD_PATH "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};${CMAKE_BINARY_DIR}/src/scm")  # to pick up generated build-config.scm
-    SET(_GUILE_LOAD_COMPILED_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+
+    SET(_GUILE_LOAD_PATH "${current_srcdir}"
+        "${current_bindir}" "${CMAKE_BINARY_DIR}/src/scm")  # to pick up generated build-config.scm
+    SET(_GUILE_LOAD_COMPILED_PATH "${current_bindir}")
     FOREACH (load_item ${_GUILE_LOAD_DIRS})
-       LIST(APPEND _GUILE_LOAD_PATH ${CMAKE_SOURCE_DIR}/${load_item})
-       LIST(APPEND _GUILE_LOAD_COMPILED_PATH ${CMAKE_BINARY_DIR}/${load_item})
+      LIST(APPEND _GUILE_LOAD_PATH "${CMAKE_SOURCE_DIR}/${load_item}")
     ENDFOREACH(load_item)
 
-    # Construct the LD_LIBRARY_PATH
-    SET(_GUILE_LD_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
-    FOREACH(ld_item ${_GUILE_LIBRARY_DIRS})
-        LIST(APPEND _GUILE_LD_LIBRARY_PATH ${CMAKE_BINARY_DIR}/${ld_item}/${CMAKE_BUILD_TYPE})
-    ENDFOREACH(ld_item)
-
-    # And then the module path
-    SET(_GNC_MODULE_PATH "")
-    FOREACH(module_item ${_GUILE_MODULES})
-      LIST(APPEND _GNC_MODULE_PATH ${CMAKE_BINARY_DIR}/${module_item}/${CMAKE_BUILD_TYPE})
-    ENDFOREACH(module_item)
-
-    # In CMake lists are text strings where the items are separated by semicolons ("a;b;c;d" for example).
-    # Replace the semis with colons to construct the path environment variables
-    STRING(REPLACE ";" ":" _GUILE_LOAD_PATH "${_GUILE_LOAD_PATH}")
-    STRING(REPLACE ";" ":" _GUILE_LOAD_COMPILED_PATH "${_GUILE_LOAD_COMPILED_PATH}")
-    STRING(REPLACE ";" ":" _GUILE_MODULES "{_GUILE_MODULES}")
-    STRING(REPLACE ";" ":" _GUILE_LD_LIBRARY_PATH "${_GUILE_LD_LIBRARY_PATH}")
-    STRING(REPLACE ";" ":" _GNC_MODULE_PATH "${_GNC_MODULE_PATH}")
-
     SET(_GUILE_CACHE_DIR ${LIBDIR_BUILD}/gnucash/scm/ccache/2.0)
-    SET(_GUILE_LOAD_PATH "${CMAKE_CURRENT_SOURCE_DIR}:${DATADIR_BUILD}/gnucash/scm")
-    SET(_GUILE_LOAD_COMPILED_PATH ${_GUILE_CACHE_DIR})
-#    SET(_GNC_MODULE_PATH  "${LIBDIR_BUILD}/${CMAKE_BUILD_TYPE}:${LIBDIR_BUILD}/gnucash/${CMAKE_BUILD_TYPE}")
-    SET(_GNC_MODULE_PATH  "")
-    SET(_GUILE_LD_LIBRARY_PATH ${_GNC_MODULE_PATH})
-    IF (__DEBUG)
-      MESSAGE("  ")
-      MESSAGE("   GUILE_LOAD_PATH: ${_GUILE_LOAD_PATH}")
-      MESSAGE("   GUILE_LOAD_COMPILED_PATH: ${_GUILE_LOAD_COMPILED_PATH}")
-      MESSAGE("   GUILE_LD_LIBRARY_PATH: ${_GUILE_LD_LIBRARY_PATH}")
-      MESSAGE("   GNC_MODULE_PATH: ${_GNC_MODULE_PATH}")
-    ENDIF(__DEBUG)
+    SET(_GUILE_LOAD_PATH "${current_srcdir}")
+    IF (MAKE_LINKS)
+      LIST(APPEND _GUILE_LOAD_PATH "${build_datadir}/gnucash/scm")
+    ENDIF()
+    SET(_GUILE_LOAD_COMPILED_PATH ${build_libdir}/gnucash/scm/ccache/2.0)
+
     SET(_TARGET_FILES "")
 
     FOREACH(source_file ${_SOURCE_FILES})
-      SET(guile_depends ${_GUILE_DEPENDS_IN})
+      SET(guile_depends ${_GUILE_DEPENDS})
       GET_FILENAME_COMPONENT(basename ${source_file} NAME_WE)
 
       SET(output_file ${basename}.go)
-      SET(_TMP_OUTPUT_DIR_IN ${_OUTPUT_DIR_IN})
-      IF (_TMP_OUTPUT_DIR_IN)
-        SET(output_file ${_OUTPUT_DIR_IN}/${basename}.go)
+      SET(_TMP_OUTPUT_DIR ${_OUTPUT_DIR})
+      IF (_TMP_OUTPUT_DIR)
+        SET(output_file ${_OUTPUT_DIR}/${basename}.go)
       ENDIF()
       SET(output_file ${_GUILE_CACHE_DIR}/${output_file})
       LIST(APPEND _TARGET_FILES ${output_file})
@@ -110,18 +128,46 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES
       IF (${CMAKE_VERSION} VERSION_GREATER 3.1)
         SET(CMAKE_COMMAND_TMP ${CMAKE_COMMAND} -E env)
       ENDIF()
+      IF (MINGW64)
+	set(fpath "")
+	foreach(dir $ENV{PATH})
+	  MAKE_UNIX_PATH(dir)
+	  set(fpath "${fpath}${dir}:")
+	endforeach(dir)
+        SET(LIBRARY_PATH "PATH=\"${build_bindir}:${fpath}\"")
+      ELSE (MINGW64)
+        SET (LIBRARY_PATH "LD_LIBRARY_PATH=${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}")
+      ENDIF (MINGW64)
+      IF (APPLE)
+        SET (LIBRARY_PATH "DYLD_LIBRARY_PATH=${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}")
+      ENDIF (APPLE)
+      SET(_GNC_MODULE_PATH "")
+      IF(MINGW64)
+	SET(_GNC_MODULE_PATH "${build_bindir}")
+      ELSE(MINGW64)
+        SET(_GNC_MODULE_PATH "${LIBDIR_BUILD}" "${LIBDIR_BUILD}/gnucash" "${GNC_MODULE_PATH}")
+      ENDIF(MINGW64)
+      MAKE_UNIX_PATH_LIST(_GUILE_LOAD_PATH)
+      MAKE_UNIX_PATH_LIST(_GUILE_LOAD_COMPILED_PATH)
+      MAKE_UNIX_PATH_LIST(_GUILE_MODULES)
+      MAKE_UNIX_PATH_LIST(_GUILE_LD_LIBRARY_PATH)
+      MAKE_UNIX_PATH_LIST(_GNC_MODULE_PATH)
+      IF (__DEBUG)
+	MESSAGE("  ")
+	MESSAGE("   LIBRARY_PATH: ${LIBRARY_PATH}")
+	MESSAGE("   GUILE_LOAD_PATH: ${_GUILE_LOAD_PATH}")
+	MESSAGE("   GUILE_LOAD_COMPILED_PATH: ${_GUILE_LOAD_COMPILED_PATH}")
+	MESSAGE("   GNC_MODULE_PATH: ${_GNC_MODULE_PATH}")
+      ENDIF(__DEBUG)
       ADD_CUSTOM_COMMAND(
         OUTPUT ${output_file}
         COMMAND ${CMAKE_COMMAND_TMP}
-           GNC_UNINSTALLED=${_GNC_UNINSTALLED}
+	   ${LIBRARY_PATH}
+           GNC_UNINSTALLED=YES
            GNC_BUILDDIR=${CMAKE_BINARY_DIR}
-           #DYLD_FALLBACK_LIBRARY_PATH=${Boost_LIBRARY_DIRS} # this is hack for OS X
-           LD_LIBRARY_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}"
-           DYLD_LIBRARY_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${_GUILE_LD_LIBRARY_PATH}"
            GUILE_LOAD_PATH=${_GUILE_LOAD_PATH}
            GUILE_LOAD_COMPILED_PATH=${_GUILE_LOAD_COMPILED_PATH}
-           #GNC_MODULE_PATH=${_GNC_MODULE_PATH}
-           GNC_MODULE_PATH="${LIBDIR_BUILD}:${LIBDIR_BUILD}/gnucash:${GNC_MODULE_PATH}"
+           GNC_MODULE_PATH=${_GNC_MODULE_PATH}
            ${GUILE_EXECUTABLE} -e '\(@@ \(guild\) main\)' -s ${GUILD_EXECUTABLE} compile -o ${output_file} ${source_file_abs_path}
         DEPENDS ${guile_depends}
         MAIN_DEPENDENCY ${source_file_abs_path}
@@ -131,8 +177,7 @@ MACRO(GNC_ADD_SCHEME_TARGETS _TARGET _SOURCE_FILES _OUTPUT_DIR_IN _GUILE_MODULES
       MESSAGE("TARGET_FILES are ${_TARGET_FILES}")
     ENDIF(__DEBUG)
     ADD_CUSTOM_TARGET(${_TARGET} ALL DEPENDS ${_TARGET_FILES})
-    INSTALL(FILES ${_TARGET_FILES} DESTINATION ${SCHEME_INSTALLED_CACHE_DIR}/${_OUTPUT_DIR_IN})
-
+    INSTALL(FILES ${_TARGET_FILES} DESTINATION ${SCHEME_INSTALLED_CACHE_DIR}/${_OUTPUT_DIR})
   ENDIF(HAVE_GUILE2)
-  INSTALL(FILES ${_SOURCE_FILES} DESTINATION ${SCHEME_INSTALLED_SOURCE_DIR}/${_OUTPUT_DIR_IN})
-ENDMACRO(GNC_ADD_SCHEME_TARGETS)
+  INSTALL(FILES ${_SOURCE_FILES} DESTINATION ${SCHEME_INSTALLED_SOURCE_DIR}/${_OUTPUT_DIR})
+ENDFUNCTION(GNC_ADD_SCHEME_TARGETS)
diff --git a/src/cmake_modules/GncAddTest.cmake b/src/cmake_modules/GncAddTest.cmake
index 9ccf2b2..b76fd8e 100644
--- a/src/cmake_modules/GncAddTest.cmake
+++ b/src/cmake_modules/GncAddTest.cmake
@@ -9,13 +9,29 @@ FUNCTION(GET_GUILE_ENV)
   LIST(APPEND env "GNC_UNINSTALLED=yes")
   LIST(APPEND env "GNC_BUILDDIR=${CMAKE_BINARY_DIR}")
   LIST(APPEND env "GUILE_WARN_DEPRECATED=no")
-  LIST(APPEND env "GNC_MODULE_PATH=${_GNC_MODULE_PATH}")
   IF (APPLE)
     LIST(APPEND env "DYLD_LIBRARY_PATH=${_GNC_MODULE_PATH}")
   ENDIF()
   IF (UNIX)
     LIST(APPEND env LD_LIBRARY_PATH=${_GNC_MODULE_PATH})
   ENDIF()
+  IF (MINGW64)
+    set(fpath "")
+    set(path $ENV{PATH})
+    list(INSERT path 0 ${CMAKE_BINARY_DIR}/bin)
+    foreach(dir ${path})
+      string(REGEX REPLACE "^([A-Za-z]):" "/\\1" dir ${dir})
+      string(REGEX REPLACE "\\\\" "/" dir ${dir})
+      set(fpath "${fpath}${dir}:")
+    endforeach(dir)
+    LIST(APPEND env "PATH=${fpath}")
+    set(compiled_path "${CMAKE_BINARY_DIR}/lib/gnucash/scm/ccache/2.0")
+    string(REGEX REPLACE "^([A-Za-z]):" "/\\1" compiled_path ${compiled_path})
+    LIST(APPEND env GUILE_LOAD_COMPILED_PATH=${compiled_path})
+  ENDIF(MINGW64)
+  LIST(APPEND env "GNC_MODULE_PATH=${_GNC_MODULE_PATH}")
+  LIST(APPEND env "GUILE=${GUILE_EXECUTABLE}")
+
   IF (NOT WIN32)
     LIST(APPEND env "GUILE_LOAD_COMPILED_PATH=${CMAKE_BINARY_DIR}/lib/gnucash/scm/ccache/2.0")
   ENDIF()
@@ -27,13 +43,20 @@ FUNCTION(GET_GUILE_ENV)
     LIST(APPEND guile_load_paths ${CMAKE_BINARY_DIR}/share/gnucash/scm)
   ENDIF()
   SET(guile_load_path "${guile_load_paths}")
-  IF (WIN32)
+  IF (MINGW64)
+    set(new_path "")
+    FOREACH(load_item ${guile_load_path})
+      string(REGEX REPLACE "^([A-Za-z]):" "/\\1" load_item ${load_item})
+      list(APPEND new_path ${load_item})
+    ENDFOREACH(load_item)
+    set(guile_load_path ${new_path})
+  ENDIF (MINGW64)
+  IF (WIN32 AND NOT MINGW64)
     STRING(REPLACE ";" "\\\\;" GUILE_LOAD_PATH "${guile_load_path}")
   ELSE()
     STRING(REPLACE ";" ":" GUILE_LOAD_PATH "${guile_load_path}")
   ENDIF()
-  LIST(APPEND env "GUILE_LOAD_PATH=${GUILE_LOAD_PATH}")
-  LIST(APPEND env "GUILE=${GUILE_EXECUTABLE}")
+  LIST(APPEND env GUILE_LOAD_PATH=${GUILE_LOAD_PATH})
   SET(GUILE_ENV ${env} PARENT_SCOPE)
 ENDFUNCTION()
 

commit 92549209c0a30f72912a63a8ad5c311d376cf804
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat May 27 12:05:46 2017 -0700

    Fix ENDIF() parameter.
    
    CMake 3.8 complains.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 271ae39..cb067fc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,7 +19,8 @@ ENDIF (WIN32)
 
 IF (NOT WIN32)
   CHECK_INCLUDE_FILES (X11/Xlib.h HAVE_X11_XLIB_H)
-ENDIF (WIN32)
+ENDIF (NOT WIN32)
+
 CHECK_INCLUDE_FILES (dirent.h HAVE_DIRENT_H)
 CHECK_INCLUDE_FILES (dlfcn.h HAVE_DLFCN_H)
 CHECK_INCLUDE_FILES (glob.h HAVE_GLOB_H)

commit 4774332fcb1b58a0c84c7d7e074c7a7020e491f0
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat May 27 12:05:16 2017 -0700

    Add CMake files and .gitattributes to lf-only files.

diff --git a/.gitattributes b/.gitattributes
index 3a130a3..75ddd56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -23,6 +23,7 @@
 *.sh    text eol=lf
 *.svg   text eol=lf
 *.xsl   text eol=lf
+*.cmake test eol=lf
 
 Makefile.TAGS    text eol=lf
 Makevars         text eol=lf
@@ -33,7 +34,8 @@ custom.sh.sample text eol=lf
 glade-fixup      text eol=lf
 gnc-glossary.txt text eol=lf
 gnc-scm-info     text eol=lf
-
+CMakeLists.txt   text eol=lf
+.gitattributes   text eol=lf
 
 # Files that should use CRLF at all times
 *.bat text eol=crlf

commit 489d0513e03262d934b5a0cd5e810a85427b6ebe
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 26 13:51:51 2017 -0700

    Adjustments to build on mingw-64.
    
    Note that there may be some changes here that need to be wrapped with ifdef.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 563a4a6..c8016d5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -135,12 +135,13 @@ IF (WIN32)
   # Setting CMAKE_FRAMEWORK_PATH, which is intended for OS X, is a terrible hack here. But I don't
   # want to mess with CMAKE_PREFIX_PATH.
   SET(CMAKE_FRAMEWORK_PATH "${CMAKE_FRAMEWORK_PATH_TMP}")
-  SET(PKG_CONFIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/gnome/bin/pkg-config.exe)
-  SET(SWIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/swig/swig.exe)
-  SET(REGEX_INCLUDE_PATH ${CMAKE_PREFIX_PATH}/regex/include)
-  SET(REGEX_LDFLAGS "-L${CMAKE_PREFIX_PATH}/regex/lib -lregex")
-  SET(LIBXSLT_INCLUDE_DIR ${CMAKE_PREFIX_PATH}/libxslt/include)
-  SET(LIBXSLT_XSLTPROC_EXECUTABLE ${CMAKE_PREFIX_PATH}/libxslt/bin/xsltproc)
+  #SET(PKG_CONFIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/gnome/bin/pkg-config.exe)
+  SET(SWIG_EXECUTABLE swig)
+  #SET(SWIG_EXECUTABLE ${CMAKE_PREFIX_PATH}/swig/swig.exe)
+  SET(REGEX_INCLUDE_PATH ${CMAKE_PREFIX_PATH}/mingw32/include)
+  SET(REGEX_LDFLAGS "-L${CMAKE_PREFIX_PATH}/mingw32/lib -lregex")
+  #SET(LIBXSLT_INCLUDE_DIR ${CMAKE_PREFIX_PATH}/libxslt/include)
+  #SET(LIBXSLT_XSLTPROC_EXECUTABLE ${CMAKE_PREFIX_PATH}/libxslt/bin/xsltproc)
   # I have not yet debugged the intltool-merge file generation process on Windows.
   SET(NO_INTLTOOL TRUE)
 #Prevent creating a console window on startup.
@@ -226,6 +227,7 @@ FIND_PATH (REGEX_INCLUDE_PATH NAMES regex.h
 		  PATHS /usr/include /opt/gnome/include)
 FIND_LIBRARY (REGEX_LIBRARY NAMES regex)
 IF (WIN32)
+  message(STATUS "Looking for htmlhelp.h and htmlhelp.a in ${HTMLHELP_DIR}")
   FIND_PATH (HTMLHELP_INCLUDE_PATH NAMES htmlhelp.h HINTS ${HTMLHELP_DIR}/include)
   FIND_LIBRARY (HTMLHELP_LIBRARY htmlhelp HINTS ${HTMLHELP_DIR}/lib)
 ENDIF (WIN32)
@@ -708,7 +710,7 @@ INSTALL(CODE
 #For windows, copy in some DLLs from Mingw
 
 IF (WIN32)
-  SET(MINGW_DLLS ${CMAKE_PREFIX_PATH}/mingw/bin/libstdc++-6.dll ${CMAKE_PREFIX_PATH}/mingw/bin/libgcc_s_dw2-1.dll)
+  SET(MINGW_DLLS ${CMAKE_PREFIX_PATH}/mingw32/bin/libstdc++-6.dll ${CMAKE_PREFIX_PATH}/mingw32/bin/libgcc_s_dw2-1.dll)
   INSTALL(PROGRAMS ${MINGW_DLLS} DESTINATION bin)
   FILE(COPY ${MINGW_DLLS} DESTINATION ${BINDIR_BUILD}
     # Do permissions matter for windows?
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 17f3667..271ae39 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -9,11 +9,17 @@ SET (GETTEXT_PACKAGE "gnucash")
 SET(GNOME 1)
 
 IF (WIN32)
-  SET (HAVE_SCANF_I64D 1)
+  IF (MINGW)
+    SET (HAVE_SCANF_LLD 1)
+  ELSE ()
+    SET (HAVE_SCANF_I64D 1)
+  ENDIF ()
   SET (HAVE_HTMLHELPW 1)
 ENDIF (WIN32)
 
-CHECK_INCLUDE_FILES (X11/Xlib.h HAVE_X11_XLIB_H)
+IF (NOT WIN32)
+  CHECK_INCLUDE_FILES (X11/Xlib.h HAVE_X11_XLIB_H)
+ENDIF (WIN32)
 CHECK_INCLUDE_FILES (dirent.h HAVE_DIRENT_H)
 CHECK_INCLUDE_FILES (dlfcn.h HAVE_DLFCN_H)
 CHECK_INCLUDE_FILES (glob.h HAVE_GLOB_H)
@@ -182,4 +188,4 @@ SET_LOCAL_DIST(src_DIST_local CMakeLists.txt Makefile.am ${src_EXTRA_DIST})
 SET(src_DIST ${src_DIST_local} ${app_utils_DIST} ${backend_DIST} ${bin_DIST} ${business_DIST} ${cmake_modules_DIST}
              ${core_utils_DIST} ${debug_DIST} ${doc_DIST} ${engine_DIST} ${gnc_module_DIST} ${gnome_DIST} ${gnome_search_DIST}
              ${gnome_utils_DIST} ${html_DIST} ${import_export_DIST} ${libqof_DIST} ${optional_DIST} ${plugins_DIST} ${pixmaps_DIST} ${python_DIST}
-             ${quotes_DIST} ${register_DIST} ${report_DIST} ${scm_DIST} ${tax_DIST} ${test_core_DIST} PARENT_SCOPE)
\ No newline at end of file
+             ${quotes_DIST} ${register_DIST} ${report_DIST} ${scm_DIST} ${tax_DIST} ${test_core_DIST} PARENT_SCOPE)
diff --git a/src/app-utils/gnc-ui-util.c b/src/app-utils/gnc-ui-util.c
index 05abd1c..1e2eaa4 100644
--- a/src/app-utils/gnc-ui-util.c
+++ b/src/app-utils/gnc-ui-util.c
@@ -22,8 +22,10 @@
 
 #include "config.h"
 
+#ifdef __MINGW32__
+#define __USE_MINGW_ANSI_STDIO 1
+#endif
 #include "gnc-ui-util.h"
-
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
diff --git a/src/app-utils/guile-util.c b/src/app-utils/guile-util.c
index 48d9ea4..24c7b7f 100644
--- a/src/app-utils/guile-util.c
+++ b/src/app-utils/guile-util.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include "swig-runtime.h"
 #include <platform.h>
 #if PLATFORM(WINDOWS)
 #include <windows.h>
@@ -28,7 +29,6 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <string.h>
-#include "swig-runtime.h"
 #include <libguile.h>
 #include <errno.h>
 #ifdef HAVE_UNISTD_H
diff --git a/src/backend/xml/gnc-backend-xml.cpp b/src/backend/xml/gnc-backend-xml.cpp
index d3e2cb2..9acbee8 100644
--- a/src/backend/xml/gnc-backend-xml.cpp
+++ b/src/backend/xml/gnc-backend-xml.cpp
@@ -116,7 +116,7 @@ struct QofXmlBackendProvider : public QofBackendProvider
 bool
 QofXmlBackendProvider::type_check (const char *uri)
 {
-    struct stat sbuf;
+    GStatBuf sbuf;
     int rc;
     FILE* t;
     gchar* filename;
diff --git a/src/backend/xml/gnc-xml-backend.cpp b/src/backend/xml/gnc-xml-backend.cpp
index 88e34fe..2c0ca21 100644
--- a/src/backend/xml/gnc-xml-backend.cpp
+++ b/src/backend/xml/gnc-xml-backend.cpp
@@ -52,7 +52,7 @@ static QofLogModule log_module = GNC_MOD_BACKEND;
 bool
 GncXmlBackend::check_path (const char* fullpath, bool create)
 {
-    struct stat statbuf;
+    GStatBuf statbuf;
     char* dirname = g_path_get_dirname (fullpath);
     /* Again check whether the directory can be accessed */
     auto rc = g_stat (dirname, &statbuf);
@@ -333,7 +333,7 @@ GncXmlBackend::save_may_clobber_data()
 {
     if (m_fullpath.empty())
         return false;
-    struct stat statbuf;
+    GStatBuf statbuf;
     auto rc = g_stat (m_fullpath.c_str(), &statbuf);
     return rc == 0;
 }
@@ -397,7 +397,7 @@ GncXmlBackend::write_to_file (bool make_backup)
                                        gnc_prefs_get_file_save_compressed ()))
     {
         /* Record the file's permissions before g_unlinking it */
-        struct stat statbuf;
+        GStatBuf statbuf;
         auto rc = g_stat (m_fullpath.c_str(), &statbuf);
         if (rc == 0)
         {
@@ -619,7 +619,7 @@ GncXmlBackend::link_or_make_backup (const std::string& orig,
 bool
 GncXmlBackend::get_file_lock ()
 {
-    struct stat statbuf;
+    GStatBuf statbuf;
 #ifndef G_OS_WIN32
     char* pathbuf = NULL, *tmpbuf = NULL;
     size_t pathbuf_size = 0;
@@ -739,7 +739,7 @@ GncXmlBackend::get_file_lock ()
 bool
 GncXmlBackend::backup_file()
 {
-    struct stat statbuf;
+    GStatBuf statbuf;
 
     auto datafile = m_fullpath.c_str();
 
@@ -773,7 +773,7 @@ GncXmlBackend::backup_file()
 void
 GncXmlBackend::remove_old_files ()
 {
-    struct stat lockstatbuf, statbuf;
+    GStatBuf lockstatbuf, statbuf;
 
     if (g_stat (m_lockfile.c_str(), &lockstatbuf) != 0)
         return;
diff --git a/src/core-utils/gnc-filepath-utils.c b/src/core-utils/gnc-filepath-utils.c
index 0462d81..3048297 100644
--- a/src/core-utils/gnc-filepath-utils.c
+++ b/src/core-utils/gnc-filepath-utils.c
@@ -307,7 +307,7 @@ gnc_path_find_localized_html_file (const gchar *file_name)
 static gboolean
 gnc_validate_directory (const gchar *dirname, gboolean create, gchar **msg)
 {
-    struct stat statbuf;
+    GStatBuf statbuf;
     gint rc;
 
     *msg = NULL;
diff --git a/src/core-utils/gnc-gkeyfile-utils.c b/src/core-utils/gnc-gkeyfile-utils.c
index df84309..f58a8eb 100644
--- a/src/core-utils/gnc-gkeyfile-utils.c
+++ b/src/core-utils/gnc-gkeyfile-utils.c
@@ -108,7 +108,6 @@ gnc_key_file_save_to_file (const gchar *filename,
 {
     gchar *contents;
     gint fd;
-    extern int errno;
     gint length;
     ssize_t written;
     gboolean success = TRUE;
diff --git a/src/engine/TransLog.c b/src/engine/TransLog.c
index eca61e1..99546a9 100644
--- a/src/engine/TransLog.c
+++ b/src/engine/TransLog.c
@@ -22,7 +22,9 @@
 \********************************************************************/
 
 #include "config.h"
-
+#ifdef __MINGW32__
+#define __USE_MINGW_ANSI_STDIO 1
+#endif
 #include <errno.h>
 #include <glib.h>
 #include <glib/gstdio.h>
diff --git a/src/gnome/assistant-hierarchy.c b/src/gnome/assistant-hierarchy.c
index ed8dd1e..f9b6155 100644
--- a/src/gnome/assistant-hierarchy.c
+++ b/src/gnome/assistant-hierarchy.c
@@ -25,6 +25,7 @@
 #include "config.h"
 
 #include <platform.h>
+#include <libguile.h>
 #if PLATFORM(WINDOWS)
 #include <windows.h>
 #endif
@@ -230,7 +231,7 @@ gnc_get_ea_locale_dir(const char *top_dir)
     static gchar *default_locale = "C";
     gchar *ret;
     gchar *locale;
-    struct stat buf;
+    GStatBuf buf;
     int i;
 
 #ifdef PLATFORM_WIN32
diff --git a/src/gnome/dialog-sx-from-trans.c b/src/gnome/dialog-sx-from-trans.c
index 5c6a93c..206155d 100644
--- a/src/gnome/dialog-sx-from-trans.c
+++ b/src/gnome/dialog-sx-from-trans.c
@@ -757,7 +757,9 @@ sxftd_update_excal_adapt( GObject *o, gpointer ud )
 void
 gnc_sx_create_from_trans( Transaction *trans )
 {
+#ifndef __MINGW32__
     int errno;
+#endif
     SXFromTransInfo *sxfti = g_new0( SXFromTransInfo, 1);
     GtkBuilder *builder;
     GtkWidget *dialog;
diff --git a/src/html/gnc-html-webkit.c b/src/html/gnc-html-webkit.c
index 9ea2f21..31b7a93 100644
--- a/src/html/gnc-html-webkit.c
+++ b/src/html/gnc-html-webkit.c
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #include <platform.h>
+#include <libguile.h>
 #if PLATFORM(WINDOWS)
 #include <windows.h>
 #endif
@@ -41,7 +42,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <regex.h>
-#include <libguile.h>
 
 #include <webkit2/webkit2.h>
 
diff --git a/src/import-export/aqb/CMakeLists.txt b/src/import-export/aqb/CMakeLists.txt
index de2da9d..30fffec 100644
--- a/src/import-export/aqb/CMakeLists.txt
+++ b/src/import-export/aqb/CMakeLists.txt
@@ -45,15 +45,21 @@ IF(WITH_AQBANKING)
     ${aqbanking_noinst_HEADERS}
   )
 
-
   SET(AQB_EXPORT_SYMBOLS "")
   IF (WIN32)
     SET(AQB_EXPORT_SYMBOLS "-Wl,--export-all-symbols")
   ENDIF()
+  SET(AQB_LIBSTDCXX "")
+  IF (MINGW)
+    SET(AQB_LIBSTDCXX "-lstdc++")
+  ENDIF()
 
- TARGET_LINK_LIBRARIES(gncmod-aqbanking gnc-gnome gncmod-gnome-utils gncmod-generic-import gncmod-register-core
-           gncmod-register-gnome gncmod-ledger-core gncmod-engine gnc-qof ${AQB_EXPORT_SYMBOLS} ${AQBANKING_LDFLAGS} ${GWENHYWFAR_LDFLAGS}
-          ${GWENGUI_GTK2_LDFLAGS} ${GNOME_LDFLAGS} ${KTOBLZCHECK_LDFLAGS})
+  TARGET_LINK_LIBRARIES(gncmod-aqbanking gnc-gnome gncmod-gnome-utils
+         gncmod-generic-import gncmod-register-core
+         gncmod-register-gnome gncmod-ledger-core gncmod-engine
+         gnc-qof ${AQB_EXPORT_SYMBOLS} ${AQBANKING_LDFLAGS}
+         ${GWENHYWFAR_LDFLAGS} ${GWENGUI_GTK2_LDFLAGS}
+         ${GNOME_LDFLAGS} ${KTOBLZCHECK_LDFLAGS} ${AQB_LIBSTDCXX})
 
   TARGET_COMPILE_DEFINITIONS(gncmod-aqbanking PRIVATE -DG_LOG_DOMAIN=\"gnc.import.aqbanking\")
 
diff --git a/src/import-export/qif-imp/assistant-qif-import.c b/src/import-export/qif-imp/assistant-qif-import.c
index 9b423f5..c495b51 100644
--- a/src/import-export/qif-imp/assistant-qif-import.c
+++ b/src/import-export/qif-imp/assistant-qif-import.c
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #include <platform.h>
+#include <libguile.h>
 #if PLATFORM(WINDOWS)
 #include <windows.h>
 #endif
diff --git a/src/report/report-gnome/gnc-plugin-page-report.c b/src/report/report-gnome/gnc-plugin-page-report.c
index 8f86c5e..58d1353 100644
--- a/src/report/report-gnome/gnc-plugin-page-report.c
+++ b/src/report/report-gnome/gnc-plugin-page-report.c
@@ -1471,7 +1471,7 @@ static char *
 gnc_get_export_filename (SCM choice)
 {
     char * filepath;
-    struct stat statbuf;
+    GStatBuf statbuf;
     char * title;
     const gchar * html_type = _("HTML");
     char * type;
diff --git a/src/report/report-system/gnc-report.c b/src/report/report-system/gnc-report.c
index 3001f0f..40c5090 100644
--- a/src/report/report-system/gnc-report.c
+++ b/src/report/report-system/gnc-report.c
@@ -231,7 +231,9 @@ gnc_saved_reports_write_internal (const gchar *file, const gchar *contents, gboo
 {
     gboolean success = TRUE;
     gint fd;
+#ifndef __MINGW32__
     extern int errno;
+#endif
     ssize_t written;
     gint length;
     gint flags = O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_APPEND);



Summary of changes:
 .gitattributes                                     |    4 +-
 CMakeLists.txt                                     |   40 +-
 src/CMakeLists.txt                                 |   13 +-
 src/app-utils/gnc-ui-util.c                        |    4 +-
 src/app-utils/guile-util.c                         |    9 +-
 src/backend/dbi/CMakeLists.txt                     |    6 +-
 src/backend/dbi/gnc-backend-dbi.cpp                |    1 +
 src/backend/xml/gnc-backend-xml.cpp                |    2 +-
 src/backend/xml/gnc-xml-backend.cpp                |   12 +-
 src/backend/xml/test/test-file-stuff.cpp           |    2 +-
 src/backend/xml/test/test-load-xml2.cpp            |    4 +-
 src/bin/CMakeLists.txt                             |   22 +-
 src/cmake_modules/GncAddSchemeTargets.cmake        |  163 ++-
 src/cmake_modules/GncAddTest.cmake                 |   31 +-
 src/config.h.cmake.in                              |    2 +
 src/core-utils/gnc-filepath-utils.c                |    2 +-
 src/core-utils/gnc-gkeyfile-utils.c                |    1 -
 src/engine/CMakeLists.txt                          |   19 +-
 src/engine/TransLog.c                              |    4 +-
 src/engine/gnc-engine.c                            |   13 +
 src/gnome-utils/gnc-main-window.c                  |    1 +
 src/gnome/assistant-hierarchy.c                    |    3 +-
 src/gnome/dialog-sx-from-trans.c                   |    2 +
 src/html/CMakeLists.txt                            |   11 +-
 src/html/gnc-html-webkit.h                         |   45 +-
 src/html/gnc-html-webkit1.c                        | 1318 ++++++++++++++++++++
 src/html/{gnc-html-webkit.h => gnc-html-webkit1.h} |    0
 src/html/{gnc-html-webkit.c => gnc-html-webkit2.c} |    5 +-
 src/html/{gnc-html-webkit.h => gnc-html-webkit2.h} |    0
 src/html/gnc-html.c                                |   10 +-
 src/html/gnc-html.h                                |   18 +-
 src/import-export/aqb/CMakeLists.txt               |   14 +-
 src/import-export/qif-imp/assistant-qif-import.c   |    1 +
 src/report/report-gnome/gnc-plugin-page-report.c   |   10 +-
 src/report/report-system/gnc-report.c              |    6 +-
 35 files changed, 1631 insertions(+), 167 deletions(-)
 create mode 100644 src/html/gnc-html-webkit1.c
 copy src/html/{gnc-html-webkit.h => gnc-html-webkit1.h} (100%)
 rename src/html/{gnc-html-webkit.c => gnc-html-webkit2.c} (99%)
 copy src/html/{gnc-html-webkit.h => gnc-html-webkit2.h} (100%)



More information about the gnucash-changes mailing list