gtkhtml: [PATCH] <object> and <param>

Bill Gribble grib@gnumatic.com
Tue, 5 Dec 2000 12:18:33 -0600


This patch is critical for the release of gnucash, and I would
appreciate it if someone with CVS write access and the 'moral
authority' to make changes to gtkhtml could PLEASE have a look at it
and either commit it or tell me what's wrong with it.  It's small and
doesn't affect any files that have been recently changed in CVS.

I'm trying to use gtkhtml to embed some "special" objects in html
documents within gnucash.  In particular we are embedding Guppi charts
in our financial reports.  I find that gtkhtml isn't interpreting the
<param> tags and the body of the <object> form correctly.  The
specification for correct behavior is

  http://www.w3.org/TR/html4/struct/objects.html#h-13.3.2

Basically, the problem is this: <param> tags go INSIDE the body of the
<object>, but in gtkhtml the body is only interpreted if the user's
OBJECT_REQUESTED handler returns TRUE.

There are 2 problems with this: one is that the body of an <object> is
only supposed to be displayed if the object CANNOT be loaded (it's an
alternate-text thing).  Second is that any <param> tags need to be
read BEFORE the user's OBJECT_REQUESTED handler is called, because
that's the only chance the user will have to see both the classid and
the parameters to the object.

Attached below is a patch that addresses most of this problem, against
CVS of Fri Nov 17 11:02:28 CST 2000.  It just calls the parse_body
function before emitting the OBJECT_REQUESTED signal.  This gets the
<param> forms before the user sees the GtkHTMLEmbedded object.  It
still has the problem that the alt-text is displayed no matter what,
but that's no worse than the current situation (displays the alt-text
in exactly the opposite of the correct sense, and never gets the
<param> right).  I don't know enough about the guts of the gtkhtml
code to say "read the body and process the <param>, but only display
the text if you emit OBJECT_REQUESTED and get back FALSE."

The patch also adds support for the "data=" attribute in the <object>
and gets rid of the requirement for a classid, which isn't required by
the spec; the combination of data and no classid is similar to an
<iframe> if I understand it correctly. In any case the user gets to
handle that.

Please let me know if I need to improve this patch to get it into
gtkhtml.  Gnucash is depending on <object> functionality working, so I
can spend more time getting it right if that's what it takes.  I can
generally be found on #gnucash at irc.gnome.org.

Thanks,
Bill Gribble

--- htmlengine-orig.c	Fri Nov 17 10:57:22 2000
+++ htmlengine.c	Fri Nov 17 10:50:37 2000
@@ -1237,9 +1237,13 @@
 	char *name=NULL;
 	char *type = NULL;
 	char *str = NULL;
+	char *data = NULL;
 	int width=-1,height=-1;
 	static const gchar *end[] = { "</object", 0};
-
+	GtkHTMLEmbedded *eb;
+	HTMLEmbedded *el;
+	gboolean ret_val;
+	
 	
 	html_string_tokenizer_tokenize( e->st, attr, " >" );
 	
@@ -1259,41 +1263,36 @@
 			height = atoi (token + 7);
 		} else if (strncasecmp (token, "type=", 5) == 0) {
 			type = g_strdup (token + 5);
+		} else if (strncasecmp (token, "data=", 5) == 0) {
+			data = g_strdup (token + 5);
 		}
 	}
 
-	if (classid) {
-		GtkHTMLEmbedded *eb;
-		HTMLEmbedded *el;
-		gboolean ret_val;
-		
-		eb = (GtkHTMLEmbedded *) gtk_html_embedded_new (classid, name, type, width, height);
-		html_stack_push (e->embeddedStack, eb);
+	eb = (GtkHTMLEmbedded *) gtk_html_embedded_new (classid, name, type, data, width, height);
+	html_stack_push (e->embeddedStack, eb);
 
-		el = html_embedded_new_widget (GTK_WIDGET (e->widget), eb);		
-		gtk_object_set_data (GTK_OBJECT(eb), "embeddedelement", el);
-		gtk_signal_connect (GTK_OBJECT(eb), "changed", html_object_changed, e);
-		
-		ret_val = FALSE;
-		gtk_signal_emit (GTK_OBJECT (e), signals [OBJECT_REQUESTED], eb, &ret_val);
+	el = html_embedded_new_widget (GTK_WIDGET (e->widget), eb);		
+	gtk_object_set_data (GTK_OBJECT(eb), "embeddedelement", el);
+	gtk_signal_connect (GTK_OBJECT(eb), "changed", html_object_changed, e);
+	
+	str = parse_body (e, clue, end, FALSE);
+	
+	ret_val = FALSE;
+	gtk_signal_emit (GTK_OBJECT (e), signals [OBJECT_REQUESTED], eb, &ret_val);
+	
+	if (ret_val) {
+		append_element(e, clue, HTML_OBJECT(el));
+		/* automatically add this to a form if it is part of one */
+		if (e->form)
+			html_form_add_element (e->form, HTML_EMBEDDED (el));
 		
-		if (ret_val) {
-			append_element(e, clue, HTML_OBJECT(el));
-			/* automatically add this to a form if it is part of one */
-			if (e->form)
-				html_form_add_element (e->form, HTML_EMBEDDED (el));
-
-			str = parse_body (e, clue, end, FALSE);
-		} else {
-			html_object_destroy (HTML_OBJECT (el));
-			str = discard_body (e, end);
-		}
-
-		if ((!str || strncmp( str, "/object", 7 ) == 0)
-		    && (! html_stack_is_empty (e->embeddedStack)))
-			html_stack_pop (e->embeddedStack);
-	} else
-		g_warning("Object with no classid, ignored\n");
+	} else {
+		html_object_destroy (HTML_OBJECT (el));
+	}
+	
+	if ((!str || strncmp( str, "/object", 7 ) == 0)
+	    && (! html_stack_is_empty (e->embeddedStack)))
+		html_stack_pop (e->embeddedStack);
 	
 	g_free (classid);
 	g_free (name);
--- gtkhtml-embedded-orig.c	Fri Nov 17 10:57:22 2000
+++ gtkhtml-embedded.c	Fri Nov 17 09:59:10 2000
@@ -199,7 +199,7 @@
  * Return value: A new GtkHTMLEmbedded widget.
  **/
 GtkWidget *
-gtk_html_embedded_new (char *classid, char *name, char *type, int width, int height)
+gtk_html_embedded_new (char *classid, char *name, char *type, char *data, int width, int height)
 {
 	GtkHTMLEmbedded *em;
 
@@ -209,7 +209,7 @@
 	em->type = type ? g_strdup(type) : NULL;
 	em->classid = g_strdup(classid);
 	em->name = g_strdup(name);
-
+	em->data = g_strdup(data);
 	return (GtkWidget *)em;
 }
 
--- gtkhtml-embedded-orig.h	Fri Nov 17 10:57:22 2000
+++ gtkhtml-embedded.h	Fri Nov 17 10:06:01 2000
@@ -43,6 +43,7 @@
 	char *classid;
 	char *name;
         char *type;
+        char *data;
 
 	/* parameters to class */
 	int width, height;
@@ -63,7 +64,7 @@
    themselves for a form */
 
 guint		gtk_html_embedded_get_type	(void);
-GtkWidget	*gtk_html_embedded_new (char *classid, char *name, char *type, int width, int height);
+GtkWidget	*gtk_html_embedded_new (char *classid, char *name, char *type, char *data, int width, int height);
 
 void gtk_html_embedded_set_parameter (GtkHTMLEmbedded *ge, char *param, char *value);
 char *gtk_html_embedded_get_parameter (GtkHTMLEmbedded *ge, char *param);



----- End forwarded message -----