Logo Search packages:      
Sourcecode: galeon version File versions

gtkhtml-embed.c

/*
 *  Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
 *  Copyright (C) 2002 Tommi Komulainen
 *
 *  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, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "gtkhtml-embed.h"

#include <libgtkhtml/view/htmlview.h>
#include <libgnomevfs/gnome-vfs-async-ops.h>
#include <gtk/gtkmessagedialog.h>
#include <string.h>

#define BUFFER_SIZE     2048

typedef struct _Connection Connection;


static void
gtkhtml_embed_class_init (GtkhtmlEmbedClass *klass);
static void
gtkhtml_embed_init (GtkhtmlEmbed *gs);
static void
gtkhtml_embed_finalize (GObject *object);
static void
galeon_embed_init (GaleonEmbedClass *embed_class);

static void
impl_get_capabilities (GaleonEmbed *embed,
                       EmbedCapabilities *caps);
static gresult 
impl_load_url (GaleonEmbed *embed, 
               const char *url);
static gresult 
impl_stop_load (GaleonEmbed *embed);
static gresult 
impl_can_go_back (GaleonEmbed *embed);
static gresult 
impl_can_go_forward (GaleonEmbed *embed);
static gresult 
impl_can_go_up (GaleonEmbed *embed);
static gresult 
impl_get_go_up_list (GaleonEmbed *embed, GSList **l);
static gresult 
impl_go_back (GaleonEmbed *embed);
static gresult  
impl_go_forward (GaleonEmbed *embed);
static gresult
impl_go_up (GaleonEmbed *embed);
static gresult 
impl_render_data (GaleonEmbed *embed, 
                  const char *data,
                  guint32 len,
                  const char *base_uri, 
                  const char *mime_type);
static gresult
impl_open_stream (GaleonEmbed *embed,
                  const char *base_uri,
                  const char *mime_type);
static gresult
impl_append_data (GaleonEmbed *embed,
                  const char *data, 
                  guint32 len);
static gresult
impl_close_stream (GaleonEmbed *embed);
static gresult
impl_get_title (GaleonEmbed *embed,
                char **title);
static gresult 
impl_get_location (GaleonEmbed *embed, 
                   gboolean toplevel,
                   gboolean requested,
                   char **location);
static gresult 
impl_reload (GaleonEmbed *embed, 
             EmbedReloadFlags flags);
static gresult
impl_copy_page (GaleonEmbed *dest,
                GaleonEmbed *source,
                EmbedDisplayType display_type);
static gresult 
impl_grab_focus (GaleonEmbed *embed);
static gresult
impl_get_favicon_location (GaleonEmbed *embed,
                           char **url);
static gresult
impl_get_link_tags (GaleonEmbed *embed,
                    const char *link_type,
                    GList **tags);
static gresult
impl_zoom_set (GaleonEmbed *embed, 
               int zoom, 
               gboolean reflow);
static gresult
impl_zoom_get (GaleonEmbed *embed,
               int *zoom);
static gresult 
impl_selection_can_cut (GaleonEmbed *embed);
static gresult 
impl_selection_can_copy (GaleonEmbed *embed);
static gresult 
impl_can_paste (GaleonEmbed *embed);
static gresult
impl_selection_cut (GaleonEmbed *embed);
static gresult
impl_selection_copy (GaleonEmbed *embed);
static gresult
impl_paste (GaleonEmbed *embed);
static gresult
impl_shistory_count  (GaleonEmbed *embed,
                      int *count);
static gresult
impl_shistory_get_nth (GaleonEmbed *embed, 
                       int nth,
                       gboolean is_relative,
                       char **url,
                       char **title);
static gresult
impl_shistory_get_pos (GaleonEmbed *embed,
                       int *pos);
static gresult
impl_shistory_go_nth (GaleonEmbed *embed, 
                      int nth);
static gboolean
impl_shistory_copy (GaleonEmbed *source,
                    GaleonEmbed *dest);
static gresult
impl_shistory_clear (GaleonEmbed *source);

static gresult
impl_scroll (GaleonEmbed *embed, 
             EmbedScrollDirection direction);
static gresult
impl_get_security_level (GaleonEmbed *embed, 
                         EmbedSecurityLevel level,
                         char **description);
static gresult
impl_find (GaleonEmbed *embed,
           EmbedFindInfo *info);
static gresult
impl_print (GaleonEmbed *embed, 
            EmbedPrintInfo *info);
static gresult
impl_print_preview_close (GaleonEmbed *embed);
static gresult
impl_print_preview_num_pages (GaleonEmbed *embed,
                              gint *retNum);
static gresult
impl_print_preview_navigate (GaleonEmbed *embed,
                             EmbedPrintPreviewNavType navType,
                             gint pageNum);

static gresult
impl_set_charset (GaleonEmbed *embed,
                  const char *charset);
static gresult 
impl_select_all (GaleonEmbed *embed);

static void
gtkhtml_embed_load_uri (GtkhtmlEmbed *embed, GnomeVFSURI *uri);
static gboolean
gtkhtml_embed_set_base (GtkhtmlEmbed *embed, const gchar *text_url);

/* HtmlDocument callbacks */
static gboolean
request_url_cb (HtmlDocument *document, const char *text_url,
            HtmlStream *stream, GtkhtmlEmbed *embed);
static void
link_clicked_cb (HtmlDocument *document, const gchar *text_url,
             GtkhtmlEmbed *embed);
static void
stream_cancel_cb (HtmlStream *stream, gpointer user_data, Connection *conn);

/* GNOME VFS connections */
struct _Connection
{
      GnomeVFSAsyncHandle     *handle;
      GtkhtmlEmbed            *embed;

      /* the document if we're loading something as user requested, or NULL
       * if we're loading something embedded in a page, such as images */
      HtmlDocument            *document;

      HtmlStream        *stream;
};

static void
connection_free (Connection *conn);

static void
gtkhtml_embed_add_connection (GtkhtmlEmbed *embed, Connection *conn);
static void
gtkhtml_embed_remove_connection (GtkhtmlEmbed *embed, Connection *conn);
static void
gtkhtml_embed_kill_connections (GtkhtmlEmbed *embed);

/* GNOME VFS callbacks */
static void
vfs_open_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
               Connection *conn);
static void
vfs_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
               gpointer buffer, GnomeVFSFileSize bytes_requested,
               GnomeVFSFileSize bytes_read, Connection *conn);
static void
vfs_close_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
                Connection *conn);

struct GtkhtmlEmbedPrivate
{
      HtmlView    *view;
      HtmlDocument      *document;

      /* base URI of the current page, used to resolve relative URIs */
      GnomeVFSURI *base_uri;

      GSList            *connection_list; 
};

static GtkScrolledWindowClass *parent_class = NULL;

G_DEFINE_TYPE_WITH_CODE (GtkhtmlEmbed, gtkhtml_embed, GTK_TYPE_SCROLLED_WINDOW,
                   G_IMPLEMENT_INTERFACE (GALEON_TYPE_EMBED, galeon_embed_init));

static void
galeon_embed_init (GaleonEmbedClass *embed_class)
{
      embed_class->get_capabilities = impl_get_capabilities;
      embed_class->load_url = impl_load_url; 
      embed_class->stop_load = impl_stop_load;
      embed_class->can_go_back = impl_can_go_back;
      embed_class->can_go_forward =impl_can_go_forward;
      embed_class->can_go_up = impl_can_go_up;
      embed_class->get_go_up_list = impl_get_go_up_list;
      embed_class->go_back = impl_go_back;
      embed_class->go_forward = impl_go_forward;
      embed_class->go_up = impl_go_up;
      embed_class->render_data = impl_render_data;
      embed_class->open_stream = impl_open_stream;
      embed_class->append_data = impl_append_data;
      embed_class->close_stream = impl_close_stream;
      embed_class->get_title = impl_get_title;
      embed_class->get_location = impl_get_location;
      embed_class->reload = impl_reload;
      embed_class->copy_page = impl_copy_page;
      embed_class->grab_focus = impl_grab_focus;
      embed_class->get_favicon_location = impl_get_favicon_location;
      embed_class->get_link_tags = impl_get_link_tags;
      embed_class->zoom_set = impl_zoom_set;
      embed_class->zoom_get = impl_zoom_get;
      embed_class->selection_can_cut = impl_selection_can_cut;
      embed_class->selection_can_copy = impl_selection_can_copy;
      embed_class->can_paste = impl_can_paste;
      embed_class->selection_cut = impl_selection_cut;
      embed_class->selection_copy = impl_selection_copy;
      embed_class->paste = impl_paste;
      embed_class->shistory_count = impl_shistory_count;
      embed_class->shistory_get_nth = impl_shistory_get_nth;
      embed_class->shistory_get_pos = impl_shistory_get_pos;
      embed_class->shistory_go_nth = impl_shistory_go_nth;
      embed_class->shistory_copy = impl_shistory_copy;
      embed_class->shistory_clear = impl_shistory_clear;
      embed_class->scroll = impl_scroll;
      embed_class->get_security_level = impl_get_security_level;
      embed_class->find = impl_find;
      embed_class->print = impl_print;
      embed_class->set_charset = impl_set_charset;
      embed_class->select_all = impl_select_all;
      embed_class->print_preview_close = impl_print_preview_close;
      embed_class->print_preview_num_pages = impl_print_preview_num_pages;
      embed_class->print_preview_navigate = impl_print_preview_navigate;
}

static void
gtkhtml_embed_class_init (GtkhtmlEmbedClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
      
        parent_class = (GtkScrolledWindowClass *) g_type_class_peek_parent (klass);
      
        object_class->finalize = gtkhtml_embed_finalize;
}

static void
gtkhtml_embed_init (GtkhtmlEmbed *embed)
{
        embed->priv = g_new0 (GtkhtmlEmbedPrivate, 1);

      /* HtmlDocument */
      embed->priv->document = html_document_new ();
      g_signal_connect (G_OBJECT (embed->priv->document), "request_url",
                    G_CALLBACK (request_url_cb), embed);
      g_signal_connect (G_OBJECT (embed->priv->document), "link_clicked",
                    G_CALLBACK (link_clicked_cb), embed);

      /* HtmlView */
      embed->priv->view = HTML_VIEW (html_view_new ());
      html_view_set_document (embed->priv->view,
                        embed->priv->document);
      gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (embed),
                                       gtk_layout_get_hadjustment 
                                    (GTK_LAYOUT (embed->priv->view)));
      gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (embed),
                                       gtk_layout_get_vadjustment 
                                    (GTK_LAYOUT (embed->priv->view)));
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (embed),
                                  GTK_POLICY_AUTOMATIC,
                              GTK_POLICY_AUTOMATIC);

      gtk_container_add (GTK_CONTAINER (embed), GTK_WIDGET (embed->priv->view));
      gtk_widget_show (GTK_WIDGET (embed->priv->view));
}

static void
gtkhtml_embed_finalize (GObject *object)
{
        GtkhtmlEmbed *embed;

        g_return_if_fail (object != NULL);
        g_return_if_fail (GTKHTML_IS_EMBED (object));

      embed = GTKHTML_EMBED (object);

        g_return_if_fail (embed->priv != NULL);

      gtkhtml_embed_kill_connections (embed);
      if (embed->priv->base_uri) gnome_vfs_uri_unref (embed->priv->base_uri);

        g_free (embed->priv);

        G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
impl_get_capabilities (GaleonEmbed *embed,
                       EmbedCapabilities *caps)
{
      *caps = 0;
}

static gresult 
impl_load_url (GaleonEmbed *embed, 
               const char *url)
{
      if (strchr (url, ':') == NULL)
      {
            /* no protocol in url, use http */
            char *http_url = g_strconcat("http://", url, NULL);
            link_clicked_cb (NULL, http_url, GTKHTML_EMBED (embed));
            g_free (http_url);
      }
      else
      {
            link_clicked_cb (NULL, url, GTKHTML_EMBED (embed));
      }
      return G_OK;
}

static gresult 
impl_stop_load (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_can_go_back (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_can_go_forward (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_can_go_up (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_get_go_up_list (GaleonEmbed *embed, GSList **l)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_go_back (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult  
impl_go_forward (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_go_up (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_render_data (GaleonEmbed *embed, 
                  const char *data,
                  guint32 len,
                  const char *base_uri, 
                  const char *mime_type)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_open_stream (GaleonEmbed *embed,
                  const char *base_uri,
                  const char *mime_type)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_append_data (GaleonEmbed *embed,
                  const char *data, 
                  guint32 len)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_close_stream (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_get_title (GaleonEmbed *embed,
                char **title)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_get_location (GaleonEmbed *ge, 
                   gboolean toplevel,
                   gboolean requested,
                   char **location)
{
      GtkhtmlEmbed *embed = GTKHTML_EMBED (ge);

      if (embed->priv->base_uri == NULL)
      {
            *location = g_strdup ("");
            return G_OK;
      }

      *location = gnome_vfs_uri_to_string (embed->priv->base_uri,
                                       GNOME_VFS_URI_HIDE_NONE);
      return G_OK;
}

static gresult 
impl_reload (GaleonEmbed *embed, 
             EmbedReloadFlags flags)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_copy_page (GaleonEmbed *dest,
                GaleonEmbed *source,
                EmbedDisplayType display_type)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_grab_focus (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_get_favicon_location (GaleonEmbed *embed,
                           char **url)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_get_link_tags (GaleonEmbed *embed,
                    const char *link_type,
                    GList **tags)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_zoom_set (GaleonEmbed *embed, 
               int zoom, 
               gboolean reflow)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_zoom_get (GaleonEmbed *embed,
               int *zoom)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_selection_can_cut (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_selection_can_copy (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_can_paste (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_selection_cut (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_selection_copy (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_paste (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_shistory_count  (GaleonEmbed *embed,
                      int *count)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_shistory_get_nth (GaleonEmbed *embed, 
                       int nth,
                       gboolean is_relative,
                       char **url,
                       char **title)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_shistory_get_pos (GaleonEmbed *embed,
                       int *pos)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_shistory_go_nth (GaleonEmbed *embed, 
                      int nth)
{
      return G_NOT_IMPLEMENTED;
}

static gboolean
impl_shistory_copy (GaleonEmbed *source,
                    GaleonEmbed *dest)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_shistory_clear (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_scroll (GaleonEmbed *embed, 
             EmbedScrollDirection direction)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_get_security_level (GaleonEmbed *embed, 
                         EmbedSecurityLevel level,
                         char **description)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_find (GaleonEmbed *embed,
           EmbedFindInfo *info)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_print (GaleonEmbed *embed, 
            EmbedPrintInfo *info)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_print_preview_close (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_print_preview_num_pages (GaleonEmbed *embed,
                              gint *retNum)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_print_preview_navigate (GaleonEmbed *embed,
                             EmbedPrintPreviewNavType navType,
                             gint pageNum)
{
      return G_NOT_IMPLEMENTED;
}

static gresult
impl_set_charset (GaleonEmbed *embed,
                  const char *charset)
{
      return G_NOT_IMPLEMENTED;
}

static gresult 
impl_select_all (GaleonEmbed *embed)
{
      return G_NOT_IMPLEMENTED;
}

static GnomeVFSURI *
gtkhtml_embed_resolve_relative (GtkhtmlEmbed *embed, const char *text_url)
{
      GnomeVFSURI *uri;

      g_return_val_if_fail (text_url != NULL, NULL);

      if (embed->priv->base_uri != NULL)
      {
            uri = gnome_vfs_uri_resolve_relative (embed->priv->base_uri,
                                              text_url);
      }
      else
      {
            uri = gnome_vfs_uri_new (text_url);
      }

      return uri;
}

static gboolean
request_url_cb (HtmlDocument *document, const char *text_url,
                          HtmlStream *stream, GtkhtmlEmbed *embed)
{
      Connection *conn;
      GnomeVFSURI *uri;

      uri = gtkhtml_embed_resolve_relative (embed, text_url);
      g_return_val_if_fail (uri != NULL, FALSE);

      conn = g_new0 (Connection, 1);
      conn->stream = stream;

      gtkhtml_embed_add_connection (embed, conn);

      gnome_vfs_async_open_uri (&conn->handle, uri, GNOME_VFS_OPEN_READ,
                            GNOME_VFS_PRIORITY_DEFAULT,
                          (GnomeVFSAsyncOpenCallback)vfs_open_callback,
                          conn);
      gnome_vfs_uri_unref (uri);
      html_stream_set_cancel_func (stream, 
                               (HtmlStreamCancelFunc)stream_cancel_cb, 
                             conn);

      return TRUE;
}

static void
link_clicked_cb (HtmlDocument *document, const gchar *text_url,
                           GtkhtmlEmbed *embed)
{
      if (gtkhtml_embed_set_base (embed, text_url))
      {
            /* same document, jump to anchor */
            const gchar *anchor = gnome_vfs_uri_get_fragment_identifier (embed->priv->base_uri);
            if (anchor != NULL)
            {
                  html_view_jump_to_anchor (embed->priv->view, anchor);
            }
      }
      else
      {
            GnomeVFSURI *uri;

            gtkhtml_embed_kill_connections (embed);

            uri = gtkhtml_embed_resolve_relative (embed, text_url);

            /* FIXME error in URI? show dialog? */
            g_return_if_fail (uri != NULL); 

            gtkhtml_embed_load_uri (embed, uri);
            gnome_vfs_uri_unref (uri);
      }
}

static void
stream_cancel_cb (HtmlStream *stream, gpointer user_data, Connection *conn)
{
      gnome_vfs_async_cancel (conn->handle);
      gtkhtml_embed_remove_connection (conn->embed, conn);
      connection_free (conn);
}

/* Return true if the new URI is on the same page as previously */
static gboolean
gtkhtml_embed_set_base (GtkhtmlEmbed *embed, const gchar *text_url)
{
      gchar *old_url, *new_url;
      gboolean equal;
      GnomeVFSURI *uri;

      if (embed->priv->base_uri == NULL)
      {
            embed->priv->base_uri = gnome_vfs_uri_new (text_url);
            g_signal_emit_by_name (embed, "ge_location");
            return FALSE;
      }
      
      uri = gnome_vfs_uri_resolve_relative (embed->priv->base_uri, text_url);
      old_url = gnome_vfs_uri_to_string (embed->priv->base_uri,
                                     GNOME_VFS_URI_HIDE_FRAGMENT_IDENTIFIER);
      new_url = gnome_vfs_uri_to_string (uri,
                                     GNOME_VFS_URI_HIDE_FRAGMENT_IDENTIFIER);

      equal = (strcmp (old_url, new_url) == 0);

      g_free (old_url);
      g_free (new_url);

      gnome_vfs_uri_unref (embed->priv->base_uri);
      embed->priv->base_uri = uri;
      g_signal_emit_by_name (embed, "ge_location");

      return equal;
}

static void
gtkhtml_embed_add_connection (GtkhtmlEmbed *embed, Connection *conn)
{
      g_assert (conn->stream == NULL || conn->document == NULL);

      conn->embed = embed;
      embed->priv->connection_list =
            g_slist_prepend (embed->priv->connection_list, conn);
}

static void
gtkhtml_embed_remove_connection (GtkhtmlEmbed *embed, Connection *conn)
{
      embed->priv->connection_list =
            g_slist_remove (embed->priv->connection_list, conn);
}

static void
gtkhtml_embed_kill_connections (GtkhtmlEmbed *embed)
{
      GSList *tmp;

      for (tmp = embed->priv->connection_list; tmp != NULL; tmp = g_slist_next (tmp))
      {
            Connection *conn = tmp->data;
            gnome_vfs_async_cancel (conn->handle);
            connection_free (conn);
      }
      g_slist_free (embed->priv->connection_list);
      embed->priv->connection_list = NULL;
}

static void
connection_free (Connection *conn)
{
      if (conn->stream != NULL) html_stream_close (conn->stream);
      g_free (conn);
}

static void
gtkhtml_embed_load_uri (GtkhtmlEmbed *embed, GnomeVFSURI *uri)
{
      Connection *conn;
      
      conn = g_new0 (Connection, 1);
      conn->document = embed->priv->document;
      
      gtkhtml_embed_add_connection (embed, conn);

      gnome_vfs_async_open_uri (&conn->handle, uri, GNOME_VFS_OPEN_READ,
                            GNOME_VFS_PRIORITY_DEFAULT,
                          (GnomeVFSAsyncOpenCallback)vfs_open_callback,
                          conn);
}

static void
vfs_open_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
               Connection *conn)
{
      if (result == GNOME_VFS_OK)
      {
            gchar *buffer;

            if (conn->document != NULL)
            {
                  html_document_clear (conn->document);
                  gtk_adjustment_set_value 
                   (gtk_scrolled_window_get_vadjustment
                    (GTK_SCROLLED_WINDOW (conn->embed)), 0);

                  /* FIXME hook up some gnome-vfs callback to get HTTP headers */
                  html_document_open_stream (conn->document, "text/html");

                  /* avoid need for special cases in vfs_read_callback */
                  conn->stream = conn->document->current_stream;
            }

            buffer = g_malloc (BUFFER_SIZE);
            gnome_vfs_async_read (handle, buffer, BUFFER_SIZE,
                              (GnomeVFSAsyncReadCallback)vfs_read_callback,
                              conn);
      }
      else
      {
            if (conn->document != NULL)
            {
                  GtkWidget *parent = gtk_widget_get_toplevel 
                                    (GTK_WIDGET (conn->embed));
                  GtkWidget *dialog = gtk_message_dialog_new 
                                    (GTK_WINDOW (parent),
                                   GTK_DIALOG_MODAL,
                                   GTK_MESSAGE_ERROR,
                                   GTK_BUTTONS_OK,
                                   "%s",
                                   gnome_vfs_result_to_string (result));
                  gtk_dialog_run (GTK_DIALOG (dialog));
                  gtk_widget_destroy (dialog);
            }

            gtkhtml_embed_remove_connection (conn->embed, conn);
            connection_free (conn);
      }
}

static void
vfs_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
               gpointer buffer, GnomeVFSFileSize bytes_requested,
               GnomeVFSFileSize bytes_read, Connection *conn)
{
      if (result == GNOME_VFS_OK)
      {
            html_stream_write (conn->stream, buffer, bytes_read);
            gnome_vfs_async_read (handle, buffer, bytes_requested,
                              (GnomeVFSAsyncReadCallback)vfs_read_callback,
                              conn);
      }
      else
      {
            gnome_vfs_async_close (handle,
                               (GnomeVFSAsyncCloseCallback)vfs_close_callback,
                               conn);
            g_free (buffer);
      }
}

static void
vfs_close_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
                Connection *conn)
{
      if (conn->document != NULL)
      {
            conn->stream = NULL;
            html_document_close_stream (conn->document);
      }
      gtkhtml_embed_remove_connection (conn->embed, conn);
      connection_free (conn);
}


Generated by  Doxygen 1.6.0   Back to index