Commit 47ffee2f authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

plug-ins/helpbrowser/Makefile.am added new files that implement conversion

2002-06-10  Sven Neumann  <sven@gimp.org>

	* plug-ins/helpbrowser/Makefile.am
	* plug-ins/helpbrowser/uri.[ch]: added new files that implement
	conversion of a relative URI and an absolute base URI to a new
	absolute URI according to RFC 2396. This code has been kindly
	provided by Jacob Schroeder <jacob@convergence.de>.

	* plug-ins/helpbrowser/helpbrowser.c: more work on the help
	browser using the new URI functions. Still work in progress.
parent 72215f93
2002-06-10 Sven Neumann <sven@gimp.org>
* plug-ins/helpbrowser/Makefile.am
* plug-ins/helpbrowser/uri.[ch]: added new files that implement
conversion of a relative URI and an absolute base URI to a new
absolute URI according to RFC 2396. This code has been kindly
provided by Jacob Schroeder <jacob@convergence.de>.
* plug-ins/helpbrowser/helpbrowser.c: more work on the help
browser using the new URI functions. Still work in progress.
2002-06-09 Michael Natterer <mitch@gimp.org>
* themes/Default/imagerc
......
......@@ -7,7 +7,9 @@ libexec_PROGRAMS = helpbrowser
helpbrowser_SOURCES = \
helpbrowser.c \
queue.c \
queue.h
queue.h \
uri.c \
uri.h
INCLUDES = \
-I$(top_srcdir) \
......
......@@ -27,9 +27,10 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
......@@ -40,6 +41,7 @@
#include <libgimp/gimpui.h>
#include "queue.h"
#include "uri.h"
#include "libgimp/stdplugins-intl.h"
......@@ -91,28 +93,9 @@ N_("<html><head><title>Document not found</title></head>"
"</body>"
"</html>");
static gchar *dir_not_found_format_string =
N_("<html><head><title>Directory not found</title></head>"
"<body bgcolor=\"#ffffff\">"
"<center>"
"<p>"
"%s"
"<h3>Couldn't change to directory</h3>"
"<tt>%s</tt>"
"<h3>while trying to access</h3>"
"<tt>%s</tt>"
"</center>"
"<p>"
"<small>This either means that the help for this topic has not been written "
"yet or that something is wrong with your installation. "
"Please check carefully before you report this as a bug.</small>"
"</body>"
"</html>");
static gchar *eek_png_tag = "<h1>Eeek!</h1>";
static gchar *gimp_help_root = NULL;
static GList *history = NULL;
......@@ -151,8 +134,15 @@ static gboolean temp_proc_installed = FALSE;
/* forward declaration */
static gint load_page (const gchar *ref,
gboolean add_to_queue);
static gboolean load_page (const gchar *ref,
gboolean add_to_queue);
static void request_url (HtmlDocument *doc,
const gchar *url,
HtmlStream *stream,
gpointer data);
static gboolean io_handler (GIOChannel *io,
GIOCondition condition,
gpointer data);
/* functions */
......@@ -347,126 +337,29 @@ load_page (const gchar *ref,
gboolean add_to_queue)
{
HtmlDocument *doc;
FILE *fp = NULL;
gchar buf[8192];
gchar *old_dir;
gchar *new_dir;
gchar *new_base;
gchar *new_ref;
gchar *tmp;
gsize bytes_read;
gboolean page_valid = FALSE;
gboolean filters_dir = FALSE;
gchar *new_ref;
g_return_val_if_fail (ref != NULL, FALSE);
doc = HTML_VIEW (html)->document;
old_dir = g_path_get_dirname (current_ref);
new_dir = g_path_get_dirname (ref);
new_base = g_path_get_basename (ref);
/* return value is intentionally ignored */
chdir (old_dir);
if (chdir (new_dir) == -1)
{
gchar *msg;
new_ref = uri_to_abs (ref, current_ref);
if (g_path_is_absolute (ref))
new_ref = g_strdup (ref);
else
new_ref = g_build_filename (old_dir, ref, NULL);
if (!new_ref)
return FALSE;
msg = g_strdup_printf (gettext (dir_not_found_format_string),
eek_png_tag, new_dir, new_ref);
g_print ("load_page %s\n", new_ref);
if (strcmp (current_ref, new_ref))
{
html_document_clear (doc);
html_document_open_stream (doc, "text/html");
html_document_write_stream (doc, msg, strlen (msg));
html_document_close_stream (doc);
g_free (msg);
goto FINISH;
}
tmp = new_dir;
new_dir = g_path_get_basename (tmp);
g_free (tmp);
if (strcmp (new_dir, "filters") == 0)
filters_dir = TRUE;
g_free (new_dir);
new_dir = g_get_current_dir ();
new_ref = g_build_filename (new_dir, new_base, NULL);
gtk_adjustment_set_value (gtk_layout_get_vadjustment (GTK_LAYOUT (html)),
0);
if (strcmp (current_ref, new_ref) == 0)
{
if (add_to_queue)
queue_add (queue, new_ref);
goto FINISH;
}
html_document_clear (doc);
html_document_open_stream (doc, "text/html");
/*
* handle basename like: filename.html#11111 -> filename.html
*/
g_strdelimit (new_base, "#", '\0');
fp = fopen (new_base, "rt");
if (fp != NULL)
{
while ((bytes_read =
fread (buf, sizeof (gchar), sizeof (buf), fp)) > 0)
html_document_write_stream (doc, buf, bytes_read);
}
else if (filters_dir)
{
gchar *undocumented_filter =
g_build_filename (new_dir, "undocumented_filter.html", NULL);
fp = fopen (undocumented_filter, "rt");
if (fp != NULL)
{
while ((bytes_read =
fread (buf, sizeof (gchar), sizeof (buf), fp)) > 0)
html_document_write_stream (doc, buf, bytes_read);
}
g_free (undocumented_filter);
request_url (doc, new_ref, doc->current_stream, NULL);
}
if (fp)
{
fclose (fp);
page_valid = TRUE;
}
else
{
gchar *msg = g_strdup_printf (gettext (doc_not_found_format_string),
eek_png_tag, ref);
chdir (old_dir);
html_document_write_stream (doc, msg, strlen (msg));
g_free (msg);
}
html_document_close_stream (doc);
FINISH:
g_free (old_dir);
g_free (new_dir);
g_free (new_base);
g_free (current_ref);
current_ref = new_ref;
......@@ -475,7 +368,7 @@ load_page (const gchar *ref,
update_toolbar ();
return (page_valid);
return TRUE;
}
static void
......@@ -513,6 +406,106 @@ link_clicked (HtmlDocument *doc,
#endif
}
static void
request_url (HtmlDocument *doc,
const gchar *url,
HtmlStream *stream,
gpointer data)
{
gchar *abs;
gchar *filename;
g_return_if_fail (url != NULL);
g_return_if_fail (stream != NULL);
abs = uri_to_abs (url, current_ref);
if (!abs)
return;
filename = g_filename_from_uri (abs, NULL, NULL);
if (filename)
{
gint fd;
fd = open (filename, O_RDONLY);
if (fd == -1)
{
gchar *msg = g_strdup_printf (gettext (doc_not_found_format_string),
eek_png_tag, filename);
html_document_write_stream (doc, msg, strlen (msg));
}
else
{
GIOChannel *io = g_io_channel_unix_new (fd);
g_print ("loading %s\n", filename);
g_io_channel_set_close_on_unref (io, TRUE);
g_io_channel_set_encoding (io, NULL, NULL);
g_io_add_watch (io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
io_handler, stream);
}
g_free (filename);
}
else
{
g_print ("no filename for %s\n", filename);
}
g_free (abs);
}
static gboolean
io_handler (GIOChannel *io,
GIOCondition condition,
gpointer data)
{
HtmlStream *stream;
gchar buffer[8192];
guint bytes;
stream = (HtmlStream *) data;
if (condition & G_IO_IN)
{
if (g_io_channel_read_chars (io, buffer, sizeof (buffer),
&bytes, NULL) != G_IO_STATUS_ERROR
&& bytes > 0)
{
html_stream_write (stream, buffer, bytes);
}
else
{
return FALSE;
}
if (condition & G_IO_HUP)
{
while (g_io_channel_read_chars (io, buffer, sizeof (buffer),
&bytes, NULL) != G_IO_STATUS_ERROR
&& bytes > 0)
{
html_stream_write (stream, buffer, bytes);
}
}
}
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
{
html_stream_close (stream);
g_io_channel_unref (io);
return FALSE;
}
return TRUE;
}
static void
drag_begin (GtkWidget *widget,
GdkDragContext *context,
......@@ -539,10 +532,10 @@ drag_data_get (GtkWidget *widget,
strlen (current_ref));
}
gboolean
open_browser_dialog (gchar *help_path,
gchar *locale,
gchar *help_file)
static gboolean
open_browser_dialog (const gchar *help_path,
const gchar *locale,
const gchar *help_file)
{
GtkWidget *window;
GtkWidget *vbox;
......@@ -552,38 +545,17 @@ open_browser_dialog (gchar *help_path,
GtkWidget *button;
GtkWidget *drag_source;
GtkWidget *image;
gchar *initial_dir;
gchar *initial_ref;
gchar *eek_png_path;
gint success;
gimp_ui_init ("helpbrowser", TRUE);
if (chdir (gimp_help_root) == -1)
{
g_message (_("GIMP Help Browser Error.\n\n"
"Couldn't find my root html directory.\n"
"(%s)"), gimp_help_root);
return FALSE;
}
eek_png_path = g_build_filename (gimp_help_root, "images", "eek.png", NULL);
if (access (eek_png_path, R_OK) == 0)
if (g_file_test (eek_png_path, G_FILE_TEST_EXISTS))
eek_png_tag = g_strdup_printf ("<img src=\"%s\">", eek_png_path);
g_free (eek_png_path);
if (chdir (help_path) == -1)
{
g_message (_("GIMP Help Browser Error.\n\n"
"Couldn't find my root html directory.\n"
"(%s)"), help_path);
return FALSE;
}
initial_dir = g_get_current_dir ();
/* the dialog window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "destroy",
......@@ -698,18 +670,15 @@ open_browser_dialog (gchar *help_path,
g_signal_connect (G_OBJECT (HTML_VIEW (html)->document), "link_clicked",
G_CALLBACK (link_clicked),
NULL);
g_signal_connect (G_OBJECT (HTML_VIEW (html)->document), "request_url",
G_CALLBACK (request_url),
NULL);
gtk_widget_show (window);
current_ref = g_build_filename (initial_dir, locale, NULL);
current_ref = g_strconcat ("file://", help_path, "/", locale, "/", NULL);
initial_ref = g_build_filename (initial_dir, locale, help_file, NULL);
success = load_page (initial_ref, TRUE);
g_free (initial_ref);
g_free (initial_dir);
return TRUE;
return load_page (help_file, TRUE);
}
static gboolean
......@@ -827,9 +796,9 @@ install_temp_proc (void)
}
static gboolean
open_url (gchar *help_path,
gchar *locale,
gchar *help_file)
open_url (const gchar *help_path,
const gchar *locale,
const gchar *help_file)
{
if (! open_browser_dialog (help_path, locale, help_file))
return FALSE;
......@@ -906,7 +875,7 @@ run (gchar *name,
if (env_root_dir)
{
if (chdir (env_root_dir) == -1)
if (!g_file_test (env_root_dir, G_FILE_TEST_IS_DIR))
{
g_message (_("GIMP Help Browser Error.\n\n"
"Couldn't find GIMP_HELP_ROOT html directory.\n"
......
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* The GIMP Help Browser - URI functions
* Copyright (C) 2001 Jacob Schroeder <jacob@convergence.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib.h>
#include "uri.h"
/* #define URI_DEBUG 1 */
typedef enum
{
URI_UNKNOWN,
URI_ABSURI,
URI_NETPATH,
URI_ABSPATH,
URI_RELPATH,
URI_QUERY,
URI_EMPTY,
URI_FRAGMENT,
URI_INVALID
} UriType;
static UriType
uri_get_type (const gchar *uri)
{
gchar c;
const gchar *cptr;
UriType type = URI_UNKNOWN;
if (!uri)
return type;
cptr = uri;
c = *cptr++;
if (g_ascii_isalpha (c))
{
type = URI_RELPATH; /* assume relative path */
while ((c = *cptr++))
{
if (g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.')
continue;
if (c == ':')
{
/* it was a scheme */
type = URI_ABSURI;
}
break;
}
}
else
{
switch (c)
{
case '/':
if (*cptr == '/')
{
cptr++;
type = URI_NETPATH;
}
else
{
type = URI_ABSPATH;
}
break;
case '?':
type = URI_QUERY;
break;
case '#':
type = URI_FRAGMENT;
break;
case '\0':
type = URI_EMPTY;
break;
default:
type = URI_RELPATH;
break;
}
}
#ifdef URI_DEBUG
g_print ("uri_get_type (\"%s\") -> ", uri);
switch (type)
{
case URI_UNKNOWN: g_print ("unknown"); break;
case URI_ABSURI: g_print ("absuri"); break;
case URI_NETPATH: g_print ("netpath"); break;
case URI_ABSPATH: g_print ("abspath"); break;
case URI_RELPATH: g_print ("relpath"); break;
case URI_QUERY: g_print ("query"); break;
case URI_EMPTY: g_print ("empty"); break;
case URI_FRAGMENT: g_print ("fragment"); break;
case URI_INVALID: g_print ("invalid"); break;
}
g_print ("\n");
#endif
return type;
}
gchar *
uri_to_abs (const gchar *uri,
const gchar *base_uri)
{
gchar c;
const gchar *cptr;
gchar *retval = NULL;
UriType uri_type = URI_UNKNOWN;
UriType base_type = URI_UNKNOWN;
gint base_cnt = 0; /* no of chars to be copied from base URI */
gint uri_cnt = 0; /* no of chars to be copied from URI */
gint sep_cnt = 0; /* no of chars to be inserted between them */
gint path_offset = -1;
const gchar *sep_str = ""; /* string to insert between base and uri */
const gchar *part;
const gchar *last_segment = NULL;
#ifdef URI_DEBUG
g_print ("uri_to_abs (\"%s\", \"%s\")\n", uri, base_uri);
#endif
/* this function does not use the algorithm that is being proposed
* in RFC 2396. Instead it analyses the first characters of each
* URI to determine its kind (abs, net, path, ...).
* After that it locates the missing parts in the base URI and then
* concats everything into a newly allocated string.
*/
/* determine the kind of the URIs */
uri_type = uri_get_type (uri);
if (uri_type != URI_ABSURI)
{
base_type = uri_get_type (base_uri);
if (base_type != URI_ABSURI)
{
g_warning ("base uri is not absolute: '%s'\n", base_uri);
return NULL;
}
}
/* find missing parts in base URI */
switch (uri_type)
{
case URI_ABSURI:
/* base uri not needed */
break;
case URI_QUERY:
/* ??? last segment? */
uri_type = URI_RELPATH;
case URI_NETPATH: /* base scheme */
case URI_ABSPATH: /* base scheme and authority */
case URI_RELPATH: /* base scheme, authority and path */
cptr = base_uri;