r18003 - gnucash/branches/webkit/src/html - 1) Add initial support for webkit-based reports. Reports seem to display OK, and clicking

Phil Longstaff plongstaff at cvs.gnucash.org
Sat Mar 28 13:33:31 EDT 2009


Author: plongstaff
Date: 2009-03-28 13:33:30 -0400 (Sat, 28 Mar 2009)
New Revision: 18003
Trac: http://svn.gnucash.org/trac/changeset/18003

Added:
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.h
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.c
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.h
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.c
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.h
   gnucash/branches/webkit/src/html/gnc-html-gtkmozembed-p.h
   gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.c
   gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.h
   gnucash/branches/webkit/src/html/gnc-html-webkit-p.h
   gnucash/branches/webkit/src/html/gnc-html-webkit.c
   gnucash/branches/webkit/src/html/gnc-html-webkit.h
Removed:
   gnucash/branches/webkit/src/html/gnc-html-extras.c
   gnucash/branches/webkit/src/html/gnc-html-graph-gog.h
Modified:
   gnucash/branches/webkit/src/html/Makefile.am
   gnucash/branches/webkit/src/html/gnc-html-extras.h
   gnucash/branches/webkit/src/html/gnc-html-factory.c
   gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.c
   gnucash/branches/webkit/src/html/gnc-html-gtkhtml-p.h
   gnucash/branches/webkit/src/html/gnc-html-gtkhtml.c
   gnucash/branches/webkit/src/html/gnc-html-gtkhtml.h
   gnucash/branches/webkit/src/html/gnc-html.c
   gnucash/branches/webkit/src/html/gnc-html.h
Log:
1) Add initial support for webkit-based reports.  Reports seem to display OK, and clicking
on an account name does show the register.  However, charts do not work.
2) Add initial support for gtkmozembed (gecko).  The infrastructure is there, but nothing
works.
3) HTML system uses GNC_HTML env var to select an HTML engine.  If defined as "webkit",
reports will use webkit engine.  If defined as "gtkmozembed", will use gtkmozembed
engine (DON"T USE THIS).  If not defined, defined as "gtkhtml" or anything except
"webkit" or "gtkmozembed", will use the gtkhtml engine.



Modified: gnucash/branches/webkit/src/html/Makefile.am
===================================================================
--- gnucash/branches/webkit/src/html/Makefile.am	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/Makefile.am	2009-03-28 17:33:30 UTC (rev 18003)
@@ -15,30 +15,32 @@
   -I${top_srcdir}/src \
   -I${top_builddir}/src \
   -I${top_srcdir}/lib/libc \
+  -I/usr/include/xulrunner/gtkembedmoz \
+  ${QOF_CFLAGS} \
   ${GLIB_CFLAGS} \
-  ${GLADE_CFLAGS} \
   ${GTK_CFLAGS} \
   ${GNOME_CFLAGS} \
   ${GTKHTML_CFLAGS} \
-  ${GUILE_INCS} \
-  ${QOF_CFLAGS} \
   ${GOFFICE_CFLAGS} \
-  ${LIBGDA_CFLAGS} \
   ${WEBKIT_CFLAGS}
 
 libgncmod_html_la_SOURCES = \
   gnc-html.c \
-  gnc-html-extras.c \
   gnc-html-history.c \
   gnc-html-gtkhtml.c \
   gnc-html-graph-gog-gtkhtml.c \
+  gnc-html-webkit.c \
+  gnc-html-graph-gog-webkit.c \
+  gnc-html-gtkmozembed.c \
+  gnc-html-graph-gog-gtkmozembed.c \
   gnc-html-factory.c \
   swig-gnc-html.c
 
 gncincludedir = ${GNC_INCLUDE_DIR}
 gncinclude_HEADERS = \
-  gnc-html-extras.h \
-  gnc-html-graph-gog.h \
+  gnc-html-graph-gog-gtkhtml.h \
+  gnc-html-graph-gog-webkit.h \
+  gnc-html-graph-gog-gtkmozembed.h \
   gnc-html-history.h \
   gnc-html.h \
   gnc-html-factory.h
@@ -53,18 +55,15 @@
   ${top_builddir}/src/calculation/libgncmod-calculation.la \
   ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
   $(top_builddir)/lib/libc/libc-missing.la \
+  -L/usr/lib/xulrunner -lgtkembedmoz \
   ${GNOME_LIBS} \
   ${GTKHTML_LIBS} \
-  ${GUILE_LIBS} \
   ${GDK_PIXBUF_LIBS} \
-  ${GLADE_LIBS} \
-  ${GUILE_LIBS} \
   ${GLIB_LIBS} \
   ${DB_LIBS} \
   ${QOF_LIBS} \
   ${GOFFICE_LIBS} \
   ${REGEX_LIBS} \
-  ${LIBXML2_LIBS} \
   ${WEBKIT_LIBS}
 
 if BUILDING_FROM_SVN

Deleted: gnucash/branches/webkit/src/html/gnc-html-extras.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-extras.c	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-extras.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -1,362 +0,0 @@
-/********************************************************************
- * gnc-html-extras.c -- display HTML with some special gnucash tags.*
- *                                                                  *
- * 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 <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 "gnc-engine.h"
-#include "gnc-html-extras.h"
-#include "gnc-html-graph-gog.h"
-
-/* indicates the debugging module that this .o belongs to.  */
-static QofLogModule log_module = GNC_MOD_HTML;
-
-/* hashes for URLType -> protocol and protocol -> URLType */
-static GHashTable * gnc_html_type_to_proto_hash = NULL;
-GHashTable * gnc_html_proto_to_type_hash = NULL;
-
-/* Register the URLType if it doesn't already exist.
- * Returns TRUE if successful, FALSE if the type already exists.
- */
-gboolean
-gnc_html_register_urltype( URLType type, const char *protocol )
-{
-  if (!gnc_html_type_to_proto_hash) {
-    gnc_html_type_to_proto_hash = g_hash_table_new (g_str_hash, g_str_equal);
-    gnc_html_proto_to_type_hash = g_hash_table_new (g_str_hash, g_str_equal);
-  }
-  if (!protocol) return FALSE;
-  if (g_hash_table_lookup (gnc_html_type_to_proto_hash, type))
-    return FALSE;
-
-  g_hash_table_insert (gnc_html_type_to_proto_hash, type, (gpointer)protocol);
-  if (*protocol)
-    g_hash_table_insert (gnc_html_proto_to_type_hash, (gpointer)protocol, type);
-
-  return TRUE;
-}
-
-void
-gnc_html_initialize (void)
-{
-  int i;
-  static struct {
-    URLType	type;
-    char *	protocol;
-  } types[] = {
-    { URL_TYPE_FILE, "file" },
-    { URL_TYPE_JUMP, "" },
-    { URL_TYPE_HTTP, "http" },
-    { URL_TYPE_FTP, "ftp" },
-    { URL_TYPE_SECURE, "https" },
-    { URL_TYPE_REGISTER, "gnc-register" },
-    { URL_TYPE_ACCTTREE, "gnc-acct-tree" },
-    { URL_TYPE_REPORT, "gnc-report" },
-    { URL_TYPE_OPTIONS, "gnc-options" },
-    { URL_TYPE_SCHEME, "gnc-scm" },
-    { URL_TYPE_HELP, "gnc-help" },
-    { URL_TYPE_XMLDATA, "gnc-xml" },
-    { URL_TYPE_PRICE, "gnc-price" },
-    { URL_TYPE_BUDGET, "gnc-budget" },
-    { URL_TYPE_OTHER, "" },
-    { NULL, NULL }};
-
-  for (i = 0; types[i].type; i++)
-    gnc_html_register_urltype (types[i].type, types[i].protocol);
-
-  // initialize graphing support
-  gnc_html_graph_gog_init();
-}
-
-char  *
-gnc_build_url (URLType type, const gchar * location, const gchar * label)
-{
-  char * type_name;
-
-  DEBUG(" ");
-  type_name = g_hash_table_lookup (gnc_html_type_to_proto_hash, type);
-  if (!type_name)
-    type_name = "";
-
-  if(label) {
-    return g_strdup_printf("%s%s%s#%s", type_name, (*type_name ? ":" : ""),
-                           (location ? location : ""),
-                           label ? label : "");
-  }
-  else {
-    return g_strdup_printf("%s%s%s", type_name, (*type_name ? ":" : ""),
-                           (location ? location : ""));
-  }
-}
-
-/********************************************************************
- * gnc_html_pack/unpack_form_data
- * convert an encoded arg string to/from a name-value hash table
- ********************************************************************/
-
-GHashTable *
-gnc_html_unpack_form_data(const char * encoding)
-{
-  GHashTable * rv;
-
-  DEBUG(" ");
-  rv = g_hash_table_new(g_str_hash, g_str_equal);
-  gnc_html_merge_form_data(rv, encoding);
-  return rv;
-}
-
-void
-gnc_html_merge_form_data(GHashTable * rv, const char * encoding)
-{
-  char * next_pair = NULL;
-  char * name  = NULL;
-  char * value = NULL;
-  char * extr_name  = NULL;
-  char * extr_value = NULL;
-
-  DEBUG(" ");
-  if(!encoding) {
-    return;
-  }
-  next_pair = g_strdup(encoding);
-
-  while(next_pair) {
-    name = next_pair;
-    if((value = strchr(name, '=')) != NULL) {
-      extr_name = g_strndup(name, value-name);
-      next_pair = strchr(value, '&');
-      if(next_pair) {
-        extr_value = g_strndup(value+1, next_pair-value-1);
-        next_pair++;
-      }
-      else {
-        extr_value = g_strdup(value+1);
-      }
-
-      g_hash_table_insert(rv,
-                          gnc_html_decode_string(extr_name),
-                          gnc_html_decode_string(extr_value));
-      g_free(extr_name);
-      g_free(extr_value);
-    }
-    else {
-      next_pair = NULL;
-    }
-  }
-}
-
-static gboolean
-free_form_data_helper(gpointer k, gpointer v, gpointer user)
-{
-  DEBUG(" ");
-  g_free(k);
-  g_free(v);
-  return TRUE;
-}
-
-void
-gnc_html_free_form_data(GHashTable * d)
-{
-  DEBUG(" ");
-  g_hash_table_foreach_remove(d, free_form_data_helper, NULL);
-  g_hash_table_destroy(d);
-}
-
-static void
-pack_form_data_helper(gpointer key, gpointer val,
-                      gpointer user_data)
-{
-  char * old_str = *(char **)user_data;
-  char * enc_key = gnc_html_encode_string((char *)key);
-  char * enc_val = gnc_html_encode_string((char *)val);
-  char * new_str = NULL;
-
-  DEBUG(" ");
-  if(old_str) {
-    new_str = g_strconcat(old_str, "&", enc_key, "=", enc_val, NULL);
-  }
-  else {
-    new_str = g_strconcat(enc_key, "=", enc_val, NULL);
-  }
-  *(char **)user_data = new_str;
-  g_free(old_str);
-}
-
-char *
-gnc_html_pack_form_data(GHashTable * form_data)
-{
-  char * encoded = NULL;
-  DEBUG(" ");
-  g_hash_table_foreach(form_data, pack_form_data_helper, &encoded);
-  return encoded;
-}
-
-/********************************************************************
- * gnc_html_encode_string
- * RFC 1738 encoding of string for submission with an HTML form.
- * GPL code lifted from gtkhtml.  copyright notice:
- *
- * Copyright (C) 1997 Martin Jones (mjones at kde.org)
- * Copyright (C) 1997 Torben Weis (weis at kde.org)
- * Copyright (C) 1999 Helix Code, Inc.
- ********************************************************************/
-
-char *
-gnc_html_encode_string(const char * str)
-{
-  static gchar *safe = "$-._!*(),"; /* RFC 1738 */
-  unsigned pos      = 0;
-  GString *encoded  = g_string_new ("");
-  gchar buffer[5], *ptr;
-  guchar c;
-
-  if(!str) return NULL;
-
-  while(pos < strlen(str)) {
-    c = (unsigned char) str[pos];
-
-    if ((( c >= 'A') && ( c <= 'Z')) ||
-        (( c >= 'a') && ( c <= 'z')) ||
-        (( c >= '0') && ( c <= '9')) ||
-        (strchr(safe, c))) {
-      encoded = g_string_append_c (encoded, c);
-    }
-    else if ( c == ' ' ) {
-      encoded = g_string_append_c (encoded, '+');
-    }
-    else if ( c == '\n' ) {
-      encoded = g_string_append (encoded, "%0D%0A");
-    }
-    else if ( c != '\r' ) {
-      sprintf( buffer, "%%%02X", (int)c );
-      encoded = g_string_append (encoded, buffer);
-    }
-    pos++;
-  }
-
-  ptr = encoded->str;
-
-  g_string_free (encoded, FALSE);
-
-  return (char *)ptr;
-}
-
-
-char *
-gnc_html_decode_string(const char * str)
-{
-  static gchar * safe = "$-._!*(),"; /* RFC 1738 */
-  GString * decoded  = g_string_new ("");
-  const gchar   * ptr;
-  guchar  c;
-  guint   hexval;
-  ptr = str;
-
-  if(!str) return NULL;
-
-  while(*ptr) {
-    c = (unsigned char) *ptr;
-    if ((( c >= 'A') && ( c <= 'Z')) ||
-        (( c >= 'a') && ( c <= 'z')) ||
-        (( c >= '0') && ( c <= '9')) ||
-        (strchr(safe, c))) {
-      decoded = g_string_append_c (decoded, c);
-    }
-    else if ( c == '+' ) {
-      decoded = g_string_append_c (decoded, ' ');
-    }
-    else if (!strncmp(ptr, "%0D0A", 5)) {
-      decoded = g_string_append (decoded, "\n");
-      ptr += 4;
-    }
-    else if(c == '%') {
-      ptr++;
-      if (1 == sscanf(ptr, "%02X", &hexval))
-	decoded = g_string_append_c(decoded, (char)hexval);
-      else
-	decoded = g_string_append_c(decoded, ' ');
-      ptr++;
-    }
-    ptr++;
-  }
-  ptr = decoded->str;
-  g_string_free (decoded, FALSE);
-
-  return (char *)ptr;
-}
-
-/********************************************************************
- * escape/unescape_newlines : very simple string encoding for GPG
- * ASCII-armored text.
- ********************************************************************/
-
-char *
-gnc_html_unescape_newlines(const gchar * in)
-{
-  const char * ip = in;
-  char    * cstr = NULL;
-  GString * rv = g_string_new("");
-
-  for(ip=in; *ip; ip++) {
-    if((*ip == '\\') && (*(ip+1)=='n')) {
-      g_string_append(rv, "\n");
-      ip++;
-    }
-    else {
-      g_string_append_c(rv, *ip);
-    }
-  }
-
-  g_string_append_c(rv, 0);
-  cstr = rv->str;
-  g_string_free(rv, FALSE);
-  return cstr;
-}
-
-char *
-gnc_html_escape_newlines(const gchar * in)
-{
-  char *out;
-  const char * ip   = in;
-  GString * escaped = g_string_new("");
-
-  for(ip=in; *ip; ip++) {
-    if(*ip == '\012') {
-      g_string_append(escaped, "\\n");
-    }
-    else {
-      g_string_append_c(escaped, *ip);
-    }
-  }
-  g_string_append_c(escaped, 0);
-  out = escaped->str;
-  g_string_free(escaped, FALSE);
-  return out;
-}

Modified: gnucash/branches/webkit/src/html/gnc-html-extras.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-extras.h	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-extras.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -23,6 +23,10 @@
 #ifndef GNC_HTML_EXTRAS_H
 #define GNC_HTML_EXTRAS_H
 
+// This file is needed so that these definitions can be separately included in the
+// gnc-html.i file.  The full gnc-html.h file can't be parsed because of the new
+// use of GObject
+
 typedef gchar* URLType;
 
 #define URL_TYPE_FILE	"file"
@@ -43,26 +47,4 @@
 
 gchar* gnc_build_url( URLType type, const gchar* location, const gchar* label );
 
-/* Register a new URLType.
- * returns TRUE if succesful, FALSE if type already exists.
- *
- * protocol should be an empty string if there is no corresponding protocol.
- * if protocol is NULL, this function returns FALSE.
- */
-gboolean gnc_html_register_urltype( URLType type, const gchar* protocol );
-
-/* Initialize the html subsystem */
-void gnc_html_initialize( void );
-
-gchar* gnc_html_encode_string( const gchar* in );
-gchar* gnc_html_decode_string( const gchar* in );
-gchar* gnc_html_escape_newlines( const gchar* in );
-gchar* gnc_html_unescape_newlines( const gchar* in );
-
-/* utilities for dealing with encoded argument strings for forms */
-gchar* gnc_html_pack_form_data( GHashTable* form_data );
-GHashTable* gnc_html_unpack_form_data( const gchar* encoding );
-void gnc_html_merge_form_data( GHashTable* fdata, const gchar* enc );
-void gnc_html_free_form_data( GHashTable* fdata );
-
 #endif

Modified: gnucash/branches/webkit/src/html/gnc-html-factory.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-factory.c	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-factory.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -27,6 +27,8 @@
 
 #include "gnc-html.h"
 #include "gnc-html-gtkhtml.h"
+#include "gnc-html-webkit.h"
+#include "gnc-html-gtkmozembed.h"
 #include "qoflog.h"
 #include "gnc-engine.h"
 
@@ -37,5 +39,17 @@
 
 GncHtml* gnc_html_factory_create_html( void )
 {
-	return GNC_HTML(gnc_html_gtkhtml_new());
+	const gchar* html_type = g_getenv( "GNC_HTML" );
+
+	if( html_type == NULL ) {
+		return gnc_html_gtkhtml_new();
+	} else if( strcmp( html_type, "webkit" ) == 0 ) {
+		return gnc_html_webkit_new();
+	} else if( strcmp( html_type, "gtkhtml" ) == 0 ) {
+		return gnc_html_gtkhtml_new();
+	} else if( strcmp( html_type, "gtkmozembed" ) == 0 ) {
+		return gnc_html_gtkmozembed_new();
+	} else {
+		return gnc_html_gtkhtml_new();
+	}
 }

Modified: gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.c	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -29,7 +29,7 @@
 #include <string.h>
 
 #include "gnc-ui-util.h"
-#include "gnc-html-graph-gog.h"
+#include "gnc-html-graph-gog-gtkhtml.h"
 #include "gnc-html.h"
 #include "gnc-engine.h"
 #include <goffice/goffice.h>
@@ -67,7 +67,7 @@
  **/
 
 #undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "gnc.gui.html.graph.gog"
+#define G_LOG_DOMAIN "gnc.html.graph.gog.gtkhtml"
 
 static int handle_piechart( GncHtml* html, gpointer eb, gpointer d );
 static int handle_barchart( GncHtml* html, gpointer eb, gpointer d );
@@ -90,15 +90,14 @@
 static void set_chart_axis_labels(GogObject *chart, const char *x_axis_label, const char* y_axis_label);
 
 void
-gnc_html_graph_gog_init(void)
+gnc_html_graph_gog_gtkhtml_init( void )
 {
-
   g_debug( "init gog graphing" );
   
   libgoffice_init();
   
   /* Initialize plugins manager */
-  go_plugins_init (NULL, NULL, NULL, NULL, TRUE, GO_PLUGIN_LOADER_MODULE_TYPE);
+  go_plugins_init( NULL, NULL, NULL, NULL, TRUE, GO_PLUGIN_LOADER_MODULE_TYPE );
 
   gnc_html_register_object_handler( "gnc-guppi-pie", handle_piechart );
   gnc_html_register_object_handler( "gnc-guppi-bar", handle_barchart );

Copied: gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.h (from rev 18002, gnucash/branches/webkit/src/html/gnc-html-graph-gog.h)
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkhtml.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,30 @@
+/********************************************************************
+ * gnc-html_graph_gog_gtkhtml.h -- display html with gnc special    *
+ *									tags			                *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_GRAPH_GOG_GTKHTML_H
+#define GNC_HTML_GRAPH_GOG_GTKHTML_H 1
+
+void gnc_html_graph_gog_gtkhtml_init( void );
+
+#endif /* GNC_HTML_GRAPH_GOG_GTKHTML_H */

Added: gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.c	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,822 @@
+/********************************************************************
+ * gnc-html-graph-gog-gtkmozembed.c -- GNC/HTML Graphing support via*
+ *                                     GOG                          *
+ *                                                                  *
+ * Copyright (C) 2005 Joshua Sled <jsled at asynchronous.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 <gtk/gtk.h>
+#include <gtkmozembed.h>
+#include <string.h>
+
+#include "gnc-ui-util.h"
+#include "gnc-html-graph-gog-gtkmozembed.h"
+#include "gnc-html.h"
+#include "gnc-engine.h"
+#include <goffice/goffice.h>
+#include <goffice/graph/gog-chart.h>
+#include <goffice/graph/gog-graph.h>
+#include <goffice/graph/gog-object.h>
+#if defined(HAVE_GOFFICE_0_5)
+#    include <goffice/graph/gog-renderer.h>
+#elif defined(GOFFICE_WITH_CAIRO)
+#    include <goffice/graph/gog-renderer-cairo.h>
+#else
+#    include <goffice/graph/gog-renderer-pixbuf.h>
+#endif
+#ifndef GTKHTML_USES_GTKPRINT
+#    include <goffice/graph/gog-renderer-gnome-print.h>
+#endif
+#include <goffice/graph/gog-style.h>
+#include <goffice/graph/gog-styled-object.h>
+#include <goffice/graph/gog-plot.h>
+#include <goffice/graph/gog-series.h>
+#include <goffice/utils/go-color.h>
+#include <goffice/utils/go-marker.h>
+#include <goffice/graph/gog-data-set.h>
+#include <goffice/data/go-data-simple.h>
+#include <goffice/app/go-plugin.h>
+#include <goffice/app/go-plugin-loader-module.h>
+
+/**
+ * TODO:
+ * - scatter-plot marker selection
+ * - series-color, piecharts (hard, not really supported by GOG)
+ *   and scatters (or drop feature)
+ * - title-string freeing (fixmes)
+ * - general graph cleanup
+ **/
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "gnc.html.graph.gog.gtkmozembed"
+
+static int handle_piechart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_barchart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_linechart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_scatter( GncHtml* html, gpointer eb, gpointer d );
+
+#if 0
+#ifdef GTKHTML_USES_GTKPRINT
+static void draw_print_cb(GtkHTMLEmbedded *eb, cairo_t *cr, gpointer graph);
+#else
+static void draw_print_cb(GtkHTMLEmbedded *eb, GnomePrintContext *context, gpointer graph);
+#endif
+#endif
+
+static gboolean create_basic_plot_elements(const char *plot_type, GogObject **out_graph, GogObject **out_chart, GogPlot **out_plot);
+
+static double * read_doubles(const char * string, int nvalues);
+
+static void set_chart_titles_from_hash(GogObject *chart, gpointer eb);
+static void set_chart_titles(GogObject *chart, const char *title, const char* sub_title);
+static void set_chart_axis_labels_from_hash(GogObject *chart, gpointer eb);
+static void set_chart_axis_labels(GogObject *chart, const char *x_axis_label, const char* y_axis_label);
+
+void
+gnc_html_graph_gog_gtkmozembed_init( void )
+{
+  g_debug( "init gog graphing" );
+  
+  libgoffice_init();
+  
+  /* Initialize plugins manager */
+  go_plugins_init( NULL, NULL, NULL, NULL, TRUE, GO_PLUGIN_LOADER_MODULE_TYPE );
+
+  gnc_html_register_object_handler( "gnc-guppi-pie", handle_piechart );
+  gnc_html_register_object_handler( "gnc-guppi-bar", handle_barchart );
+  gnc_html_register_object_handler( "gnc-guppi-scatter", handle_scatter );
+  gnc_html_register_object_handler( "gnc-guppi-line", handle_linechart );
+}
+
+static double * 
+read_doubles(const char * string, int nvalues)
+{
+  int    n;
+  gchar *next;
+  double * retval = g_new0(double, nvalues);
+
+  // guile is going to (puts ...) the elements of the double array
+  // together. In non-POSIX locales, that will be in a format that
+  // the locale-specific sscanf will not be able to parse.
+  gnc_push_locale("C");
+  {
+    for (n=0; n<nvalues; n++) {
+      retval[n] = strtod(string, &next);
+      string = next;
+     }
+  }
+  gnc_pop_locale();
+
+  return retval;
+}
+
+static char ** 
+read_strings(const char * string, int nvalues)
+{
+  int n;
+  int choffset=0;
+  int accum = 0;
+  char ** retval = g_new0(char *, nvalues);
+  char thischar;
+  const char * inptr = string;
+  int escaped = FALSE;
+
+  for (n=0; n < nvalues; n++) {
+    retval[n] = g_new0(char, strlen(string+accum)+1);
+    retval[n][0] = 0;
+    choffset = 0;
+    while ((thischar = *inptr) != 0) {
+      if (thischar == '\\') {
+        escaped = TRUE;
+        inptr++;
+      }
+      else if ((thischar != ' ') || escaped) {
+        retval[n][choffset] = thischar;
+        retval[n][choffset+1] = 0;    
+        choffset++;
+        escaped = FALSE;
+        inptr++;
+      }
+      else {
+        /* an unescaped space */
+        escaped = FALSE;
+        inptr++;
+        break;
+      }
+    }
+    accum += choffset;
+    /* printf("retval[%d] = '%s'\n", n, retval[n]); */
+  }
+  
+  return retval;  
+}
+
+#if 0
+static void
+add_pixbuf_graph_widget( GtkHTMLEmbedded *eb, GogObject *graph )
+{
+  GtkWidget *widget;
+#if defined(HAVE_GOFFICE_0_5)
+  GogRenderer *renderer;
+#elif defined(GOFFICE_WITH_CAIRO)
+  GogRendererCairo *cairo_renderer;
+#else
+  GogRendererPixbuf *pixbuf_renderer;
+#endif
+  GdkPixbuf *buf;
+  gboolean update_status;
+
+  // Note that this shouldn't be necessary as per discussion with Jody...
+  // ... but it is because we don't embed in a control which passes the
+  // update requests back to the graph widget, a-la the foo-canvas that
+  // gnumeric uses.  We probably _should_ do something like that, though.
+  gog_object_update (GOG_OBJECT (graph));
+
+#if defined(HAVE_GOFFICE_0_5)
+  renderer = GOG_RENDERER (g_object_new (GOG_RENDERER_TYPE,
+					 "model", graph,
+					 NULL));
+  update_status = gog_renderer_update (renderer, eb->width, eb->height);
+  buf = gog_renderer_get_pixbuf (renderer);
+#elif defined(GOFFICE_WITH_CAIRO)
+  cairo_renderer = GOG_RENDERER_CAIRO (g_object_new (GOG_RENDERER_CAIRO_TYPE,
+						     "model", graph,
+						     NULL));
+  update_status = gog_renderer_cairo_update (cairo_renderer,
+					     eb->width, eb->height, 1.0);
+  buf = gog_renderer_cairo_get_pixbuf (cairo_renderer);
+#else
+  pixbuf_renderer = GOG_RENDERER_PIXBUF (g_object_new (GOG_RENDERER_PIXBUF_TYPE,
+						       "model", graph,
+						       NULL));
+  update_status = gog_renderer_pixbuf_update (pixbuf_renderer,
+					      eb->width, eb->height, 1.0);
+  buf = gog_renderer_pixbuf_get (pixbuf_renderer);
+#endif
+
+  widget = gtk_image_new_from_pixbuf (buf);
+  gtk_widget_set_size_request (widget, eb->width, eb->height);
+  gtk_widget_show_all (widget);
+  gtk_container_add (GTK_CONTAINER (eb), widget);
+
+  // blindly copied from gnc-html-guppi.c..
+  gtk_widget_set_size_request (GTK_WIDGET (eb), eb->width, eb->height);
+
+  g_object_set_data_full (G_OBJECT (eb), "graph", graph, g_object_unref);
+  g_signal_connect (G_OBJECT (eb), "draw_print",
+		    G_CALLBACK (draw_print_cb), NULL);
+}
+#endif
+
+static gboolean
+create_basic_plot_elements(const char *plot_type_name,
+                           GogObject **out_graph,
+                           GogObject **out_chart,
+                           GogPlot **out_plot)
+{
+  *out_graph = g_object_new(GOG_GRAPH_TYPE, NULL);
+  *out_chart = gog_object_add_by_name(*out_graph, "Chart", NULL);
+  *out_plot = gog_plot_new_by_name(plot_type_name);
+  if (!*out_plot)
+  {
+    // FIXME - log betterer; should probably use GError?
+    g_warning("gog: unable to load %s plugin", plot_type_name);
+    return FALSE;
+  }
+  gog_object_add_by_name(*out_chart, "Plot", GOG_OBJECT(*out_plot) );
+  return TRUE;
+}
+
+static void
+set_chart_titles_from_hash(GogObject *chart, gpointer eb)
+{
+  set_chart_titles(chart,
+                   (const char *)gnc_html_get_embedded_param(eb, "title"), 
+                   (const char *)gnc_html_get_embedded_param(eb, "subtitle"));
+}
+
+static void
+set_chart_titles(GogObject *chart, const char *title, const char* sub_title)
+{
+  gchar *my_sub_title, *total_title;
+  GOData *title_scalar;
+  GogObject *tmp;
+
+  if (sub_title)
+    my_sub_title = g_strdup_printf("%s(%s)", title ? " " : "", sub_title);
+  else
+    my_sub_title = g_strdup("");
+
+  total_title = g_strdup_printf("%s%s", title ? title : "", my_sub_title);
+
+  tmp = gog_object_add_by_name(chart, "Title", NULL);
+  title_scalar = go_data_scalar_str_new(total_title, TRUE);
+  gog_dataset_set_dim(GOG_DATASET(tmp), 0, title_scalar, NULL);
+
+  g_free(my_sub_title);
+}
+
+static void
+set_chart_axis_labels_from_hash(GogObject *chart, gpointer eb)
+{
+  set_chart_axis_labels(chart,
+                        gnc_html_get_embedded_param(eb, "x_axis_label"),
+                        gnc_html_get_embedded_param(eb, "y_axis_label"));
+}
+
+static void
+set_chart_axis_labels(GogObject *chart, const char *x_axis_label, const char* y_axis_label)
+{
+  if (x_axis_label != NULL)
+  {
+    GogObject *xaxis, *label;
+    GOData *data;
+    xaxis = gog_object_get_child_by_role(chart, gog_object_find_role_by_name(chart, "X-Axis"));
+    label = gog_object_add_by_name(xaxis, "Label", NULL);
+    data = go_data_scalar_str_new(x_axis_label, FALSE);
+    gog_dataset_set_dim(GOG_DATASET(label), 0, data, NULL);
+  }
+
+  if (y_axis_label != NULL)
+  {
+    GogObject *yaxis, *label;
+    GOData *data;
+    yaxis = gog_object_get_child_by_role(chart, gog_object_find_role_by_name(chart, "Y-Axis"));
+    label = gog_object_add_by_name(yaxis, "Label", NULL);
+    data = go_data_scalar_str_new(y_axis_label, FALSE);
+    gog_dataset_set_dim(GOG_DATASET(label), 0, data, NULL);
+  }
+}
+
+/*
+ * Handle the following parameters:
+ * title: text
+ * subtitle: text
+ * datasize: (length data), sscanf( .., %d, (int)&datasize )
+ * data: (foreach (lambda (datum) (push datum) (push " ")) data)
+ * colors: string; space-seperated?
+ * labels: string; space-seperated?
+ * slice_urls_[123]: ?
+ * legend_urls_[123]: ?
+ */
+static gboolean
+handle_piechart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GOData *labelData, *sliceData;
+  int datasize;
+  double *data = NULL;
+  char **labels = NULL, **colors = NULL;
+
+  // parse data from the text-ized params.
+  {
+    const char *datasizeStr, *dataStr, *labelsStr, *colorStr;
+
+    datasizeStr = gnc_html_get_embedded_param(eb, "datasize");
+    dataStr = gnc_html_get_embedded_param(eb, "data" );
+    labelsStr = gnc_html_get_embedded_param(eb, "labels");
+    colorStr = gnc_html_get_embedded_param(eb, "colors");
+    g_return_val_if_fail( datasizeStr != NULL
+                          && dataStr != NULL
+                          && labelsStr != NULL
+                          && colorStr != NULL, FALSE );
+    datasize = atoi( datasizeStr );
+    data = read_doubles( dataStr, datasize );
+    labels = read_strings( labelsStr, datasize );
+    colors = read_strings( colorStr, datasize );
+  }
+
+  if (!create_basic_plot_elements("GogPiePlot", &graph, &chart, &plot))
+  {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  GOG_STYLED_OBJECT(graph)->style->outline.width = 5;
+  GOG_STYLED_OBJECT(graph)->style->outline.color = RGBA_BLACK;
+
+  series = gog_plot_new_series(plot);
+  labelData = go_data_vector_str_new((char const * const *)labels, datasize, NULL);
+  gog_series_set_dim(series, 0, labelData, NULL);
+  go_data_emit_changed(GO_DATA(labelData));
+
+  sliceData = go_data_vector_val_new(data, datasize, NULL);
+  gog_series_set_dim(series, 1, sliceData, NULL);
+  go_data_emit_changed(GO_DATA(sliceData));
+
+  // fixme: colors
+  set_chart_titles_from_hash(chart, eb);
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  return TRUE;
+}
+
+/**
+ * data_rows:int
+ * data_cols:int
+ * data:doubles[], data_rows*data_cols
+ * x_axis_label:string
+ * y_axis_label:string
+ * row_labels:string[]
+ * col_labels:string[]
+ * col_colors:string[]
+ * rotate_row_labels:boolean
+ * stacked:boolean
+ **/
+static gboolean
+handle_barchart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GogStyle *style;
+  GOData *label_data, *slice_data;
+  int data_rows, data_cols;
+  double *data = NULL;
+  char **col_labels = NULL, **row_labels = NULL, **col_colors = NULL;
+  gboolean rotate_row_labels = FALSE;
+  gboolean stacked = FALSE;
+  char *bar_type = "normal";
+  int bar_overlap = 0 /*percent*/; // seperate bars; no overlap.
+
+  // parse data from the text-ized params
+  // series => bars [gnc:cols]
+  // series-elements => segments [gnc:rows]
+  {
+    const char *data_rows_str, *data_cols_str, *data_str, *col_labels_str, *row_labels_str;
+    const char *col_colors_str, *rotate_row_labels_str = NULL, *stacked_str = NULL;
+
+    data_rows_str         = gnc_html_get_embedded_param (eb, "data_rows");
+    data_cols_str         = gnc_html_get_embedded_param (eb, "data_cols");
+    data_str              = gnc_html_get_embedded_param (eb, "data" );
+    row_labels_str        = gnc_html_get_embedded_param (eb, "row_labels");
+    col_labels_str        = gnc_html_get_embedded_param (eb, "col_labels");
+    col_colors_str        = gnc_html_get_embedded_param (eb, "col_colors");
+    rotate_row_labels_str = gnc_html_get_embedded_param (eb, "rotate_row_labels");
+    stacked_str           = gnc_html_get_embedded_param (eb, "stacked");
+
+    rotate_row_labels     = (gboolean) atoi (rotate_row_labels_str);
+    stacked               = (gboolean) atoi (stacked_str);
+
+#if 0 // too strong at the moment.
+    g_return_val_if_fail (data_rows_str != NULL
+                          && data_cols_str != NULL
+                          && data_str != NULL
+                          && col_labels_str != NULL
+                          && row_labels_str != NULL
+                          && col_colors_str != NULL, FALSE );
+#endif // 0
+    data_rows = atoi (data_rows_str);
+    data_cols = atoi (data_cols_str);
+    data = read_doubles (data_str, data_rows*data_cols);
+    row_labels = read_strings (row_labels_str, data_rows);
+    col_labels = read_strings (col_labels_str, data_cols);
+    col_colors = read_strings (col_colors_str, data_cols);
+  }
+
+  if (!create_basic_plot_elements("GogBarColPlot", &graph, &chart, &plot)) {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  if ( stacked ) {
+    // when stacked, we want the bars on _top_ of eachother.
+    bar_type = "stacked";
+    bar_overlap = 100 /*percent*/;
+  }
+
+  g_object_set (G_OBJECT (plot),
+                //"vary_style_by_element",	TRUE,
+                "type",                         bar_type,
+                "overlap_percentage",           bar_overlap, 
+                NULL);
+  label_data = go_data_vector_str_new ((char const * const *)row_labels, data_rows, NULL);
+  {
+    // foreach row:
+    //   series = row
+    GdkColor color;
+    int i;
+    for (i = 0; i < data_cols; i++) {
+      GError *err = NULL;
+
+      series = gog_plot_new_series (plot);
+      gog_object_set_name (GOG_OBJECT (series), col_labels[i], &err);
+      if (err != NULL)
+      {
+           g_warning("error setting name [%s] on series [%d]: [%s]",
+                     col_labels[i], i, err->message);
+      }
+
+      g_object_ref (label_data);
+      gog_series_set_dim (series, 0, label_data, NULL);
+      go_data_emit_changed (GO_DATA (label_data));
+
+      slice_data = go_data_vector_val_new (data + (i*data_rows), data_rows, NULL);
+      gog_series_set_dim (series, 1, slice_data, NULL);
+      go_data_emit_changed (GO_DATA (slice_data));
+
+      style = gog_styled_object_get_style (GOG_STYLED_OBJECT (series));
+      style->fill.type = GOG_FILL_STYLE_PATTERN;
+      if (gdk_color_parse (col_colors[i], &color)) {
+           style->fill.auto_back = FALSE;
+           go_pattern_set_solid (&style->fill.pattern, GDK_TO_UINT (color));
+      } else {
+           g_warning("cannot parse color [%s]", col_colors[i]);
+      }
+    }
+  }
+
+  if (rotate_row_labels) {
+    GogObject *object = gog_object_get_child_by_role (
+      chart, gog_object_find_role_by_name (chart, "X-Axis"));
+    style = gog_styled_object_get_style (GOG_STYLED_OBJECT (object));
+    gog_style_set_text_angle (style, 90.0);
+  }
+
+  set_chart_titles_from_hash (chart, eb);
+  set_chart_axis_labels_from_hash (chart, eb);
+
+  // we need to do this twice for the barchart... :p
+  gog_object_update (GOG_OBJECT (graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  g_debug("barchart rendered.");
+  return TRUE;
+}
+
+
+/**
+ * data_rows:int
+ * data_cols:int
+ * data:doubles[], data_rows*data_cols
+ * x_axis_label:string
+ * y_axis_label:string
+ * row_labels:string[]
+ * col_labels:string[]
+ * col_colors:string[]
+ * rotate_row_labels:boolean
+ * stacked:boolean
+ * markers:boolean
+ * major_grid:boolean
+ * minor_grid:boolean
+ **/
+static gboolean
+handle_linechart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GogStyle *style;
+  GOData *label_data, *slice_data;
+  int data_rows, data_cols;
+  double *data = NULL;
+  char **col_labels = NULL, **row_labels = NULL, **col_colors = NULL;
+  gboolean rotate_row_labels = FALSE;
+  gboolean stacked = FALSE;
+  gboolean markers = FALSE;
+  gboolean major_grid = FALSE;
+  gboolean minor_grid = FALSE;
+  char *line_type = "normal";
+
+  // parse data from the text-ized params
+  // series => lines [gnc:cols]
+  // series-elements => segments [gnc:rows]
+  {
+    const char *data_rows_str, *data_cols_str, *data_str, *col_labels_str, *row_labels_str;
+    const char *col_colors_str, *rotate_row_labels_str = NULL, *stacked_str = NULL, *markers_str = NULL;
+    const char *major_grid_str = NULL, *minor_grid_str = NULL;
+
+    data_rows_str         = gnc_html_get_embedded_param (eb, "data_rows");
+    data_cols_str         = gnc_html_get_embedded_param (eb, "data_cols");
+    data_str              = gnc_html_get_embedded_param (eb, "data" );
+    row_labels_str        = gnc_html_get_embedded_param (eb, "row_labels");
+    col_labels_str        = gnc_html_get_embedded_param (eb, "col_labels");
+    col_colors_str        = gnc_html_get_embedded_param (eb, "col_colors");
+    rotate_row_labels_str = gnc_html_get_embedded_param (eb, "rotate_row_labels");
+    stacked_str           = gnc_html_get_embedded_param (eb, "stacked");
+    markers_str           = gnc_html_get_embedded_param (eb, "markers");
+    major_grid_str        = gnc_html_get_embedded_param (eb, "major_grid");
+    minor_grid_str        = gnc_html_get_embedded_param (eb, "minor_grid");
+
+    rotate_row_labels     = (gboolean) atoi (rotate_row_labels_str);
+    stacked               = (gboolean) atoi (stacked_str);
+    markers               = (gboolean) atoi (markers_str);
+    major_grid            = (gboolean) atoi (major_grid_str);
+    minor_grid            = (gboolean) atoi (minor_grid_str);
+
+#if 0 // too strong at the moment.
+    g_return_val_if_fail (data_rows_str != NULL
+                          && data_cols_str != NULL
+                          && data_str != NULL
+                          && col_labels_str != NULL
+                          && row_labels_str != NULL
+                          && col_colors_str != NULL, FALSE );
+#endif // 0
+
+    data_rows = atoi (data_rows_str);
+    data_cols = atoi (data_cols_str);
+    data = read_doubles (data_str, data_rows*data_cols);
+    row_labels = read_strings (row_labels_str, data_rows);
+    col_labels = read_strings (col_labels_str, data_cols);
+    col_colors = read_strings (col_colors_str, data_cols);
+  }
+
+  if (!create_basic_plot_elements("GogLinePlot", &graph, &chart, &plot)) {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  if ( stacked ) {
+    // when stacked, we want the lines on _top_ of eachother.
+    line_type = "stacked";
+  }
+
+  g_object_set (G_OBJECT (plot),
+                //"vary_style_by_element",	TRUE,
+                "type",                         line_type,
+                "default-style-has-markers",	markers,
+                NULL);
+  label_data = go_data_vector_str_new ((char const * const *)row_labels, data_rows, NULL);
+  {
+    // foreach row:
+    //   series = row
+    GdkColor color;
+    int i;
+    for (i = 0; i < data_cols; i++) {
+      GError *err = NULL;
+
+      series = gog_plot_new_series (plot);
+      gog_object_set_name (GOG_OBJECT (series), col_labels[i], &err);
+      if (err != NULL)
+      {
+           g_warning("error setting name [%s] on series [%d]: [%s]",
+                     col_labels[i], i, err->message);
+      }
+
+      g_object_ref (label_data);
+      gog_series_set_dim (series, 0, label_data, NULL);
+      go_data_emit_changed (GO_DATA (label_data));
+
+      slice_data = go_data_vector_val_new (data + (i*data_rows), data_rows, NULL);
+      gog_series_set_dim (series, 1, slice_data, NULL);
+      go_data_emit_changed (GO_DATA (slice_data));
+
+      style = gog_styled_object_get_style (GOG_STYLED_OBJECT (series));
+      style->fill.type = GOG_FILL_STYLE_PATTERN;
+      if (gdk_color_parse (col_colors[i], &color)) {
+           style->fill.auto_back = FALSE;
+           go_pattern_set_solid (&style->fill.pattern, GDK_TO_UINT (color));
+      } else {
+           g_warning("cannot parse color [%s]", col_colors[i]);
+      }
+    }
+  }
+
+  if (rotate_row_labels) {
+    GogObject *object = gog_object_get_child_by_role (
+      chart, gog_object_find_role_by_name (chart, "X-Axis"));
+    style = gog_styled_object_get_style (GOG_STYLED_OBJECT (object));
+    gog_style_set_text_angle (style, 90.0);
+  }
+
+  if (major_grid || minor_grid) {
+    GogObject *object;
+    gog_object_add_by_name(chart,"Grid", NULL);
+    object = gog_object_get_child_by_role (chart, gog_object_find_role_by_name (chart, "Y-Axis"));
+    if (major_grid)
+      gog_object_add_by_name (GOG_OBJECT (object),"MajorGrid", NULL);
+    if (minor_grid)
+      gog_object_add_by_name (GOG_OBJECT (object),"MinorGrid", NULL);
+  }
+
+  set_chart_titles_from_hash (chart, eb);
+  set_chart_axis_labels_from_hash (chart, eb);
+
+  // we need to do this twice for the linechart... :p
+  gog_object_update (GOG_OBJECT (graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  g_debug("linechart rendered.");
+  return TRUE;
+}
+
+
+static gboolean
+handle_scatter( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GOData *sliceData;
+  GogStyle *style;
+  int datasize;
+  double *xData, *yData;
+  const gchar *marker_str, *color_str;
+  gboolean fill = FALSE;
+
+  {
+    const char *datasizeStr, *xDataStr, *yDataStr;
+
+    datasizeStr = gnc_html_get_embedded_param( eb, "datasize" );
+    datasize = atoi( datasizeStr );
+
+    xDataStr = gnc_html_get_embedded_param( eb, "x_data" );
+    xData = read_doubles( xDataStr, datasize );
+
+    yDataStr = gnc_html_get_embedded_param( eb, "y_data" );
+    yData = read_doubles( yDataStr, datasize );
+
+    marker_str = gnc_html_get_embedded_param(eb, "marker");
+    color_str = gnc_html_get_embedded_param(eb, "color");
+  }
+
+  if (!create_basic_plot_elements("GogXYPlot", &graph, &chart, &plot))
+  {
+    return FALSE;
+  }
+
+  series = gog_plot_new_series( plot );
+  style = gog_styled_object_get_style(GOG_STYLED_OBJECT(series));
+
+  sliceData = go_data_vector_val_new( xData, datasize, NULL );
+  gog_series_set_dim( series, 0, sliceData, NULL );
+  go_data_emit_changed (GO_DATA (sliceData));
+
+  sliceData = go_data_vector_val_new( yData, datasize, NULL );
+  gog_series_set_dim( series, 1, sliceData, NULL );
+  go_data_emit_changed (GO_DATA (sliceData));
+
+  /* set marker shape */
+  if (marker_str) {
+    GOMarkerShape shape;
+
+    if (g_str_has_prefix(marker_str, "filled ")) {
+      fill = TRUE;
+      marker_str += 7;
+    }
+    shape = go_marker_shape_from_str(marker_str);
+    if (shape != GO_MARKER_NONE) {
+      style->marker.auto_shape = FALSE;
+      go_marker_set_shape(style->marker.mark, shape);
+    } else {
+      g_warning("cannot parse marker shape [%s]", marker_str);
+    }
+  }
+
+  /* set marker and line colors */
+  if (color_str) {
+    GdkColor color;
+    if (gdk_color_parse(color_str, &color)) {
+      style->marker.auto_outline_color = FALSE;
+      go_marker_set_outline_color(style->marker.mark, GDK_TO_UINT(color));
+      style->line.auto_color = FALSE;
+      style->line.color = GDK_TO_UINT(color);
+    } else {
+      g_warning("cannot parse color [%s]", color_str);
+    }
+  }
+
+  /* set marker fill colors */
+  if (fill) {
+    style->marker.auto_fill_color = style->marker.auto_outline_color;
+    go_marker_set_fill_color(style->marker.mark,
+                             go_marker_get_outline_color(style->marker.mark));
+  } else {
+    GogStyle *chart_style =
+      gog_styled_object_get_style(GOG_STYLED_OBJECT(chart));
+
+    if (chart_style->fill.type == GOG_FILL_STYLE_PATTERN
+        && chart_style->fill.pattern.pattern == GO_PATTERN_SOLID) {
+      style->marker.auto_fill_color = FALSE;
+      go_marker_set_fill_color(style->marker.mark,
+                               chart_style->fill.pattern.back);
+    } else if (chart_style->fill.type == GOG_FILL_STYLE_PATTERN
+               && chart_style->fill.pattern.pattern
+               == GO_PATTERN_FOREGROUND_SOLID) {
+      style->marker.auto_fill_color = FALSE;
+      go_marker_set_fill_color(style->marker.mark,
+                               chart_style->fill.pattern.fore);
+    } else {
+      g_warning("fill color of markers can only be set like a solid fill "
+                "pattern of the chart");
+    }
+  }
+
+  set_chart_titles_from_hash(chart, eb);
+  set_chart_axis_labels_from_hash(chart, eb);
+
+  // And twice for the scatter, too... :p
+  gog_object_update(GOG_OBJECT(graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  return TRUE;
+}
+
+#if 0
+#ifdef GTKHTML_USES_GTKPRINT
+static void
+draw_print_cb(GtkHTMLEmbedded *eb, cairo_t *cr, gpointer unused)
+{
+  GogGraph *graph = GOG_GRAPH(g_object_get_data(G_OBJECT(eb), "graph"));
+#    ifdef HAVE_GOFFICE_0_5
+  GogRenderer *rend = g_object_new(GOG_RENDERER_TYPE, "model", graph, NULL);
+#    else
+  GogRendererCairo *rend = g_object_new(GOG_RENDERER_CAIRO_TYPE, "model", graph,
+                                        "cairo", cr, "is-vector", TRUE, NULL);
+#    endif
+
+  /* assuming pixel size is 0.5, cf. gtkhtml/src/htmlprinter.c */
+  cairo_scale(cr, 0.5, 0.5);
+
+  cairo_translate(cr, 0, -eb->height);
+
+#    ifdef HAVE_GOFFICE_0_5
+  gog_renderer_render_to_cairo(rend, cr, eb->width, eb->height);
+#    else
+  gog_renderer_cairo_update(rend, eb->width, eb->height, 1.0);
+#    endif
+  g_object_unref(rend);
+}
+#endif
+
+#else /* !GTKHTML_USES_GTKPRINT */
+#if 0
+static void
+draw_print_cb(GtkHTMLEmbedded *eb, GnomePrintContext *context, gpointer unused)
+{
+  GogGraph *graph = GOG_GRAPH (g_object_get_data (G_OBJECT (eb), "graph"));
+
+  /* assuming pixel size is 0.5, cf. gtkhtml/src/htmlprinter.c */
+  gnome_print_scale (context, 0.5, 0.5);
+
+  gnome_print_translate (context, 0, eb->height);
+  gog_graph_print_to_gnome_print (graph, context, eb->width, eb->height);
+}
+#endif
+#endif /* GTKHTML_USES_GTKPRINT */

Added: gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-gtkmozembed.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,30 @@
+/********************************************************************
+ * gnc-html_graph_gog_gtkmozembed.h -- display html with gnc        *
+ *                                     special tags			        *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_GRAPH_GOG_GTKMOZEMBED_H
+#define GNC_HTML_GRAPH_GOG_GTKMOZEMBED_H 1
+
+void gnc_html_graph_gog_gtkmozembed_init( void );
+
+#endif /* GNC_HTML_GRAPH_GOG_GTKMOZEMBED_H */

Added: gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.c	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,821 @@
+/********************************************************************
+ * gnc-html-graph-gog_webkit.c -- GNC/HTML Graphing support via GOG *
+
+ * Copyright (C) 2005 Joshua Sled <jsled at asynchronous.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 <gtk/gtk.h>
+#include <webkit/webkit.h>
+#include <string.h>
+
+#include "gnc-ui-util.h"
+#include "gnc-html-graph-gog-webkit.h"
+#include "gnc-html.h"
+#include "gnc-engine.h"
+#include <goffice/goffice.h>
+#include <goffice/graph/gog-chart.h>
+#include <goffice/graph/gog-graph.h>
+#include <goffice/graph/gog-object.h>
+#if defined(HAVE_GOFFICE_0_5)
+#    include <goffice/graph/gog-renderer.h>
+#elif defined(GOFFICE_WITH_CAIRO)
+#    include <goffice/graph/gog-renderer-cairo.h>
+#else
+#    include <goffice/graph/gog-renderer-pixbuf.h>
+#endif
+#ifndef GTKHTML_USES_GTKPRINT
+#    include <goffice/graph/gog-renderer-gnome-print.h>
+#endif
+#include <goffice/graph/gog-style.h>
+#include <goffice/graph/gog-styled-object.h>
+#include <goffice/graph/gog-plot.h>
+#include <goffice/graph/gog-series.h>
+#include <goffice/utils/go-color.h>
+#include <goffice/utils/go-marker.h>
+#include <goffice/graph/gog-data-set.h>
+#include <goffice/data/go-data-simple.h>
+#include <goffice/app/go-plugin.h>
+#include <goffice/app/go-plugin-loader-module.h>
+
+/**
+ * TODO:
+ * - scatter-plot marker selection
+ * - series-color, piecharts (hard, not really supported by GOG)
+ *   and scatters (or drop feature)
+ * - title-string freeing (fixmes)
+ * - general graph cleanup
+ **/
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "gnc.html.graph.gog.webkit"
+
+static int handle_piechart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_barchart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_linechart( GncHtml* html, gpointer eb, gpointer d );
+static int handle_scatter( GncHtml* html, gpointer eb, gpointer d );
+
+#if 0
+#ifdef GTKHTML_USES_GTKPRINT
+static void draw_print_cb(GtkHTMLEmbedded *eb, cairo_t *cr, gpointer graph);
+#else
+static void draw_print_cb(GtkHTMLEmbedded *eb, GnomePrintContext *context, gpointer graph);
+#endif
+#endif
+
+static gboolean create_basic_plot_elements(const char *plot_type, GogObject **out_graph, GogObject **out_chart, GogPlot **out_plot);
+
+static double * read_doubles(const char * string, int nvalues);
+
+static void set_chart_titles_from_hash(GogObject *chart, gpointer eb);
+static void set_chart_titles(GogObject *chart, const char *title, const char* sub_title);
+static void set_chart_axis_labels_from_hash(GogObject *chart, gpointer eb);
+static void set_chart_axis_labels(GogObject *chart, const char *x_axis_label, const char* y_axis_label);
+
+void
+gnc_html_graph_gog_webkit_init( void )
+{
+  g_debug( "init gog graphing" );
+  
+  libgoffice_init();
+  
+  /* Initialize plugins manager */
+  go_plugins_init( NULL, NULL, NULL, NULL, TRUE, GO_PLUGIN_LOADER_MODULE_TYPE );
+
+  gnc_html_register_object_handler( "gnc-guppi-pie", handle_piechart );
+  gnc_html_register_object_handler( "gnc-guppi-bar", handle_barchart );
+  gnc_html_register_object_handler( "gnc-guppi-scatter", handle_scatter );
+  gnc_html_register_object_handler( "gnc-guppi-line", handle_linechart );
+}
+
+static double * 
+read_doubles(const char * string, int nvalues)
+{
+  int    n;
+  gchar *next;
+  double * retval = g_new0(double, nvalues);
+
+  // guile is going to (puts ...) the elements of the double array
+  // together. In non-POSIX locales, that will be in a format that
+  // the locale-specific sscanf will not be able to parse.
+  gnc_push_locale("C");
+  {
+    for (n=0; n<nvalues; n++) {
+      retval[n] = strtod(string, &next);
+      string = next;
+     }
+  }
+  gnc_pop_locale();
+
+  return retval;
+}
+
+static char ** 
+read_strings(const char * string, int nvalues)
+{
+  int n;
+  int choffset=0;
+  int accum = 0;
+  char ** retval = g_new0(char *, nvalues);
+  char thischar;
+  const char * inptr = string;
+  int escaped = FALSE;
+
+  for (n=0; n < nvalues; n++) {
+    retval[n] = g_new0(char, strlen(string+accum)+1);
+    retval[n][0] = 0;
+    choffset = 0;
+    while ((thischar = *inptr) != 0) {
+      if (thischar == '\\') {
+        escaped = TRUE;
+        inptr++;
+      }
+      else if ((thischar != ' ') || escaped) {
+        retval[n][choffset] = thischar;
+        retval[n][choffset+1] = 0;    
+        choffset++;
+        escaped = FALSE;
+        inptr++;
+      }
+      else {
+        /* an unescaped space */
+        escaped = FALSE;
+        inptr++;
+        break;
+      }
+    }
+    accum += choffset;
+    /* printf("retval[%d] = '%s'\n", n, retval[n]); */
+  }
+  
+  return retval;  
+}
+
+#if 0
+static void
+add_pixbuf_graph_widget( GtkHTMLEmbedded *eb, GogObject *graph )
+{
+  GtkWidget *widget;
+#if defined(HAVE_GOFFICE_0_5)
+  GogRenderer *renderer;
+#elif defined(GOFFICE_WITH_CAIRO)
+  GogRendererCairo *cairo_renderer;
+#else
+  GogRendererPixbuf *pixbuf_renderer;
+#endif
+  GdkPixbuf *buf;
+  gboolean update_status;
+
+  // Note that this shouldn't be necessary as per discussion with Jody...
+  // ... but it is because we don't embed in a control which passes the
+  // update requests back to the graph widget, a-la the foo-canvas that
+  // gnumeric uses.  We probably _should_ do something like that, though.
+  gog_object_update (GOG_OBJECT (graph));
+
+#if defined(HAVE_GOFFICE_0_5)
+  renderer = GOG_RENDERER (g_object_new (GOG_RENDERER_TYPE,
+					 "model", graph,
+					 NULL));
+  update_status = gog_renderer_update (renderer, eb->width, eb->height);
+  buf = gog_renderer_get_pixbuf (renderer);
+#elif defined(GOFFICE_WITH_CAIRO)
+  cairo_renderer = GOG_RENDERER_CAIRO (g_object_new (GOG_RENDERER_CAIRO_TYPE,
+						     "model", graph,
+						     NULL));
+  update_status = gog_renderer_cairo_update (cairo_renderer,
+					     eb->width, eb->height, 1.0);
+  buf = gog_renderer_cairo_get_pixbuf (cairo_renderer);
+#else
+  pixbuf_renderer = GOG_RENDERER_PIXBUF (g_object_new (GOG_RENDERER_PIXBUF_TYPE,
+						       "model", graph,
+						       NULL));
+  update_status = gog_renderer_pixbuf_update (pixbuf_renderer,
+					      eb->width, eb->height, 1.0);
+  buf = gog_renderer_pixbuf_get (pixbuf_renderer);
+#endif
+
+  widget = gtk_image_new_from_pixbuf (buf);
+  gtk_widget_set_size_request (widget, eb->width, eb->height);
+  gtk_widget_show_all (widget);
+  gtk_container_add (GTK_CONTAINER (eb), widget);
+
+  // blindly copied from gnc-html-guppi.c..
+  gtk_widget_set_size_request (GTK_WIDGET (eb), eb->width, eb->height);
+
+  g_object_set_data_full (G_OBJECT (eb), "graph", graph, g_object_unref);
+  g_signal_connect (G_OBJECT (eb), "draw_print",
+		    G_CALLBACK (draw_print_cb), NULL);
+}
+#endif
+
+static gboolean
+create_basic_plot_elements(const char *plot_type_name,
+                           GogObject **out_graph,
+                           GogObject **out_chart,
+                           GogPlot **out_plot)
+{
+  *out_graph = g_object_new(GOG_GRAPH_TYPE, NULL);
+  *out_chart = gog_object_add_by_name(*out_graph, "Chart", NULL);
+  *out_plot = gog_plot_new_by_name(plot_type_name);
+  if (!*out_plot)
+  {
+    // FIXME - log betterer; should probably use GError?
+    g_warning("gog: unable to load %s plugin", plot_type_name);
+    return FALSE;
+  }
+  gog_object_add_by_name(*out_chart, "Plot", GOG_OBJECT(*out_plot) );
+  return TRUE;
+}
+
+static void
+set_chart_titles_from_hash(GogObject *chart, gpointer eb)
+{
+  set_chart_titles(chart,
+                   (const char *)gnc_html_get_embedded_param(eb, "title"), 
+                   (const char *)gnc_html_get_embedded_param(eb, "subtitle"));
+}
+
+static void
+set_chart_titles(GogObject *chart, const char *title, const char* sub_title)
+{
+  gchar *my_sub_title, *total_title;
+  GOData *title_scalar;
+  GogObject *tmp;
+
+  if (sub_title)
+    my_sub_title = g_strdup_printf("%s(%s)", title ? " " : "", sub_title);
+  else
+    my_sub_title = g_strdup("");
+
+  total_title = g_strdup_printf("%s%s", title ? title : "", my_sub_title);
+
+  tmp = gog_object_add_by_name(chart, "Title", NULL);
+  title_scalar = go_data_scalar_str_new(total_title, TRUE);
+  gog_dataset_set_dim(GOG_DATASET(tmp), 0, title_scalar, NULL);
+
+  g_free(my_sub_title);
+}
+
+static void
+set_chart_axis_labels_from_hash(GogObject *chart, gpointer eb)
+{
+  set_chart_axis_labels(chart,
+                        gnc_html_get_embedded_param(eb, "x_axis_label"),
+                        gnc_html_get_embedded_param(eb, "y_axis_label"));
+}
+
+static void
+set_chart_axis_labels(GogObject *chart, const char *x_axis_label, const char* y_axis_label)
+{
+  if (x_axis_label != NULL)
+  {
+    GogObject *xaxis, *label;
+    GOData *data;
+    xaxis = gog_object_get_child_by_role(chart, gog_object_find_role_by_name(chart, "X-Axis"));
+    label = gog_object_add_by_name(xaxis, "Label", NULL);
+    data = go_data_scalar_str_new(x_axis_label, FALSE);
+    gog_dataset_set_dim(GOG_DATASET(label), 0, data, NULL);
+  }
+
+  if (y_axis_label != NULL)
+  {
+    GogObject *yaxis, *label;
+    GOData *data;
+    yaxis = gog_object_get_child_by_role(chart, gog_object_find_role_by_name(chart, "Y-Axis"));
+    label = gog_object_add_by_name(yaxis, "Label", NULL);
+    data = go_data_scalar_str_new(y_axis_label, FALSE);
+    gog_dataset_set_dim(GOG_DATASET(label), 0, data, NULL);
+  }
+}
+
+/*
+ * Handle the following parameters:
+ * title: text
+ * subtitle: text
+ * datasize: (length data), sscanf( .., %d, (int)&datasize )
+ * data: (foreach (lambda (datum) (push datum) (push " ")) data)
+ * colors: string; space-seperated?
+ * labels: string; space-seperated?
+ * slice_urls_[123]: ?
+ * legend_urls_[123]: ?
+ */
+static gboolean
+handle_piechart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GOData *labelData, *sliceData;
+  int datasize;
+  double *data = NULL;
+  char **labels = NULL, **colors = NULL;
+
+  // parse data from the text-ized params.
+  {
+    const char *datasizeStr, *dataStr, *labelsStr, *colorStr;
+
+    datasizeStr = gnc_html_get_embedded_param(eb, "datasize");
+    dataStr = gnc_html_get_embedded_param(eb, "data" );
+    labelsStr = gnc_html_get_embedded_param(eb, "labels");
+    colorStr = gnc_html_get_embedded_param(eb, "colors");
+    g_return_val_if_fail( datasizeStr != NULL
+                          && dataStr != NULL
+                          && labelsStr != NULL
+                          && colorStr != NULL, FALSE );
+    datasize = atoi( datasizeStr );
+    data = read_doubles( dataStr, datasize );
+    labels = read_strings( labelsStr, datasize );
+    colors = read_strings( colorStr, datasize );
+  }
+
+  if (!create_basic_plot_elements("GogPiePlot", &graph, &chart, &plot))
+  {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  GOG_STYLED_OBJECT(graph)->style->outline.width = 5;
+  GOG_STYLED_OBJECT(graph)->style->outline.color = RGBA_BLACK;
+
+  series = gog_plot_new_series(plot);
+  labelData = go_data_vector_str_new((char const * const *)labels, datasize, NULL);
+  gog_series_set_dim(series, 0, labelData, NULL);
+  go_data_emit_changed(GO_DATA(labelData));
+
+  sliceData = go_data_vector_val_new(data, datasize, NULL);
+  gog_series_set_dim(series, 1, sliceData, NULL);
+  go_data_emit_changed(GO_DATA(sliceData));
+
+  // fixme: colors
+  set_chart_titles_from_hash(chart, eb);
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  return TRUE;
+}
+
+/**
+ * data_rows:int
+ * data_cols:int
+ * data:doubles[], data_rows*data_cols
+ * x_axis_label:string
+ * y_axis_label:string
+ * row_labels:string[]
+ * col_labels:string[]
+ * col_colors:string[]
+ * rotate_row_labels:boolean
+ * stacked:boolean
+ **/
+static gboolean
+handle_barchart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GogStyle *style;
+  GOData *label_data, *slice_data;
+  int data_rows, data_cols;
+  double *data = NULL;
+  char **col_labels = NULL, **row_labels = NULL, **col_colors = NULL;
+  gboolean rotate_row_labels = FALSE;
+  gboolean stacked = FALSE;
+  char *bar_type = "normal";
+  int bar_overlap = 0 /*percent*/; // seperate bars; no overlap.
+
+  // parse data from the text-ized params
+  // series => bars [gnc:cols]
+  // series-elements => segments [gnc:rows]
+  {
+    const char *data_rows_str, *data_cols_str, *data_str, *col_labels_str, *row_labels_str;
+    const char *col_colors_str, *rotate_row_labels_str = NULL, *stacked_str = NULL;
+
+    data_rows_str         = gnc_html_get_embedded_param (eb, "data_rows");
+    data_cols_str         = gnc_html_get_embedded_param (eb, "data_cols");
+    data_str              = gnc_html_get_embedded_param (eb, "data" );
+    row_labels_str        = gnc_html_get_embedded_param (eb, "row_labels");
+    col_labels_str        = gnc_html_get_embedded_param (eb, "col_labels");
+    col_colors_str        = gnc_html_get_embedded_param (eb, "col_colors");
+    rotate_row_labels_str = gnc_html_get_embedded_param (eb, "rotate_row_labels");
+    stacked_str           = gnc_html_get_embedded_param (eb, "stacked");
+
+    rotate_row_labels     = (gboolean) atoi (rotate_row_labels_str);
+    stacked               = (gboolean) atoi (stacked_str);
+
+#if 0 // too strong at the moment.
+    g_return_val_if_fail (data_rows_str != NULL
+                          && data_cols_str != NULL
+                          && data_str != NULL
+                          && col_labels_str != NULL
+                          && row_labels_str != NULL
+                          && col_colors_str != NULL, FALSE );
+#endif // 0
+    data_rows = atoi (data_rows_str);
+    data_cols = atoi (data_cols_str);
+    data = read_doubles (data_str, data_rows*data_cols);
+    row_labels = read_strings (row_labels_str, data_rows);
+    col_labels = read_strings (col_labels_str, data_cols);
+    col_colors = read_strings (col_colors_str, data_cols);
+  }
+
+  if (!create_basic_plot_elements("GogBarColPlot", &graph, &chart, &plot)) {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  if ( stacked ) {
+    // when stacked, we want the bars on _top_ of eachother.
+    bar_type = "stacked";
+    bar_overlap = 100 /*percent*/;
+  }
+
+  g_object_set (G_OBJECT (plot),
+                //"vary_style_by_element",	TRUE,
+                "type",                         bar_type,
+                "overlap_percentage",           bar_overlap, 
+                NULL);
+  label_data = go_data_vector_str_new ((char const * const *)row_labels, data_rows, NULL);
+  {
+    // foreach row:
+    //   series = row
+    GdkColor color;
+    int i;
+    for (i = 0; i < data_cols; i++) {
+      GError *err = NULL;
+
+      series = gog_plot_new_series (plot);
+      gog_object_set_name (GOG_OBJECT (series), col_labels[i], &err);
+      if (err != NULL)
+      {
+           g_warning("error setting name [%s] on series [%d]: [%s]",
+                     col_labels[i], i, err->message);
+      }
+
+      g_object_ref (label_data);
+      gog_series_set_dim (series, 0, label_data, NULL);
+      go_data_emit_changed (GO_DATA (label_data));
+
+      slice_data = go_data_vector_val_new (data + (i*data_rows), data_rows, NULL);
+      gog_series_set_dim (series, 1, slice_data, NULL);
+      go_data_emit_changed (GO_DATA (slice_data));
+
+      style = gog_styled_object_get_style (GOG_STYLED_OBJECT (series));
+      style->fill.type = GOG_FILL_STYLE_PATTERN;
+      if (gdk_color_parse (col_colors[i], &color)) {
+           style->fill.auto_back = FALSE;
+           go_pattern_set_solid (&style->fill.pattern, GDK_TO_UINT (color));
+      } else {
+           g_warning("cannot parse color [%s]", col_colors[i]);
+      }
+    }
+  }
+
+  if (rotate_row_labels) {
+    GogObject *object = gog_object_get_child_by_role (
+      chart, gog_object_find_role_by_name (chart, "X-Axis"));
+    style = gog_styled_object_get_style (GOG_STYLED_OBJECT (object));
+    gog_style_set_text_angle (style, 90.0);
+  }
+
+  set_chart_titles_from_hash (chart, eb);
+  set_chart_axis_labels_from_hash (chart, eb);
+
+  // we need to do this twice for the barchart... :p
+  gog_object_update (GOG_OBJECT (graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  g_debug("barchart rendered.");
+  return TRUE;
+}
+
+
+/**
+ * data_rows:int
+ * data_cols:int
+ * data:doubles[], data_rows*data_cols
+ * x_axis_label:string
+ * y_axis_label:string
+ * row_labels:string[]
+ * col_labels:string[]
+ * col_colors:string[]
+ * rotate_row_labels:boolean
+ * stacked:boolean
+ * markers:boolean
+ * major_grid:boolean
+ * minor_grid:boolean
+ **/
+static gboolean
+handle_linechart( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GogStyle *style;
+  GOData *label_data, *slice_data;
+  int data_rows, data_cols;
+  double *data = NULL;
+  char **col_labels = NULL, **row_labels = NULL, **col_colors = NULL;
+  gboolean rotate_row_labels = FALSE;
+  gboolean stacked = FALSE;
+  gboolean markers = FALSE;
+  gboolean major_grid = FALSE;
+  gboolean minor_grid = FALSE;
+  char *line_type = "normal";
+
+  // parse data from the text-ized params
+  // series => lines [gnc:cols]
+  // series-elements => segments [gnc:rows]
+  {
+    const char *data_rows_str, *data_cols_str, *data_str, *col_labels_str, *row_labels_str;
+    const char *col_colors_str, *rotate_row_labels_str = NULL, *stacked_str = NULL, *markers_str = NULL;
+    const char *major_grid_str = NULL, *minor_grid_str = NULL;
+
+    data_rows_str         = gnc_html_get_embedded_param (eb, "data_rows");
+    data_cols_str         = gnc_html_get_embedded_param (eb, "data_cols");
+    data_str              = gnc_html_get_embedded_param (eb, "data" );
+    row_labels_str        = gnc_html_get_embedded_param (eb, "row_labels");
+    col_labels_str        = gnc_html_get_embedded_param (eb, "col_labels");
+    col_colors_str        = gnc_html_get_embedded_param (eb, "col_colors");
+    rotate_row_labels_str = gnc_html_get_embedded_param (eb, "rotate_row_labels");
+    stacked_str           = gnc_html_get_embedded_param (eb, "stacked");
+    markers_str           = gnc_html_get_embedded_param (eb, "markers");
+    major_grid_str        = gnc_html_get_embedded_param (eb, "major_grid");
+    minor_grid_str        = gnc_html_get_embedded_param (eb, "minor_grid");
+
+    rotate_row_labels     = (gboolean) atoi (rotate_row_labels_str);
+    stacked               = (gboolean) atoi (stacked_str);
+    markers               = (gboolean) atoi (markers_str);
+    major_grid            = (gboolean) atoi (major_grid_str);
+    minor_grid            = (gboolean) atoi (minor_grid_str);
+
+#if 0 // too strong at the moment.
+    g_return_val_if_fail (data_rows_str != NULL
+                          && data_cols_str != NULL
+                          && data_str != NULL
+                          && col_labels_str != NULL
+                          && row_labels_str != NULL
+                          && col_colors_str != NULL, FALSE );
+#endif // 0
+
+    data_rows = atoi (data_rows_str);
+    data_cols = atoi (data_cols_str);
+    data = read_doubles (data_str, data_rows*data_cols);
+    row_labels = read_strings (row_labels_str, data_rows);
+    col_labels = read_strings (col_labels_str, data_cols);
+    col_colors = read_strings (col_colors_str, data_cols);
+  }
+
+  if (!create_basic_plot_elements("GogLinePlot", &graph, &chart, &plot)) {
+    return FALSE;
+  }
+  gog_object_add_by_name(chart, "Legend", NULL);
+
+  if ( stacked ) {
+    // when stacked, we want the lines on _top_ of eachother.
+    line_type = "stacked";
+  }
+
+  g_object_set (G_OBJECT (plot),
+                //"vary_style_by_element",	TRUE,
+                "type",                         line_type,
+                "default-style-has-markers",	markers,
+                NULL);
+  label_data = go_data_vector_str_new ((char const * const *)row_labels, data_rows, NULL);
+  {
+    // foreach row:
+    //   series = row
+    GdkColor color;
+    int i;
+    for (i = 0; i < data_cols; i++) {
+      GError *err = NULL;
+
+      series = gog_plot_new_series (plot);
+      gog_object_set_name (GOG_OBJECT (series), col_labels[i], &err);
+      if (err != NULL)
+      {
+           g_warning("error setting name [%s] on series [%d]: [%s]",
+                     col_labels[i], i, err->message);
+      }
+
+      g_object_ref (label_data);
+      gog_series_set_dim (series, 0, label_data, NULL);
+      go_data_emit_changed (GO_DATA (label_data));
+
+      slice_data = go_data_vector_val_new (data + (i*data_rows), data_rows, NULL);
+      gog_series_set_dim (series, 1, slice_data, NULL);
+      go_data_emit_changed (GO_DATA (slice_data));
+
+      style = gog_styled_object_get_style (GOG_STYLED_OBJECT (series));
+      style->fill.type = GOG_FILL_STYLE_PATTERN;
+      if (gdk_color_parse (col_colors[i], &color)) {
+           style->fill.auto_back = FALSE;
+           go_pattern_set_solid (&style->fill.pattern, GDK_TO_UINT (color));
+      } else {
+           g_warning("cannot parse color [%s]", col_colors[i]);
+      }
+    }
+  }
+
+  if (rotate_row_labels) {
+    GogObject *object = gog_object_get_child_by_role (
+      chart, gog_object_find_role_by_name (chart, "X-Axis"));
+    style = gog_styled_object_get_style (GOG_STYLED_OBJECT (object));
+    gog_style_set_text_angle (style, 90.0);
+  }
+
+  if (major_grid || minor_grid) {
+    GogObject *object;
+    gog_object_add_by_name(chart,"Grid", NULL);
+    object = gog_object_get_child_by_role (chart, gog_object_find_role_by_name (chart, "Y-Axis"));
+    if (major_grid)
+      gog_object_add_by_name (GOG_OBJECT (object),"MajorGrid", NULL);
+    if (minor_grid)
+      gog_object_add_by_name (GOG_OBJECT (object),"MinorGrid", NULL);
+  }
+
+  set_chart_titles_from_hash (chart, eb);
+  set_chart_axis_labels_from_hash (chart, eb);
+
+  // we need to do this twice for the linechart... :p
+  gog_object_update (GOG_OBJECT (graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  g_debug("linechart rendered.");
+  return TRUE;
+}
+
+
+static gboolean
+handle_scatter( GncHtml* html, gpointer eb, gpointer unused )
+{
+  GogObject *graph, *chart;
+  GogPlot *plot;
+  GogSeries *series;
+  GOData *sliceData;
+  GogStyle *style;
+  int datasize;
+  double *xData, *yData;
+  const gchar *marker_str, *color_str;
+  gboolean fill = FALSE;
+
+  {
+    const char *datasizeStr, *xDataStr, *yDataStr;
+
+    datasizeStr = gnc_html_get_embedded_param( eb, "datasize" );
+    datasize = atoi( datasizeStr );
+
+    xDataStr = gnc_html_get_embedded_param( eb, "x_data" );
+    xData = read_doubles( xDataStr, datasize );
+
+    yDataStr = gnc_html_get_embedded_param( eb, "y_data" );
+    yData = read_doubles( yDataStr, datasize );
+
+    marker_str = gnc_html_get_embedded_param(eb, "marker");
+    color_str = gnc_html_get_embedded_param(eb, "color");
+  }
+
+  if (!create_basic_plot_elements("GogXYPlot", &graph, &chart, &plot))
+  {
+    return FALSE;
+  }
+
+  series = gog_plot_new_series( plot );
+  style = gog_styled_object_get_style(GOG_STYLED_OBJECT(series));
+
+  sliceData = go_data_vector_val_new( xData, datasize, NULL );
+  gog_series_set_dim( series, 0, sliceData, NULL );
+  go_data_emit_changed (GO_DATA (sliceData));
+
+  sliceData = go_data_vector_val_new( yData, datasize, NULL );
+  gog_series_set_dim( series, 1, sliceData, NULL );
+  go_data_emit_changed (GO_DATA (sliceData));
+
+  /* set marker shape */
+  if (marker_str) {
+    GOMarkerShape shape;
+
+    if (g_str_has_prefix(marker_str, "filled ")) {
+      fill = TRUE;
+      marker_str += 7;
+    }
+    shape = go_marker_shape_from_str(marker_str);
+    if (shape != GO_MARKER_NONE) {
+      style->marker.auto_shape = FALSE;
+      go_marker_set_shape(style->marker.mark, shape);
+    } else {
+      g_warning("cannot parse marker shape [%s]", marker_str);
+    }
+  }
+
+  /* set marker and line colors */
+  if (color_str) {
+    GdkColor color;
+    if (gdk_color_parse(color_str, &color)) {
+      style->marker.auto_outline_color = FALSE;
+      go_marker_set_outline_color(style->marker.mark, GDK_TO_UINT(color));
+      style->line.auto_color = FALSE;
+      style->line.color = GDK_TO_UINT(color);
+    } else {
+      g_warning("cannot parse color [%s]", color_str);
+    }
+  }
+
+  /* set marker fill colors */
+  if (fill) {
+    style->marker.auto_fill_color = style->marker.auto_outline_color;
+    go_marker_set_fill_color(style->marker.mark,
+                             go_marker_get_outline_color(style->marker.mark));
+  } else {
+    GogStyle *chart_style =
+      gog_styled_object_get_style(GOG_STYLED_OBJECT(chart));
+
+    if (chart_style->fill.type == GOG_FILL_STYLE_PATTERN
+        && chart_style->fill.pattern.pattern == GO_PATTERN_SOLID) {
+      style->marker.auto_fill_color = FALSE;
+      go_marker_set_fill_color(style->marker.mark,
+                               chart_style->fill.pattern.back);
+    } else if (chart_style->fill.type == GOG_FILL_STYLE_PATTERN
+               && chart_style->fill.pattern.pattern
+               == GO_PATTERN_FOREGROUND_SOLID) {
+      style->marker.auto_fill_color = FALSE;
+      go_marker_set_fill_color(style->marker.mark,
+                               chart_style->fill.pattern.fore);
+    } else {
+      g_warning("fill color of markers can only be set like a solid fill "
+                "pattern of the chart");
+    }
+  }
+
+  set_chart_titles_from_hash(chart, eb);
+  set_chart_axis_labels_from_hash(chart, eb);
+
+  // And twice for the scatter, too... :p
+  gog_object_update(GOG_OBJECT(graph));
+
+//FIXME  add_pixbuf_graph_widget (eb, graph);
+
+  return TRUE;
+}
+
+#if 0
+#ifdef GTKHTML_USES_GTKPRINT
+static void
+draw_print_cb(GtkHTMLEmbedded *eb, cairo_t *cr, gpointer unused)
+{
+  GogGraph *graph = GOG_GRAPH(g_object_get_data(G_OBJECT(eb), "graph"));
+#    ifdef HAVE_GOFFICE_0_5
+  GogRenderer *rend = g_object_new(GOG_RENDERER_TYPE, "model", graph, NULL);
+#    else
+  GogRendererCairo *rend = g_object_new(GOG_RENDERER_CAIRO_TYPE, "model", graph,
+                                        "cairo", cr, "is-vector", TRUE, NULL);
+#    endif
+
+  /* assuming pixel size is 0.5, cf. gtkhtml/src/htmlprinter.c */
+  cairo_scale(cr, 0.5, 0.5);
+
+  cairo_translate(cr, 0, -eb->height);
+
+#    ifdef HAVE_GOFFICE_0_5
+  gog_renderer_render_to_cairo(rend, cr, eb->width, eb->height);
+#    else
+  gog_renderer_cairo_update(rend, eb->width, eb->height, 1.0);
+#    endif
+  g_object_unref(rend);
+}
+#endif
+
+#else /* !GTKHTML_USES_GTKPRINT */
+#if 0
+static void
+draw_print_cb(GtkHTMLEmbedded *eb, GnomePrintContext *context, gpointer unused)
+{
+  GogGraph *graph = GOG_GRAPH (g_object_get_data (G_OBJECT (eb), "graph"));
+
+  /* assuming pixel size is 0.5, cf. gtkhtml/src/htmlprinter.c */
+  gnome_print_scale (context, 0.5, 0.5);
+
+  gnome_print_translate (context, 0, eb->height);
+  gog_graph_print_to_gnome_print (graph, context, eb->width, eb->height);
+}
+#endif
+#endif /* GTKHTML_USES_GTKPRINT */

Added: gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog-webkit.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,30 @@
+/********************************************************************
+ * gnc-html_graph_gog_webkit.h -- display html with gnc special     *
+ *									tags			                *
+ * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_GRAPH_GOG_WEBKIT_H
+#define GNC_HTML_GRAPH_GOG_WEBKIT_H 1
+
+void gnc_html_graph_gog_webkit_init( void );
+
+#endif /* GNC_HTML_GRAPH_GOG_WEBKIT_H */

Deleted: gnucash/branches/webkit/src/html/gnc-html-graph-gog.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-graph-gog.h	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-graph-gog.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -1,6 +0,0 @@
-#ifndef GNC_HTML_GRAPH_GOG_H
-#define GNC_HTML_GRAPH_GOG_H 1
-
-void gnc_html_graph_gog_init(void);
-
-#endif /* GNC_HTML_GRAPH_GOG_H */

Modified: gnucash/branches/webkit/src/html/gnc-html-gtkhtml-p.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkhtml-p.h	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkhtml-p.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -1,6 +1,6 @@
 /********************************************************************
  * gnc-html-gtkhtml-p.h -- display html with gnc special tags       *
- * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
+ * 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   *

Modified: gnucash/branches/webkit/src/html/gnc-html-gtkhtml.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkhtml.c	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkhtml.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -1,5 +1,6 @@
 /********************************************************************
- * gnc-html.c -- display HTML with some special gnucash tags.       *
+ * gnc-html-gtkhtml.c -- display HTML with some special gnucash     *
+ *                       tags.                                      *
  *                                                                  *
  * Copyright (C) 2000 Bill Gribble <grib at billgribble.com>           *
  * Copyright (C) 2001 Linas Vepstas <linas at linas.org>               *
@@ -50,7 +51,7 @@
 #include "gnc-html.h"
 #include "gnc-html-gtkhtml.h"
 #include "gnc-html-history.h"
-#include "gnc-html-graph-gog.h"
+#include "gnc-html-graph-gog-gtkhtml.h"
 #include "gnc-ui.h"
 #include "gnc-ui-util.h"
 
@@ -74,18 +75,18 @@
 extern GHashTable* gnc_html_proto_to_type_hash;
 
 /* hashes an HTML <object classid="ID"> classid to a handler function */
-static GHashTable* gnc_html_object_handlers = NULL;
+extern GHashTable* gnc_html_object_handlers;
 
 /* hashes an action name from a FORM definition to a handler function.
  * <form method=METHOD action=gnc-action:ACTION-NAME?ACTION-ARGS>
  * action-args is what gets passed to the handler. */
-static GHashTable* gnc_html_action_handlers = NULL;
+extern GHashTable* gnc_html_action_handlers;
 
 /* hashes handlers for loading different URLType data */
-static GHashTable* gnc_html_stream_handlers = NULL;
+extern GHashTable* gnc_html_stream_handlers;
 
 /* hashes handlers for handling different URLType data */
-static GHashTable* gnc_html_url_handlers = NULL;
+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");
@@ -113,8 +114,6 @@
 static gboolean impl_gtkhtml_export( GncHtml* self, const gchar* filepath );
 static void impl_gtkhtml_print( GncHtml* self );
 static void impl_gtkhtml_cancel( GncHtml* self );
-static URLType impl_gtkhtml_parse_url( GncHtml* self, const gchar* url,
-						gchar** url_location, gchar** url_label );
 static void impl_gtkhtml_set_parent( GncHtml* self, GtkWindow* parent );
 
 static void
@@ -124,22 +123,12 @@
 	GncHtmlGtkhtmlPrivate* new_priv;
 
 	new_priv = g_realloc( GNC_HTML(self)->priv, sizeof(GncHtmlGtkhtmlPrivate) );
-//	priv = self->priv = g_new0( GncHtmlGtkhtmlPrivate, 1 );
 	priv = self->priv = new_priv;
 
-//	priv->base.container = gtk_scrolled_window_new( NULL, NULL );
 	priv->html = gtk_html_new();
-
-//	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(priv->base.container),
-//									GTK_POLICY_AUTOMATIC,
-//									GTK_POLICY_AUTOMATIC );
-
 	gtk_container_add( GTK_CONTAINER(priv->base.container),
 						GTK_WIDGET(priv->html) );
 
-//	priv->base.request_info = g_hash_table_new( g_str_hash, g_str_equal );
-//	priv->base.history = gnc_html_history_new();
-
 #ifdef HAVE_GTK_2_10
 	g_object_ref_sink( priv->base.container );
 #else
@@ -178,6 +167,8 @@
 
 	gtk_html_load_empty(GTK_HTML(priv->html));
 
+	show_type_signals( GTK_TYPE_HTML );
+
 	LEAVE("retval %p", self);
 }
 
@@ -197,8 +188,10 @@
 	html_class->export = impl_gtkhtml_export;
 	html_class->print = impl_gtkhtml_print;
 	html_class->cancel = impl_gtkhtml_cancel;
-	html_class->parse_url = impl_gtkhtml_parse_url;
 	html_class->set_parent = impl_gtkhtml_set_parent;
+
+	// Initialize graphing support
+	gnc_html_graph_gog_gtkhtml_init();
 }
 
 static void
@@ -231,139 +224,6 @@
 /*****************************************************************************/
 
 static char*
-extract_machine_name( const gchar* path )
-{
-	gchar machine_rexp[] = "^(//[^/]*)/*(.*)?$";
-	regex_t compiled_m;
-	regmatch_t match[4];
-	gchar* machine = NULL;
-
-	if( path == NULL ) return NULL;
-
-	regcomp( &compiled_m, machine_rexp, REG_EXTENDED );
-
-	/* 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 );
-		}
-	}
-	return machine;
-}
-
-/********************************************************************
- * gnc_html_parse_url
- * this takes a URL and determines the protocol type, location, and
- * possible anchor name from the URL.
- ********************************************************************/
-
-static URLType
-impl_gtkhtml_parse_url( GncHtml* self, const gchar* url,
-						gchar** url_location, gchar** url_label )
-{
-	gchar uri_rexp[] = "^(([^:][^:]+):)?([^#]+)?(#(.*))?$";
-	regex_t compiled;
-	regmatch_t match[6];
-	gchar* protocol = NULL;
-	gchar* path = NULL;
-	gchar* label = NULL;
-	gboolean found_protocol = FALSE;
-	gboolean found_path = FALSE;
-	gboolean found_label = FALSE;
-	URLType retval;
-	GncHtmlGtkhtmlPrivate* priv = GNC_HTML_GTKHTML_GET_PRIVATE(self);
-
-	DEBUG( "parsing %s, base_location %s",
-			url ? url : "(null)",
-			self ? (priv->base.base_location ? priv->base.base_location
-										: "(null base_location)")
-				: "(null html)");
-
-	regcomp( &compiled, uri_rexp, REG_EXTENDED );
-
-	if( !regexec( &compiled, url, 6, match, 0 ) ) {
-		if( match[2].rm_so != -1 ) {
-			protocol = g_new0( gchar, match[2].rm_eo - match[2].rm_so + 1 );
-			strncpy( protocol, url + match[2].rm_so, match[2].rm_eo - match[2].rm_so );
-			protocol[match[2].rm_eo - match[2].rm_so] = 0;
-			found_protocol = TRUE;
-		}
-		if( match[3].rm_so != -1 ) {
-			path = g_new0( gchar, match[3].rm_eo - match[3].rm_so + 1 );
-			strncpy( path, url+match[3].rm_so, match[3].rm_eo - match[3].rm_so );
-			path[match[3].rm_eo - match[3].rm_so] = 0;
-			found_path = TRUE;
-		}
-		if( match[5].rm_so != -1 ) {
-			label = g_new0( gchar, match[5].rm_eo - match[5].rm_so + 1 );
-			strncpy( label, url+match[5].rm_so, match[5].rm_eo - match[5].rm_so );
-			label[match[5].rm_eo - match[5].rm_so] = 0;
-			found_label = TRUE;
-		}
-	}
-
-	regfree( &compiled );
-
-	if( found_protocol ) {
-		retval = g_hash_table_lookup( gnc_html_proto_to_type_hash, protocol );
-		if( retval == NULL ) {
-			PWARN( "unhandled URL type for '%s'", url ? url : "(null)" );
-			retval = URL_TYPE_OTHER;
-		}
-	} else if( found_label && !found_path ) {
-		retval = URL_TYPE_JUMP;
-	} else {
-		if( self ) {
-			retval = priv->base.base_type;
-		} else {
-			retval = URL_TYPE_FILE;
-		}
-	}
-
-	g_free( protocol );
-
-	if( !safe_strcmp( retval, URL_TYPE_FILE ) ) {
-		if( !found_protocol && path && self && priv->base.base_location ) {
-			if( g_path_is_absolute( path ) ) {
-				*url_location = g_strdup( path );
-			} else {
-				*url_location = g_build_filename( priv->base.base_location, path, (gchar*)NULL );
-			}
-			g_free( path );
-		} else {
-			*url_location = g_strdup( path );
-			g_free( path );
-		}
-
-	} else if( !safe_strcmp( retval, URL_TYPE_JUMP ) ) {
-		*url_location = NULL;
-		g_free( path );
-
-	} else {
-		/* case URL_TYPE_OTHER: */
-
-		if( !found_protocol && path && self && priv->base.base_location ) {
-			if( g_path_is_absolute( path ) ) {
-				*url_location = g_build_filename( extract_machine_name( priv->base.base_location ),
-                           path, (gchar*)NULL );
-			} else {
-				*url_location = g_build_filename( priv->base.base_location, path, (gchar*)NULL );
-			}
-			g_free( path );
-		} else {
-			*url_location = g_strdup( path );
-			g_free( path );
-		}
-	}
-
-	*url_label = label;
-	return retval;
-}
-
-
-static char*
 extract_base_name(URLType type, const gchar* path)
 {
 	gchar       machine_rexp[] = "^(//[^/]*)/*(/.*)?$";
@@ -944,17 +804,17 @@
 
 
 /********************************************************************
- * gnc_html_new
+ * gnc_html_gtkhtml_new
  * create and set up a new gtkhtml widget.
  ********************************************************************/
 
-GncHtmlGtkhtml*
+GncHtml*
 gnc_html_gtkhtml_new( void )
 {
 	GncHtmlGtkhtml* self = g_object_new( GNC_TYPE_HTML_GTKHTML, NULL );
 	GncHtmlGtkhtmlPrivate* priv = GNC_HTML_GTKHTML_GET_PRIVATE(self);
 
-	return self;
+	return GNC_HTML(self);
 }
 
 /********************************************************************
@@ -1097,116 +957,6 @@
 	priv->base.parent = GTK_WIDGET(parent);
 }
 
-void
-gnc_html_register_object_handler( const char * classid,
-                                 GncHTMLObjectCB hand )
-{
-	g_return_if_fail( classid != NULL );
-
-	if( gnc_html_object_handlers == NULL ) {
-		gnc_html_object_handlers = g_hash_table_new( g_str_hash, g_str_equal );
-	}
-
-	gnc_html_unregister_object_handler( classid );
-	if( hand != NULL ) {
-		g_hash_table_insert( gnc_html_object_handlers, g_strdup( classid ), hand );
-	}
-}
-
-void
-gnc_html_unregister_object_handler( const gchar* classid )
-{
-	gchar* keyptr = NULL;
-	gchar* valptr = NULL;
-	gchar** p_keyptr = &keyptr;
-	gchar** p_valptr = &valptr;
-
-	if( g_hash_table_lookup_extended( gnc_html_object_handlers,
-											 classid,
-											(gpointer *)p_keyptr,
-											(gpointer *)p_valptr) ) {
-		g_hash_table_remove( gnc_html_object_handlers, classid );
-		g_free( keyptr );
-	}
-}
-
-void
-gnc_html_register_action_handler( const gchar* actionid,
-								GncHTMLActionCB hand )
-{
-	g_return_if_fail( actionid != NULL );
-
-	if( gnc_html_action_handlers == NULL ) {
-		gnc_html_action_handlers = g_hash_table_new( g_str_hash, g_str_equal );
-	}
-
-	gnc_html_unregister_action_handler( actionid );
-	if( hand != NULL ) {
-		g_hash_table_insert( gnc_html_action_handlers, g_strdup( actionid ), hand );
-	}
-}
-
-void
-gnc_html_unregister_action_handler( const gchar* actionid )
-{
-	gchar* keyptr = NULL;
-	gchar* valptr = NULL;
-	gchar** p_keyptr = &keyptr;
-	gchar** p_valptr = &valptr;
-
-	g_return_if_fail( actionid != NULL );
-
-	if( g_hash_table_lookup_extended( gnc_html_action_handlers,
-											actionid,
-											(gpointer *)p_keyptr,
-											(gpointer *)p_valptr) ) {
-		g_hash_table_remove( gnc_html_action_handlers, actionid );
-		g_free( keyptr );
-	}
-}
-
-void
-gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand )
-{
-	g_return_if_fail( url_type != NULL && *url_type != '\0' );
-
-	if( gnc_html_stream_handlers == NULL ) {
-		gnc_html_stream_handlers = g_hash_table_new( g_str_hash, g_str_equal );
-	}
-
-	gnc_html_unregister_stream_handler( url_type );
-	if( hand != NULL ) {
-		g_hash_table_insert( gnc_html_stream_handlers, url_type, hand );
-	}
-}
-
-void
-gnc_html_unregister_stream_handler( URLType url_type )
-{
-	g_hash_table_remove( gnc_html_stream_handlers, url_type );
-}
-
-void
-gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand )
-{
-	g_return_if_fail( url_type != NULL && *url_type != '\0' );
-
-	if( gnc_html_url_handlers == NULL ) {
-		gnc_html_url_handlers = g_hash_table_new( g_str_hash, g_str_equal );
-	}
-
-	gnc_html_unregister_url_handler( url_type );
-	if( hand != NULL ) {
-		g_hash_table_insert( gnc_html_url_handlers, url_type, hand );
-	}
-}
-
-void
-gnc_html_unregister_url_handler( URLType url_type )
-{
-	g_hash_table_remove( gnc_html_url_handlers, url_type );
-}
-
 const gchar*
 gnc_html_get_embedded_param( gpointer eb, const gchar* param_name )
 {

Modified: gnucash/branches/webkit/src/html/gnc-html-gtkhtml.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkhtml.h	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkhtml.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -52,7 +52,7 @@
 
 GType gnc_html_gtkhtml_get_type( void );
 
-GncHtmlGtkhtml* gnc_html_gtkhtml_new( void );
+GncHtml* gnc_html_gtkhtml_new( void );
 
 G_END_DECLS
 

Added: gnucash/branches/webkit/src/html/gnc-html-gtkmozembed-p.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkmozembed-p.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkmozembed-p.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,34 @@
+/********************************************************************
+ * gnc-html-gtkmozembed-p.h -- display html with gnc special tags   *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_GTKMOZEMBED_P_H
+#define GNC_HTML_GTKMOZEMBED_P_H
+
+#include "gnc-html-p.h"
+
+struct _GncHtmlGtkmozembedPrivate {
+	struct _GncHtmlPrivate base;
+
+	GtkMozEmbed* moz_embed;				/* gtkmozembed widget itself */
+};
+
+#endif

Added: gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.c	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,951 @@
+/********************************************************************
+ * gnc-html_gtkmozembed.c -- display HTML with some special gnucash *
+ *                           tags.                                  *
+ *                                                                  *
+ * 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 <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 <libguile.h>
+
+#include <gtkmozembed.h>
+
+#include "Account.h"
+#include "print-session.h"
+#include "gnc-engine.h"
+#include "gnc-gui-query.h"
+#include "gnc-html.h"
+#include "gnc-html-gtkmozembed.h"
+#include "gnc-html-history.h"
+#include "gnc-html-graph-gog-gtkmozembed.h"
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+
+G_DEFINE_TYPE(GncHtmlGtkmozembed, gnc_html_gtkmozembed, GNC_TYPE_HTML )
+
+static void gnc_html_gtkmozembed_dispose( GObject* obj );
+static void gnc_html_gtkmozembed_finalize( GObject* obj );
+static void gnc_html_gtkmozembed_class_init( GncHtmlGtkmozembedClass* klass );
+static void gnc_html_gtkmozembed_init( GncHtmlGtkmozembed* gs );
+
+//#define GNC_HTML_GTKMOZEMBED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_HTML_GTKMOZEMBED, GncHtmlGtkmozembedPrivate))
+#define GNC_HTML_GTKMOZEMBED_GET_PRIVATE(o) (GNC_HTML_GTKMOZEMBED(o)->priv)
+
+#include "gnc-html-gtkmozembed-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 an action name from a FORM definition to a handler function.
+ * <form method=METHOD action=gnc-action:ACTION-NAME?ACTION-ARGS>
+ * action-args is what gets passed to the handler. */
+extern GHashTable* gnc_html_action_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.");
+
+#if 0
+static void webkit_navigation_requested_cb( WebKitWebView* web_view, GObject* arg1,
+												GObject* arg2, gpointer data );
+static void webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url,
+							gpointer data );
+#endif
+#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
+static int gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
+                         gpointer user_data );
+#if 0
+static int gnc_html_submit_cb( GtkHTML* html, const gchar* method,
+                   const gchar* action, const gchar* encoded_form_data,
+                   gpointer user_data );
+#endif
+static void impl_gtkmozembed_show_url( GncHtml* self, URLType type,
+                  const gchar* location, const gchar* label,
+                  gboolean new_window_hint );
+static void impl_gtkmozembed_show_data( GncHtml* self, const gchar* data, int datalen );
+static void impl_gtkmozembed_reload( GncHtml* self );
+static void impl_gtkmozembed_copy( GncHtml* self );
+static gboolean impl_gtkmozembed_export( GncHtml* self, const gchar* filepath );
+static void impl_gtkmozembed_print( GncHtml* self );
+static void impl_gtkmozembed_cancel( GncHtml* self );
+static void impl_gtkmozembed_set_parent( GncHtml* self, GtkWindow* parent );
+
+static void
+gnc_html_gtkmozembed_init( GncHtmlGtkmozembed* self )
+{
+	GncHtmlGtkmozembedPrivate* priv;
+	GncHtmlGtkmozembedPrivate* new_priv;
+
+	new_priv = g_realloc( GNC_HTML(self)->priv, sizeof(GncHtmlGtkmozembedPrivate) );
+	priv = self->priv = new_priv;
+
+	priv->moz_embed = GTK_MOZ_EMBED(gtk_moz_embed_new());
+
+	gtk_container_add( GTK_CONTAINER(priv->base.container),
+						GTK_WIDGET(priv->moz_embed) );
+
+#ifdef HAVE_GTK_2_10
+	g_object_ref_sink( priv->base.container );
+#else
+	g_object_ref( priv->base.container );
+	gtk_object_sink( GTK_OBJECT(priv->base.container) );
+#endif
+
+#if 0
+	/* 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 );
+
+#endif
+#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
+
+	printf( "GTK_TYPE_MOZ_EMBED:\n" );
+	show_type_signals( GTK_TYPE_MOZ_EMBED );
+
+	LEAVE("retval %p", self);
+}
+
+static void
+gnc_html_gtkmozembed_class_init( GncHtmlGtkmozembedClass* klass )
+{
+	GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+	GncHtmlClass* html_class = GNC_HTML_CLASS(klass);
+
+	gobject_class->dispose = gnc_html_gtkmozembed_dispose;
+	gobject_class->finalize = gnc_html_gtkmozembed_finalize;
+
+#if 0
+	html_class->show_url = impl_gtkmozembed_show_url;
+	html_class->show_data = impl_gtkmozembed_show_data;
+	html_class->reload = impl_gtkmozembed_reload;
+	html_class->copy = impl_gtkmozembed_copy;
+	html_class->export = impl_gtkmozembed_export;
+//	html_class->print = impl_gtkmozembed_print;
+	html_class->cancel = impl_gtkmozembed_cancel;
+	html_class->set_parent = impl_gtkmozembed_set_parent;
+#endif
+
+	// Initialize graphing support
+	gnc_html_graph_gog_gtkmozembed_init();
+}
+
+static void
+gnc_html_gtkmozembed_dispose( GObject* obj )
+{
+	GncHtmlGtkmozembed* self = GNC_HTML_GTKMOZEMBED(obj);
+	GncHtmlGtkmozembedPrivate* priv = GNC_HTML_GTKMOZEMBED_GET_PRIVATE(self);
+
+	if( priv->moz_embed != NULL ) {
+		g_object_unref( G_OBJECT(priv->moz_embed) );
+		priv->moz_embed = NULL;
+	}
+
+	G_OBJECT_CLASS(gnc_html_gtkmozembed_parent_class)->dispose( obj );
+}
+
+static void
+gnc_html_gtkmozembed_finalize( GObject* obj )
+{
+	GncHtmlGtkmozembed* self = GNC_HTML_GTKMOZEMBED(obj);
+
+//	if( self->priv != NULL ) {
+//		g_free( self->priv );
+		self->priv = NULL;
+//	}
+
+	G_OBJECT_CLASS(gnc_html_gtkmozembed_parent_class)->finalize( obj );
+}
+#if 0 /************************************/
+/*****************************************************************************/
+
+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 (!safe_strcmp (type, URL_TYPE_HTTP) ||
+			!safe_strcmp (type, URL_TYPE_SECURE) ||
+			!safe_strcmp (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;
+}
+
+/********************************************************************
+ * gnc_html_load_to_stream : actually do the work of loading the HTML
+ * or binary data referenced by a URL and feeding it into the GtkHTML
+ * widget.
+ ********************************************************************/
+
+static void
+gnc_html_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( "" );
+				webkit_web_view_load_html_string( priv->web_view, fdata, "base-uri" );
+			} 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" );
+			}
+
+			g_free( fdata );
+
+			if( label ) {
+				while( gtk_events_pending() ) {
+					gtk_main_iteration();
+				}
+//				gtk_html_jump_to_anchor( GTK_HTML(priv->html), label );
+				g_assert( FALSE );
+			}
+
+			return;
+		}
+	}
+
+	do {
+		if( !safe_strcmp( type, URL_TYPE_SECURE ) ||
+			!safe_strcmp( type, URL_TYPE_HTTP ) ) {
+
+			if( !safe_strcmp( type, URL_TYPE_SECURE ) ) {
+				if( !https_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+                            _("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,
+                          _("Network HTTP access is disabled. "
+                            "You can enable it in the Network section of "
+                            "the Preferences dialog."));
+			} else {
+				char *fullurl;
+
+				fullurl = 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" );
+			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 void
+webkit_navigation_requested_cb( WebKitWebView* web_view, GObject* arg1,
+												GObject* arg2, gpointer data )
+{
+	URLType type;
+	gchar* location = NULL;
+	gchar* label = NULL;
+	GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+	WebKitNetworkRequest* req = WEBKIT_NETWORK_REQUEST(arg2);
+	const gchar* url = webkit_network_request_get_uri( req );
+
+	DEBUG( "requesting %s", url );
+	type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
+	gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
+//	gnc_html_load_to_stream( self, type, location, label );
+	g_free( location );
+	g_free( label );
+}
+
+#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)
+ ********************************************************************/
+
+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;
+	}
+}
+
+/********************************************************************
+ * gnc_html_button_submit_cb
+ * form submission callback
+ ********************************************************************/
+
+#if 0
+static int
+gnc_html_submit_cb( GtkHTML* html, const gchar* method,
+                   const gchar* action, const gchar* encoded_form_data,
+                   gpointer user_data )
+{
+	GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+	gchar* location = NULL;
+	gchar* new_loc = NULL;
+	gchar* label = NULL;
+	GHashTable * form_data;
+	URLType  type;
+
+	DEBUG(" ");
+	form_data = gnc_html_unpack_form_data( encoded_form_data );
+	type = gnc_html_parse_url( GNC_HTML(self), action, &location, &label );
+
+	g_critical( "form submission hasn't been supported in years." );
+
+	g_free( location );
+	g_free( label );
+	g_free( new_loc );
+	gnc_html_free_form_data( form_data );
+	return TRUE;
+}
+#endif
+
+/********************************************************************
+ * 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 = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+	DEBUG( "datalen %d, data %20.20s", datalen, data );
+	webkit_web_view_load_html_string( priv->web_view, data, "base-uri" );
+}
+
+/********************************************************************
+ * 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 = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+	DEBUG(" ");
+
+	if( self == NULL ) return;
+	if( location == NULL ) return;
+
+	/* 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)" );
+
+			gnc_html_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( safe_strcmp( type, URL_TYPE_SCHEME ) == 0 ) {
+		gnc_html_open_scm( GNC_HTML_WEBKIT(self), location, label, new_window );
+
+	} else if( safe_strcmp( type, URL_TYPE_JUMP ) == 0 ) {
+//		gtk_html_jump_to_anchor( GTK_HTML(priv->html), label );
+		g_assert( FALSE );
+
+	} else if( safe_strcmp( type, URL_TYPE_SECURE ) == 0 ||
+				safe_strcmp( type, URL_TYPE_HTTP ) == 0 ||
+				safe_strcmp( type, URL_TYPE_FILE ) == 0 ) {
+
+		do {
+			if( safe_strcmp( type, URL_TYPE_SECURE ) == 0 ) {
+				if( !https_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+									_("Secure HTTP access is disabled. "
+									"You can enable it in the Network section of "
+									"the Preferences dialog.") );
+					break;
+				}
+			}
+
+			if( safe_strcmp( type, URL_TYPE_HTTP ) == 0 ) {
+				if( !http_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+									_("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 ) );
+			gnc_html_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
+ ********************************************************************/
+
+static void
+impl_webkit_reload( GncHtml* self )
+{
+	GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	gnc_html_history_node * n;
+
+	DEBUG(" ");
+	n = gnc_html_history_get_current( priv->base.history );
+	if( n != NULL ) {
+		gnc_html_show_url( self, n->type, n->location, n->label, 0 );
+	}
+}
+
+#endif
+/********************************************************************
+ * gnc_html_new
+ * create and set up a new webkit widget.
+ ********************************************************************/
+
+GncHtml*
+gnc_html_gtkmozembed_new( void )
+{
+	GncHtmlGtkmozembed* self = g_object_new( GNC_TYPE_HTML_GTKMOZEMBED, NULL );
+	GncHtmlGtkmozembedPrivate* priv = GNC_HTML_GTKMOZEMBED_GET_PRIVATE(self);
+
+	return GNC_HTML(self);
+}
+
+#if 0
+/********************************************************************
+ * 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 = 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( GncHtml* self )
+{
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_if_fail( self != NULL );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+//	gtk_html_copy( GTK_HTML(priv->html) );
+	g_assert( FALSE );
+}
+
+/**************************************************************
+ * gnc_html_export : wrapper around the builtin function in webkit
+ **************************************************************/
+
+static gboolean
+raw_html_receiver( gpointer engine,
+                   const gchar* data,
+                   size_t len,
+                   gpointer user_data )
+{
+	FILE *fh = (FILE *) user_data;
+	size_t written;
+
+	do {
+		written = fwrite (data, 1, len, fh);
+		len -= written;
+	} while (len > 0);
+	return TRUE;
+}
+
+static gboolean
+impl_webkit_export( GncHtml* self, const char *filepath )
+{
+	FILE *fh;
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_val_if_fail( self != NULL, FALSE );
+	g_return_val_if_fail( filepath != NULL, FALSE );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	fh = g_fopen( filepath, "w" );
+	if( fh == 0 )
+		return FALSE;
+
+//	gtk_html_save( GTK_HTML(priv->html), GINT_TO_POINTER(raw_html_receiver), fh );
+	g_assert( FALSE );
+	fclose (fh);
+
+	return TRUE;
+}
+
+#ifdef WEBKIT_USES_GTKPRINT
+static void
+draw_page_cb(GtkPrintOperation *operation, GtkPrintContext *context,
+             gint page_nr, gpointer user_data)
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+	GncHtmlWebkitPrivate* priv;
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+//    gtk_html_print_page( GTK_HTML(priv->html), context );
+	g_assert( FALSE );
+}
+
+static void
+impl_webkit_print( GncHtml* self )
+{
+    GtkPrintOperation *print;
+    GtkPrintOperationResult res;
+	GncHtmlWebkitPrivate* priv;
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    print = gtk_print_operation_new();
+
+    gnc_print_operation_init(print);
+    gtk_print_operation_set_use_full_page(print, FALSE);
+    gtk_print_operation_set_unit(print, GTK_UNIT_POINTS);
+    gtk_print_operation_set_n_pages(print, 1);
+    g_signal_connect(print, "draw_page", G_CALLBACK(draw_page_cb), self);
+
+    res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                  GTK_WINDOW(priv->base.parent), NULL);
+
+    if( res == GTK_PRINT_OPERATION_RESULT_APPLY ) {
+        gnc_print_operation_save_print_settings( print );
+	}
+
+    g_object_unref(print);
+}
+
+#else /* !WEBKIT_USES_GTKPRINT */
+#if 0
+void
+gnc_html_print( GncHtml* html )
+{
+	PrintSession *ps;
+
+	ps = gnc_print_session_create( FALSE );
+	if( ps == NULL ) {
+		/* user cancelled */
+		return;
+	}
+
+//	gtk_html_print( GTK_HTML(html->html), ps->context );
+	g_assert( FALSE );
+	gnc_print_session_done( ps );
+}
+#endif
+#endif /* WEBKIT_USES_GTKPRINT */
+
+static void
+impl_webkit_set_parent( GncHtml* self, GtkWindow* parent )
+{
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_if_fail( self != NULL );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	priv->base.parent = GTK_WIDGET(parent);
+}
+
+#if 0
+const gchar*
+gnc_html_get_embedded_param( gpointer eb, const gchar* param_name )
+{
+	GtkHTMLEmbedded* gtk_eb = (GtkHTMLEmbedded*)eb;
+
+	return (const gchar *)g_hash_table_lookup(gtk_eb->params, param_name);
+}
+#endif
+#endif

Added: gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-gtkmozembed.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,59 @@
+/********************************************************************
+ * gnc-html-gtkmozembed.h -- display html with gnc special tags     *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_GTKMOZEMBED_H
+#define GNC_HTML_GTKMOZEMBED_H
+
+#include <glib-object.h>
+#include "gnc-html.h"
+
+G_BEGIN_DECLS
+
+#define GNC_TYPE_HTML_GTKMOZEMBED       (gnc_html_gtkmozembed_get_type())
+#define GNC_HTML_GTKMOZEMBED(o)         (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_HTML_GTKMOZEMBED, GncHtmlGtkmozembed))
+#define GNC_HTML_GTKMOZEMBED_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_HTML_GTKMOZEMBED, GncHtmlGtkmozembedClass))
+#define GNC_IS_HTML_GTKMOZEMBED(o)      (G_TYPE_CHECK_INSTANCE_TYPE((o), GNC_TYPE_HTML_GTKMOZEMBED))
+#define GNC_IS_HTML_GTKMOZEMBED_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE((k), GNC_TYPE_HTML_GTKMOZEMBED))
+#define GNC_HTML_GTKMOZEMBED_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS((o), GNC_TYPE_HTML_GTKMOZEMBED, GncHtmlGtkmozembedClass))
+
+typedef struct _GncHtmlGtkmozembed GncHtmlGtkmozembed;
+typedef struct _GncHtmlGtkmozembedClass GncHtmlGtkmozembedClass;
+typedef struct _GncHtmlGtkmozembedPrivate GncHtmlGtkmozembedPrivate;
+
+struct _GncHtmlGtkmozembed {
+	GncHtml parent_instance;
+
+	/*< private >*/
+	GncHtmlGtkmozembedPrivate* priv;
+};
+
+struct _GncHtmlGtkmozembedClass {
+	GncHtmlClass parent_class;
+};
+
+GType gnc_html_gtkmozembed_get_type( void );
+
+GncHtml* gnc_html_gtkmozembed_new( void );
+
+G_END_DECLS
+
+#endif

Added: gnucash/branches/webkit/src/html/gnc-html-webkit-p.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-webkit-p.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-webkit-p.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,34 @@
+/********************************************************************
+ * gnc-html-webkit-p.h -- display html with gnc special tags        *
+ * 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                   *
+\********************************************************************/
+
+#ifndef GNC_HTML_WEBKIT_P_H
+#define GNC_HTML_WEBKIT_P_H
+
+#include "gnc-html-p.h"
+
+struct _GncHtmlWebkitPrivate {
+	struct _GncHtmlPrivate base;
+
+	WebKitWebView* web_view;				/* webkit widget itself */
+};
+
+#endif

Added: gnucash/branches/webkit/src/html/gnc-html-webkit.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-webkit.c	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-webkit.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,944 @@
+/********************************************************************
+ * gnc-html_webkit.c -- display HTML with some special gnucash tags.*
+ *                                                                  *
+ * 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 <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 <libguile.h>
+
+#include <webkit/webkit.h>
+
+#include "Account.h"
+#include "print-session.h"
+#include "gnc-engine.h"
+#include "gnc-gui-query.h"
+#include "gnc-html.h"
+#include "gnc-html-webkit.h"
+#include "gnc-html-history.h"
+#include "gnc-html-graph-gog-webkit.h"
+#include "gnc-ui.h"
+#include "gnc-ui-util.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) (G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_HTML_WEBKIT, GncHtmlWebkitPrivate))
+#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 an action name from a FORM definition to a handler function.
+ * <form method=METHOD action=gnc-action:ACTION-NAME?ACTION-ARGS>
+ * action-args is what gets passed to the handler. */
+extern GHashTable* gnc_html_action_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.");
+
+static void webkit_navigation_requested_cb( WebKitWebView* web_view, GObject* arg1,
+												GObject* arg2, gpointer data );
+static void webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url,
+							gpointer data );
+#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
+static int gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
+                         gpointer user_data );
+#if 0
+static int gnc_html_submit_cb( GtkHTML* html, const gchar* method,
+                   const gchar* action, const gchar* encoded_form_data,
+                   gpointer user_data );
+#endif
+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 );
+static void impl_webkit_copy( GncHtml* self );
+static gboolean impl_webkit_export( GncHtml* self, const gchar* filepath );
+static void impl_webkit_print( GncHtml* self );
+static void impl_webkit_cancel( GncHtml* self );
+static void impl_webkit_set_parent( GncHtml* self, GtkWindow* parent );
+
+static void
+gnc_html_webkit_init( GncHtmlWebkit* self )
+{
+	GncHtmlWebkitPrivate* priv;
+	GncHtmlWebkitPrivate* new_priv;
+
+	new_priv = g_realloc( GNC_HTML(self)->priv, sizeof(GncHtmlWebkitPrivate) );
+	priv = self->priv = new_priv;
+
+	priv->web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+
+	gtk_container_add( GTK_CONTAINER(priv->base.container),
+						GTK_WIDGET(priv->web_view) );
+
+#ifdef HAVE_GTK_2_10
+	g_object_ref_sink( priv->base.container );
+#else
+	g_object_ref( priv->base.container );
+	gtk_object_sink( GTK_OBJECT(priv->base.container) );
+#endif
+
+	/* 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
+
+	printf( "WEBKIT_TYPE_WEB_VIEW:\n" );
+	show_type_signals( WEBKIT_TYPE_WEB_VIEW );
+	printf( "WEBKIT_TYPE_WEB_FRAME:\n" );
+	show_type_signals( WEBKIT_TYPE_WEB_FRAME );
+
+	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 = impl_webkit_copy;
+	html_class->export = impl_webkit_export;
+//	html_class->print = impl_webkit_print;
+	html_class->cancel = impl_webkit_cancel;
+	html_class->set_parent = impl_webkit_set_parent;
+
+	// Initialize graphing support
+	gnc_html_graph_gog_webkit_init();
+}
+
+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 ) {
+		g_object_unref( G_OBJECT(priv->web_view) );
+		priv->web_view = NULL;
+	}
+
+	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 (!safe_strcmp (type, URL_TYPE_HTTP) ||
+			!safe_strcmp (type, URL_TYPE_SECURE) ||
+			!safe_strcmp (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;
+}
+
+/********************************************************************
+ * gnc_html_load_to_stream : actually do the work of loading the HTML
+ * or binary data referenced by a URL and feeding it into the GtkHTML
+ * widget.
+ ********************************************************************/
+
+static void
+gnc_html_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( "" );
+				webkit_web_view_load_html_string( priv->web_view, fdata, "base-uri" );
+			} 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" );
+			}
+
+			g_free( fdata );
+
+			if( label ) {
+				while( gtk_events_pending() ) {
+					gtk_main_iteration();
+				}
+//				gtk_html_jump_to_anchor( GTK_HTML(priv->html), label );
+				g_assert( FALSE );
+			}
+
+			return;
+		}
+	}
+
+	do {
+		if( !safe_strcmp( type, URL_TYPE_SECURE ) ||
+			!safe_strcmp( type, URL_TYPE_HTTP ) ) {
+
+			if( !safe_strcmp( type, URL_TYPE_SECURE ) ) {
+				if( !https_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+                            _("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,
+                          _("Network HTTP access is disabled. "
+                            "You can enable it in the Network section of "
+                            "the Preferences dialog."));
+			} else {
+				char *fullurl;
+
+				fullurl = 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" );
+			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 void
+webkit_navigation_requested_cb( WebKitWebView* web_view, GObject* arg1,
+												GObject* arg2, gpointer data )
+{
+	URLType type;
+	gchar* location = NULL;
+	gchar* label = NULL;
+	GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
+	WebKitNetworkRequest* req = WEBKIT_NETWORK_REQUEST(arg2);
+	const gchar* url = webkit_network_request_get_uri( req );
+
+	DEBUG( "requesting %s", url );
+	type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
+	gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
+//	gnc_html_load_to_stream( self, type, location, label );
+	g_free( location );
+	g_free( label );
+}
+
+#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)
+ ********************************************************************/
+
+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;
+	}
+}
+
+/********************************************************************
+ * gnc_html_button_submit_cb
+ * form submission callback
+ ********************************************************************/
+
+#if 0
+static int
+gnc_html_submit_cb( GtkHTML* html, const gchar* method,
+                   const gchar* action, const gchar* encoded_form_data,
+                   gpointer user_data )
+{
+	GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+	gchar* location = NULL;
+	gchar* new_loc = NULL;
+	gchar* label = NULL;
+	GHashTable * form_data;
+	URLType  type;
+
+	DEBUG(" ");
+	form_data = gnc_html_unpack_form_data( encoded_form_data );
+	type = gnc_html_parse_url( GNC_HTML(self), action, &location, &label );
+
+	g_critical( "form submission hasn't been supported in years." );
+
+	g_free( location );
+	g_free( label );
+	g_free( new_loc );
+	gnc_html_free_form_data( form_data );
+	return TRUE;
+}
+#endif
+
+/********************************************************************
+ * 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 = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+	DEBUG( "datalen %d, data %20.20s", datalen, data );
+	webkit_web_view_load_html_string( priv->web_view, data, "base-uri" );
+}
+
+/********************************************************************
+ * 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 = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+	DEBUG(" ");
+
+	if( self == NULL ) return;
+	if( location == NULL ) return;
+
+	/* 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)" );
+
+			gnc_html_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( safe_strcmp( type, URL_TYPE_SCHEME ) == 0 ) {
+		gnc_html_open_scm( GNC_HTML_WEBKIT(self), location, label, new_window );
+
+	} else if( safe_strcmp( type, URL_TYPE_JUMP ) == 0 ) {
+//		gtk_html_jump_to_anchor( GTK_HTML(priv->html), label );
+		g_assert( FALSE );
+
+	} else if( safe_strcmp( type, URL_TYPE_SECURE ) == 0 ||
+				safe_strcmp( type, URL_TYPE_HTTP ) == 0 ||
+				safe_strcmp( type, URL_TYPE_FILE ) == 0 ) {
+
+		do {
+			if( safe_strcmp( type, URL_TYPE_SECURE ) == 0 ) {
+				if( !https_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+									_("Secure HTTP access is disabled. "
+									"You can enable it in the Network section of "
+									"the Preferences dialog.") );
+					break;
+				}
+			}
+
+			if( safe_strcmp( type, URL_TYPE_HTTP ) == 0 ) {
+				if( !http_allowed() ) {
+					gnc_error_dialog( priv->base.parent,
+									_("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 ) );
+			gnc_html_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
+ ********************************************************************/
+
+static void
+impl_webkit_reload( GncHtml* self )
+{
+	GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	gnc_html_history_node * n;
+
+	DEBUG(" ");
+	n = gnc_html_history_get_current( priv->base.history );
+	if( n != NULL ) {
+		gnc_html_show_url( self, n->type, n->location, n->label, 0 );
+	}
+}
+
+
+/********************************************************************
+ * 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 );
+	GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+
+	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 = 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( GncHtml* self )
+{
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_if_fail( self != NULL );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+//	gtk_html_copy( GTK_HTML(priv->html) );
+	g_assert( FALSE );
+}
+
+/**************************************************************
+ * gnc_html_export : wrapper around the builtin function in webkit
+ **************************************************************/
+
+static gboolean
+raw_html_receiver( gpointer engine,
+                   const gchar* data,
+                   size_t len,
+                   gpointer user_data )
+{
+	FILE *fh = (FILE *) user_data;
+	size_t written;
+
+	do {
+		written = fwrite (data, 1, len, fh);
+		len -= written;
+	} while (len > 0);
+	return TRUE;
+}
+
+static gboolean
+impl_webkit_export( GncHtml* self, const char *filepath )
+{
+	FILE *fh;
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_val_if_fail( self != NULL, FALSE );
+	g_return_val_if_fail( filepath != NULL, FALSE );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	fh = g_fopen( filepath, "w" );
+	if( fh == 0 )
+		return FALSE;
+
+//	gtk_html_save( GTK_HTML(priv->html), GINT_TO_POINTER(raw_html_receiver), fh );
+	g_assert( FALSE );
+	fclose (fh);
+
+	return TRUE;
+}
+
+#ifdef WEBKIT_USES_GTKPRINT
+static void
+draw_page_cb(GtkPrintOperation *operation, GtkPrintContext *context,
+             gint page_nr, gpointer user_data)
+{
+    GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
+	GncHtmlWebkitPrivate* priv;
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+//    gtk_html_print_page( GTK_HTML(priv->html), context );
+	g_assert( FALSE );
+}
+
+static void
+impl_webkit_print( GncHtml* self )
+{
+    GtkPrintOperation *print;
+    GtkPrintOperationResult res;
+	GncHtmlWebkitPrivate* priv;
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+    print = gtk_print_operation_new();
+
+    gnc_print_operation_init(print);
+    gtk_print_operation_set_use_full_page(print, FALSE);
+    gtk_print_operation_set_unit(print, GTK_UNIT_POINTS);
+    gtk_print_operation_set_n_pages(print, 1);
+    g_signal_connect(print, "draw_page", G_CALLBACK(draw_page_cb), self);
+
+    res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                  GTK_WINDOW(priv->base.parent), NULL);
+
+    if( res == GTK_PRINT_OPERATION_RESULT_APPLY ) {
+        gnc_print_operation_save_print_settings( print );
+	}
+
+    g_object_unref(print);
+}
+
+#else /* !WEBKIT_USES_GTKPRINT */
+#if 0
+void
+gnc_html_print( GncHtml* html )
+{
+	PrintSession *ps;
+
+	ps = gnc_print_session_create( FALSE );
+	if( ps == NULL ) {
+		/* user cancelled */
+		return;
+	}
+
+//	gtk_html_print( GTK_HTML(html->html), ps->context );
+	g_assert( FALSE );
+	gnc_print_session_done( ps );
+}
+#endif
+#endif /* WEBKIT_USES_GTKPRINT */
+
+static void
+impl_webkit_set_parent( GncHtml* self, GtkWindow* parent )
+{
+	GncHtmlWebkitPrivate* priv;
+
+	g_return_if_fail( self != NULL );
+
+	priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
+	priv->base.parent = GTK_WIDGET(parent);
+}
+
+#if 0
+const gchar*
+gnc_html_get_embedded_param( gpointer eb, const gchar* param_name )
+{
+	GtkHTMLEmbedded* gtk_eb = (GtkHTMLEmbedded*)eb;
+
+	return (const gchar *)g_hash_table_lookup(gtk_eb->params, param_name);
+}
+#endif

Added: gnucash/branches/webkit/src/html/gnc-html-webkit.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html-webkit.h	                        (rev 0)
+++ gnucash/branches/webkit/src/html/gnc-html-webkit.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -0,0 +1,59 @@
+/********************************************************************
+ * gnc-html-webkit.h -- display html with gnc special tags          *
+ * 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                   *
+\********************************************************************/
+
+#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
+
+#endif

Modified: gnucash/branches/webkit/src/html/gnc-html.c
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html.c	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html.c	2009-03-28 17:33:30 UTC (rev 18003)
@@ -49,7 +49,7 @@
 #include "gnc-gui-query.h"
 #include "gnc-html.h"
 #include "gnc-html-history.h"
-#include "gnc-html-graph-gog.h"
+//#include "gnc-html-graph-gog.h"
 #include "gnc-ui.h"
 #include "gnc-ui-util.h"
 
@@ -58,22 +58,25 @@
 
 /* hashes for URLType -> protocol and protocol -> URLType */
 static GHashTable * gnc_html_type_to_proto_hash = NULL;
-static GHashTable * gnc_html_proto_to_type_hash = NULL;
+GHashTable * gnc_html_proto_to_type_hash = NULL;
 
 /* hashes an HTML <object classid="ID"> classid to a handler function */
-extern GHashTable* gnc_html_object_handlers;
+GHashTable* gnc_html_object_handlers = NULL;
 
 /* hashes an action name from a FORM definition to a handler function.
  * <form method=METHOD action=gnc-action:ACTION-NAME?ACTION-ARGS>
  * action-args is what gets passed to the handler. */
-static GHashTable * gnc_html_action_handlers = NULL;
+GHashTable* gnc_html_action_handlers = NULL;
 
 /* hashes handlers for loading different URLType data */
-static GHashTable * gnc_html_stream_handlers = NULL;
+GHashTable* gnc_html_stream_handlers = NULL;
 
 /* hashes handlers for handling different URLType data */
-GHashTable * gnc_html_url_handlers = NULL;
+GHashTable* gnc_html_url_handlers = NULL;
 
+/* hashes an HTML <object classid="ID"> classid to a handler function */
+extern GHashTable* gnc_html_object_handlers;
+
 static char error_404_format[] =
 "<html><body><h3>%s</h3><p>%s</body></html>";
 static char error_404_title[] = N_("Not found");
@@ -161,6 +164,29 @@
 
 /***********************************************************************************/
 
+static char*
+extract_machine_name( const gchar* path )
+{
+	gchar machine_rexp[] = "^(//[^/]*)/*(.*)?$";
+	regex_t compiled_m;
+	regmatch_t match[4];
+	gchar* machine = NULL;
+
+	if( path == NULL ) return NULL;
+
+	regcomp( &compiled_m, machine_rexp, REG_EXTENDED );
+
+	/* 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 );
+		}
+	}
+	return machine;
+}
+
 /********************************************************************
  * gnc_html_parse_url
  * this takes a URL and determines the protocol type, location, and
@@ -171,9 +197,105 @@
 gnc_html_parse_url( GncHtml* self, const gchar* url,
 					gchar** url_location, gchar** url_label )
 {
+	gchar uri_rexp[] = "^(([^:][^:]+):)?([^#]+)?(#(.*))?$";
+	regex_t compiled;
+	regmatch_t match[6];
+	gchar* protocol = NULL;
+	gchar* path = NULL;
+	gchar* label = NULL;
+	gboolean found_protocol = FALSE;
+	gboolean found_path = FALSE;
+	gboolean found_label = FALSE;
+	URLType retval;
+	GncHtmlPrivate* priv = GNC_HTML_GET_PRIVATE(self);
+
 	g_return_val_if_fail( GNC_IS_HTML(self), NULL );
 
-	return GNC_HTML_GET_CLASS(self)->parse_url( self, url, url_location, url_label );
+	DEBUG( "parsing %s, base_location %s",
+			url ? url : "(null)",
+			self ? (priv->base_location ? priv->base_location
+										: "(null base_location)")
+				: "(null html)");
+
+	regcomp( &compiled, uri_rexp, REG_EXTENDED );
+
+	if( !regexec( &compiled, url, 6, match, 0 ) ) {
+		if( match[2].rm_so != -1 ) {
+			protocol = g_new0( gchar, match[2].rm_eo - match[2].rm_so + 1 );
+			strncpy( protocol, url + match[2].rm_so, match[2].rm_eo - match[2].rm_so );
+			protocol[match[2].rm_eo - match[2].rm_so] = 0;
+			found_protocol = TRUE;
+		}
+		if( match[3].rm_so != -1 ) {
+			path = g_new0( gchar, match[3].rm_eo - match[3].rm_so + 1 );
+			strncpy( path, url+match[3].rm_so, match[3].rm_eo - match[3].rm_so );
+			path[match[3].rm_eo - match[3].rm_so] = 0;
+			found_path = TRUE;
+		}
+		if( match[5].rm_so != -1 ) {
+			label = g_new0( gchar, match[5].rm_eo - match[5].rm_so + 1 );
+			strncpy( label, url+match[5].rm_so, match[5].rm_eo - match[5].rm_so );
+			label[match[5].rm_eo - match[5].rm_so] = 0;
+			found_label = TRUE;
+		}
+	}
+
+	regfree( &compiled );
+
+	if( found_protocol ) {
+		retval = g_hash_table_lookup( gnc_html_proto_to_type_hash, protocol );
+		if( retval == NULL ) {
+			PWARN( "unhandled URL type for '%s'", url ? url : "(null)" );
+			retval = URL_TYPE_OTHER;
+		}
+	} else if( found_label && !found_path ) {
+		retval = URL_TYPE_JUMP;
+	} else {
+		if( self ) {
+			retval = priv->base_type;
+		} else {
+			retval = URL_TYPE_FILE;
+		}
+	}
+
+	g_free( protocol );
+
+	if( !safe_strcmp( retval, URL_TYPE_FILE ) ) {
+		if( !found_protocol && path && self && priv->base_location ) {
+			if( g_path_is_absolute( path ) ) {
+				*url_location = g_strdup( path );
+			} else {
+				*url_location = g_build_filename( priv->base_location, path, (gchar*)NULL );
+			}
+			g_free( path );
+		} else {
+			*url_location = g_strdup( path );
+			g_free( path );
+		}
+
+	} else if( !safe_strcmp( retval, URL_TYPE_JUMP ) ) {
+		*url_location = NULL;
+		g_free( path );
+
+	} else {
+		/* case URL_TYPE_OTHER: */
+
+		if( !found_protocol && path && self && priv->base_location ) {
+			if( g_path_is_absolute( path ) ) {
+				*url_location = g_build_filename( extract_machine_name( priv->base_location ),
+                           path, (gchar*)NULL );
+			} else {
+				*url_location = g_build_filename( priv->base_location, path, (gchar*)NULL );
+			}
+			g_free( path );
+		} else {
+			*url_location = g_strdup( path );
+			g_free( path );
+		}
+	}
+
+	*url_label = label;
+	return retval;
 }
 
 /********************************************************************
@@ -340,3 +462,443 @@
 	g_return_if_fail( GNC_IS_HTML(self) );
 	GNC_HTML_GET_CLASS(self)->set_parent( self, parent );
 }
+
+/* Register the URLType if it doesn't already exist.
+ * Returns TRUE if successful, FALSE if the type already exists.
+ */
+gboolean
+gnc_html_register_urltype( URLType type, const char *protocol )
+{
+  if (!gnc_html_type_to_proto_hash) {
+    gnc_html_type_to_proto_hash = g_hash_table_new (g_str_hash, g_str_equal);
+    gnc_html_proto_to_type_hash = g_hash_table_new (g_str_hash, g_str_equal);
+  }
+  if (!protocol) return FALSE;
+  if (g_hash_table_lookup (gnc_html_type_to_proto_hash, type))
+    return FALSE;
+
+  g_hash_table_insert (gnc_html_type_to_proto_hash, type, (gpointer)protocol);
+  if (*protocol)
+    g_hash_table_insert (gnc_html_proto_to_type_hash, (gpointer)protocol, type);
+
+  return TRUE;
+}
+
+void
+gnc_html_initialize (void)
+{
+  int i;
+  static struct {
+    URLType	type;
+    char *	protocol;
+  } types[] = {
+    { URL_TYPE_FILE, "file" },
+    { URL_TYPE_JUMP, "" },
+    { URL_TYPE_HTTP, "http" },
+    { URL_TYPE_FTP, "ftp" },
+    { URL_TYPE_SECURE, "https" },
+    { URL_TYPE_REGISTER, "gnc-register" },
+    { URL_TYPE_ACCTTREE, "gnc-acct-tree" },
+    { URL_TYPE_REPORT, "gnc-report" },
+    { URL_TYPE_OPTIONS, "gnc-options" },
+    { URL_TYPE_SCHEME, "gnc-scm" },
+    { URL_TYPE_HELP, "gnc-help" },
+    { URL_TYPE_XMLDATA, "gnc-xml" },
+    { URL_TYPE_PRICE, "gnc-price" },
+    { URL_TYPE_BUDGET, "gnc-budget" },
+    { URL_TYPE_OTHER, "" },
+    { NULL, NULL }};
+
+  for (i = 0; types[i].type; i++)
+    gnc_html_register_urltype (types[i].type, types[i].protocol);
+}
+
+char  *
+gnc_build_url (URLType type, const gchar * location, const gchar * label)
+{
+  char * type_name;
+
+  DEBUG(" ");
+  type_name = g_hash_table_lookup (gnc_html_type_to_proto_hash, type);
+  if (!type_name)
+    type_name = "";
+
+  if(label) {
+    return g_strdup_printf("%s%s%s#%s", type_name, (*type_name ? ":" : ""),
+                           (location ? location : ""),
+                           label ? label : "");
+  }
+  else {
+    return g_strdup_printf("%s%s%s", type_name, (*type_name ? ":" : ""),
+                           (location ? location : ""));
+  }
+}
+
+/********************************************************************
+ * gnc_html_pack/unpack_form_data
+ * convert an encoded arg string to/from a name-value hash table
+ ********************************************************************/
+
+GHashTable *
+gnc_html_unpack_form_data(const char * encoding)
+{
+  GHashTable * rv;
+
+  DEBUG(" ");
+  rv = g_hash_table_new(g_str_hash, g_str_equal);
+  gnc_html_merge_form_data(rv, encoding);
+  return rv;
+}
+
+void
+gnc_html_merge_form_data(GHashTable * rv, const char * encoding)
+{
+  char * next_pair = NULL;
+  char * name  = NULL;
+  char * value = NULL;
+  char * extr_name  = NULL;
+  char * extr_value = NULL;
+
+  DEBUG(" ");
+  if(!encoding) {
+    return;
+  }
+  next_pair = g_strdup(encoding);
+
+  while(next_pair) {
+    name = next_pair;
+    if((value = strchr(name, '=')) != NULL) {
+      extr_name = g_strndup(name, value-name);
+      next_pair = strchr(value, '&');
+      if(next_pair) {
+        extr_value = g_strndup(value+1, next_pair-value-1);
+        next_pair++;
+      }
+      else {
+        extr_value = g_strdup(value+1);
+      }
+
+      g_hash_table_insert(rv,
+                          gnc_html_decode_string(extr_name),
+                          gnc_html_decode_string(extr_value));
+      g_free(extr_name);
+      g_free(extr_value);
+    }
+    else {
+      next_pair = NULL;
+    }
+  }
+}
+
+static gboolean
+free_form_data_helper(gpointer k, gpointer v, gpointer user)
+{
+  DEBUG(" ");
+  g_free(k);
+  g_free(v);
+  return TRUE;
+}
+
+void
+gnc_html_free_form_data(GHashTable * d)
+{
+  DEBUG(" ");
+  g_hash_table_foreach_remove(d, free_form_data_helper, NULL);
+  g_hash_table_destroy(d);
+}
+
+static void
+pack_form_data_helper(gpointer key, gpointer val,
+                      gpointer user_data)
+{
+  char * old_str = *(char **)user_data;
+  char * enc_key = gnc_html_encode_string((char *)key);
+  char * enc_val = gnc_html_encode_string((char *)val);
+  char * new_str = NULL;
+
+  DEBUG(" ");
+  if(old_str) {
+    new_str = g_strconcat(old_str, "&", enc_key, "=", enc_val, NULL);
+  }
+  else {
+    new_str = g_strconcat(enc_key, "=", enc_val, NULL);
+  }
+  *(char **)user_data = new_str;
+  g_free(old_str);
+}
+
+char *
+gnc_html_pack_form_data(GHashTable * form_data)
+{
+  char * encoded = NULL;
+  DEBUG(" ");
+  g_hash_table_foreach(form_data, pack_form_data_helper, &encoded);
+  return encoded;
+}
+
+/********************************************************************
+ * gnc_html_encode_string
+ * RFC 1738 encoding of string for submission with an HTML form.
+ * GPL code lifted from gtkhtml.  copyright notice:
+ *
+ * Copyright (C) 1997 Martin Jones (mjones at kde.org)
+ * Copyright (C) 1997 Torben Weis (weis at kde.org)
+ * Copyright (C) 1999 Helix Code, Inc.
+ ********************************************************************/
+
+char *
+gnc_html_encode_string(const char * str)
+{
+  static gchar *safe = "$-._!*(),"; /* RFC 1738 */
+  unsigned pos      = 0;
+  GString *encoded  = g_string_new ("");
+  gchar buffer[5], *ptr;
+  guchar c;
+
+  if(!str) return NULL;
+
+  while(pos < strlen(str)) {
+    c = (unsigned char) str[pos];
+
+    if ((( c >= 'A') && ( c <= 'Z')) ||
+        (( c >= 'a') && ( c <= 'z')) ||
+        (( c >= '0') && ( c <= '9')) ||
+        (strchr(safe, c))) {
+      encoded = g_string_append_c (encoded, c);
+    }
+    else if ( c == ' ' ) {
+      encoded = g_string_append_c (encoded, '+');
+    }
+    else if ( c == '\n' ) {
+      encoded = g_string_append (encoded, "%0D%0A");
+    }
+    else if ( c != '\r' ) {
+      sprintf( buffer, "%%%02X", (int)c );
+      encoded = g_string_append (encoded, buffer);
+    }
+    pos++;
+  }
+
+  ptr = encoded->str;
+
+  g_string_free (encoded, FALSE);
+
+  return (char *)ptr;
+}
+
+
+char *
+gnc_html_decode_string(const char * str)
+{
+  static gchar * safe = "$-._!*(),"; /* RFC 1738 */
+  GString * decoded  = g_string_new ("");
+  const gchar   * ptr;
+  guchar  c;
+  guint   hexval;
+  ptr = str;
+
+  if(!str) return NULL;
+
+  while(*ptr) {
+    c = (unsigned char) *ptr;
+    if ((( c >= 'A') && ( c <= 'Z')) ||
+        (( c >= 'a') && ( c <= 'z')) ||
+        (( c >= '0') && ( c <= '9')) ||
+        (strchr(safe, c))) {
+      decoded = g_string_append_c (decoded, c);
+    }
+    else if ( c == '+' ) {
+      decoded = g_string_append_c (decoded, ' ');
+    }
+    else if (!strncmp(ptr, "%0D0A", 5)) {
+      decoded = g_string_append (decoded, "\n");
+      ptr += 4;
+    }
+    else if(c == '%') {
+      ptr++;
+      if (1 == sscanf(ptr, "%02X", &hexval))
+	decoded = g_string_append_c(decoded, (char)hexval);
+      else
+	decoded = g_string_append_c(decoded, ' ');
+      ptr++;
+    }
+    ptr++;
+  }
+  ptr = decoded->str;
+  g_string_free (decoded, FALSE);
+
+  return (char *)ptr;
+}
+
+/********************************************************************
+ * escape/unescape_newlines : very simple string encoding for GPG
+ * ASCII-armored text.
+ ********************************************************************/
+
+char *
+gnc_html_unescape_newlines(const gchar * in)
+{
+  const char * ip = in;
+  char    * cstr = NULL;
+  GString * rv = g_string_new("");
+
+  for(ip=in; *ip; ip++) {
+    if((*ip == '\\') && (*(ip+1)=='n')) {
+      g_string_append(rv, "\n");
+      ip++;
+    }
+    else {
+      g_string_append_c(rv, *ip);
+    }
+  }
+
+  g_string_append_c(rv, 0);
+  cstr = rv->str;
+  g_string_free(rv, FALSE);
+  return cstr;
+}
+
+char *
+gnc_html_escape_newlines(const gchar * in)
+{
+  char *out;
+  const char * ip   = in;
+  GString * escaped = g_string_new("");
+
+  for(ip=in; *ip; ip++) {
+    if(*ip == '\012') {
+      g_string_append(escaped, "\\n");
+    }
+    else {
+      g_string_append_c(escaped, *ip);
+    }
+  }
+  g_string_append_c(escaped, 0);
+  out = escaped->str;
+  g_string_free(escaped, FALSE);
+  return out;
+}
+
+void
+gnc_html_register_object_handler( const char * classid,
+                                 GncHTMLObjectCB hand )
+{
+	g_return_if_fail( classid != NULL );
+
+	if( gnc_html_object_handlers == NULL ) {
+		gnc_html_object_handlers = g_hash_table_new( g_str_hash, g_str_equal );
+	}
+
+	gnc_html_unregister_object_handler( classid );
+	if( hand != NULL ) {
+		g_hash_table_insert( gnc_html_object_handlers, g_strdup( classid ), hand );
+	}
+}
+
+void
+gnc_html_unregister_object_handler( const gchar* classid )
+{
+	gchar* keyptr = NULL;
+	gchar* valptr = NULL;
+	gchar** p_keyptr = &keyptr;
+	gchar** p_valptr = &valptr;
+
+	if( g_hash_table_lookup_extended( gnc_html_object_handlers,
+											 classid,
+											(gpointer *)p_keyptr,
+											(gpointer *)p_valptr) ) {
+		g_hash_table_remove( gnc_html_object_handlers, classid );
+		g_free( keyptr );
+	}
+}
+
+void
+gnc_html_register_action_handler( const gchar* actionid,
+								GncHTMLActionCB hand )
+{
+	g_return_if_fail( actionid != NULL );
+
+	if( gnc_html_action_handlers == NULL ) {
+		gnc_html_action_handlers = g_hash_table_new( g_str_hash, g_str_equal );
+	}
+
+	gnc_html_unregister_action_handler( actionid );
+	if( hand != NULL ) {
+		g_hash_table_insert( gnc_html_action_handlers, g_strdup( actionid ), hand );
+	}
+}
+
+void
+gnc_html_unregister_action_handler( const gchar* actionid )
+{
+	gchar* keyptr = NULL;
+	gchar* valptr = NULL;
+	gchar** p_keyptr = &keyptr;
+	gchar** p_valptr = &valptr;
+
+	g_return_if_fail( actionid != NULL );
+
+	if( g_hash_table_lookup_extended( gnc_html_action_handlers,
+											actionid,
+											(gpointer *)p_keyptr,
+											(gpointer *)p_valptr) ) {
+		g_hash_table_remove( gnc_html_action_handlers, actionid );
+		g_free( keyptr );
+	}
+}
+
+void
+gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand )
+{
+	g_return_if_fail( url_type != NULL && *url_type != '\0' );
+
+	if( gnc_html_stream_handlers == NULL ) {
+		gnc_html_stream_handlers = g_hash_table_new( g_str_hash, g_str_equal );
+	}
+
+	gnc_html_unregister_stream_handler( url_type );
+	if( hand != NULL ) {
+		g_hash_table_insert( gnc_html_stream_handlers, url_type, hand );
+	}
+}
+
+void
+gnc_html_unregister_stream_handler( URLType url_type )
+{
+	g_hash_table_remove( gnc_html_stream_handlers, url_type );
+}
+
+void
+gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand )
+{
+	g_return_if_fail( url_type != NULL && *url_type != '\0' );
+
+	if( gnc_html_url_handlers == NULL ) {
+		gnc_html_url_handlers = g_hash_table_new( g_str_hash, g_str_equal );
+	}
+
+	gnc_html_unregister_url_handler( url_type );
+	if( hand != NULL ) {
+		g_hash_table_insert( gnc_html_url_handlers, url_type, hand );
+	}
+}
+
+void
+gnc_html_unregister_url_handler( URLType url_type )
+{
+	g_hash_table_remove( gnc_html_url_handlers, url_type );
+}
+
+void show_type_signals( GType t )
+{
+	guint* signals;
+	guint n_ids;
+	guint i;
+	GSignalQuery sig;
+
+	signals = g_signal_list_ids( t, &n_ids );
+	for( i = 0; i < n_ids; i++ ) {
+		g_signal_query( signals[i], &sig );
+		printf( "Signal: %s\n", sig.signal_name );
+	}
+}

Modified: gnucash/branches/webkit/src/html/gnc-html.h
===================================================================
--- gnucash/branches/webkit/src/html/gnc-html.h	2009-03-27 01:43:23 UTC (rev 18002)
+++ gnucash/branches/webkit/src/html/gnc-html.h	2009-03-28 17:33:30 UTC (rev 18003)
@@ -41,7 +41,6 @@
 typedef struct _GncHtmlPrivate GncHtmlPrivate;
 
 #include "gnc-html-extras.h"
-#include "gnc-html-history.h"
 
 /* The result structure of url handlers. Strings should be g_malloc'd
  * by the handler and will be freed by gnc_html. */
@@ -66,6 +65,57 @@
 	gchar* error_message;
 } GNCURLResult;
 
+typedef gboolean (* GncHTMLObjectCB)(GncHtml* html, gpointer eb,
+                                 gpointer data); 
+typedef int  (* GncHTMLActionCB)(GncHtml* html, const gchar* method,
+                                 const gchar* action, GHashTable* form_data);
+typedef gboolean (* GncHTMLStreamCB)(const gchar* location, gchar** data, int* datalen);
+typedef gboolean (* GncHTMLUrlCB)(const gchar* location, const gchar* label,
+                                  gboolean new_window, GNCURLResult* result);
+
+/* Register a new URLType.
+ * returns TRUE if succesful, FALSE if type already exists.
+ *
+ * protocol should be an empty string if there is no corresponding protocol.
+ * if protocol is NULL, this function returns FALSE.
+ */
+gboolean gnc_html_register_urltype( URLType type, const gchar* protocol );
+
+/* Initialize the html subsystem */
+void gnc_html_initialize( void );
+
+gchar* gnc_html_encode_string( const gchar* in );
+gchar* gnc_html_decode_string( const gchar* in );
+gchar* gnc_html_escape_newlines( const gchar* in );
+gchar* gnc_html_unescape_newlines( const gchar* in );
+
+/* utilities for dealing with encoded argument strings for forms */
+gchar* gnc_html_pack_form_data( GHashTable* form_data );
+GHashTable* gnc_html_unpack_form_data( const gchar* encoding );
+void gnc_html_merge_form_data( GHashTable* fdata, const gchar* enc );
+void gnc_html_free_form_data( GHashTable* fdata );
+
+/* object handlers deal with <object classid="foo"> objects in HTML.
+ * the handlers are looked up at object load time. */
+void gnc_html_register_object_handler( const gchar* classid, GncHTMLObjectCB hand );
+void gnc_html_unregister_object_handler( const gchar* classid );
+
+/* action handlers deal with submitting forms of the type 
+ * <FORM action="gnc-action:action?args">.  Normal get/post http:
+ * forms are handled as would be expected, with no callback. */
+void gnc_html_register_action_handler( const gchar* action, GncHTMLActionCB hand );
+void gnc_html_unregister_action_handler( const gchar* action );
+
+/* stream handlers load data for particular URLTypes. */
+void gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand );
+void gnc_html_unregister_stream_handler( URLType url_type );
+
+/* handlers for particular URLTypes. */
+void gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand );
+void gnc_html_unregister_url_handler( URLType url_type );
+
+#include "gnc-html-history.h"
+
 typedef int  (* GncHTMLUrltypeCB)(URLType ut);
 typedef void (* GncHTMLFlyoverCB)(GncHtml* html, const gchar* url,
                                   gpointer data);
@@ -75,15 +125,6 @@
 typedef int  (* GncHTMLButtonCB)(GncHtml* html, GdkEventButton* event,
                                  gpointer data);
 
-//typedef gboolean (* GncHTMLObjectCB)(GncHtml* html, GtkHTMLEmbedded* eb,
-typedef gboolean (* GncHTMLObjectCB)(GncHtml* html, gpointer eb,
-                                 gpointer data); 
-typedef int  (* GncHTMLActionCB)(GncHtml* html, const gchar* method,
-                                 const gchar* action, GHashTable* form_data);
-typedef gboolean (* GncHTMLStreamCB)(const gchar* location, gchar** data, int* datalen);
-typedef gboolean (* GncHTMLUrlCB)(const gchar* location, const gchar* label,
-                                  gboolean new_window, GNCURLResult* result);
-
 struct _GncHtmlClass
 {
 	GtkBinClass parent_class;
@@ -157,4 +198,6 @@
 
 const gchar* gnc_html_get_embedded_param( gpointer eb, const gchar* param_name );
 
+void show_type_signals( GType t );
+
 #endif



More information about the gnucash-changes mailing list