gimp/plug-ins/helpbrowser/helpbrowser.c
Sven Neumann 28fddfd554 Makefile.am removed this header file.
2003-03-25  Sven Neumann  <sven@gimp.org>

	* Makefile.am
	* gimpintl.h: removed this header file.

	* gimpmiscui.c: include libgimp-intl.h.

	* gimp.c (gimp_main): call setlocale() and bind to the libgimp
	textdomain so that plug-ins don't need to do that explicitely.

	* libgimp/stdplugins-intl.h: added the functionality that used to
	live in gimpintl.h and removed the libgimp related stuff. Got rid
	of the INIT_I18N_UI() macro.

	* plug-ins/*/*.c: removed all occurances of INIT_I18N_UI().
	Plug-ins simply call INIT_I18N() once in their run() function.

	* plug-ins/script-fu/script-fu-intl.h: added the functionality
	that used to live in gimpintl.h and removed the libgimp related
	stuff.

	* app/Makefile.am
	* app/gimp-intl.h: new file that defines the gettext macros for
	the GIMP core.

	* app/*/*.c: include gimp-intl.h instead of libgimp/gimpintl.h.

	* plug-ins/script-fu/scripts/test-sphere.scm: fixed typos.
2003-03-25 16:38:19 +00:00

968 lines
24 KiB
C

/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* The GIMP Help Browser
* Copyright (C) 1999-2002 Sven Neumann <sven@gimp.org>
* Michael Natterer <mitch@gimp.org>
*
* Some code & ideas stolen from the GNOME help browser.
*
* 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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <libgtkhtml/gtkhtml.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "queue.h"
#include "uri.h"
#include "libgimp/stdplugins-intl.h"
/* defines */
#ifdef __EMX__
#define chdir _chdir2
#endif
#define GIMP_HELP_EXT_NAME "extension_gimp_help_browser"
#define GIMP_HELP_TEMP_EXT_NAME "extension_gimp_help_browser_temp"
#define GIMP_HELP_PREFIX "help"
enum
{
BUTTON_HOME,
BUTTON_INDEX,
BUTTON_BACK,
BUTTON_FORWARD
};
typedef struct
{
const gchar *title;
const gchar *ref;
gint count;
} HistoryItem;
static const gchar *eek_png_tag = "<h1>Eeek!</h1>";
static gchar *gimp_help_root = NULL;
static GList *history = NULL;
static Queue *queue;
static gchar *current_ref;
static GtkWidget *html;
static GtkWidget *back_button;
static GtkWidget *forward_button;
static GtkWidget *combo;
static GtkTargetEntry help_dnd_target_table[] =
{
{ "_NETSCAPE_URL", 0, 0 },
};
/* GIMP plugin stuff */
static void query (void);
static void run (gchar *name,
gint nparams,
GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
GimpPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static gboolean temp_proc_installed = FALSE;
/* forward declaration */
static void 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);
/* Taken from glib/gconvert.c:
* Test of haystack has the needle prefix, comparing case
* insensitive. haystack may be UTF-8, but needle must
* contain only ascii.
*/
static gboolean
has_case_prefix (const gchar *haystack, const gchar *needle)
{
const gchar *h = haystack;
const gchar *n = needle;
while (*n && *h && g_ascii_tolower (*n) == g_ascii_tolower (*h))
{
n++;
h++;
}
return (*n == '\0');
}
static void
close_callback (GtkWidget *widget,
gpointer user_data)
{
gtk_main_quit ();
}
static void
update_toolbar (void)
{
if (back_button)
gtk_widget_set_sensitive (back_button, queue_has_prev (queue));
if (forward_button)
gtk_widget_set_sensitive (forward_button, queue_has_next (queue));
}
static void
button_callback (GtkWidget *widget,
gpointer data)
{
const gchar *ref;
switch (GPOINTER_TO_INT (data))
{
case BUTTON_HOME:
load_page ("contents.html", TRUE);
break;
case BUTTON_INDEX:
load_page ("index.html", TRUE);
break;
case BUTTON_BACK:
if (!(ref = queue_prev (queue)))
return;
load_page (ref, FALSE);
queue_move_prev (queue);
break;
case BUTTON_FORWARD:
if (!(ref = queue_next (queue)))
return;
load_page (ref, FALSE);
queue_move_next (queue);
break;
default:
return;
}
update_toolbar ();
}
static void
entry_changed_callback (GtkWidget *widget,
gpointer data)
{
GList *list;
HistoryItem *item;
const gchar *entry_text;
gchar *compare_text;
gboolean found = FALSE;
entry_text = gtk_entry_get_text (GTK_ENTRY (widget));
for (list = history; list && !found; list = list->next)
{
item = (HistoryItem *) list->data;
if (item->count)
{
compare_text = g_strdup_printf ("%s <%i>",
item->title, item->count + 1);
}
else
{
compare_text = (gchar *) item->title;
}
if (strcmp (compare_text, entry_text) == 0)
{
load_page (item->ref, TRUE);
found = TRUE;
}
if (item->count)
{
g_free (compare_text);
}
}
}
static void
history_add (const gchar *ref,
const gchar *title)
{
GList *list;
GList *found = NULL;
HistoryItem *item;
GList *combo_list = NULL;
gint title_found_count = 0;
for (list = history; list && !found; list = list->next)
{
item = (HistoryItem *) list->data;
if (strcmp (item->title, title) == 0)
{
if (strcmp (item->ref, ref) != 0)
{
title_found_count++;
continue;
}
found = list;
}
}
if (found)
{
item = (HistoryItem *) found->data;
history = g_list_remove_link (history, found);
}
else
{
item = g_new (HistoryItem, 1);
item->ref = g_strdup (ref);
item->title = g_strdup (title);
item->count = title_found_count;
}
history = g_list_prepend (history, item);
for (list = history; list; list = list->next)
{
gchar* combo_title;
item = (HistoryItem *) list->data;
if (item->count)
combo_title = g_strdup_printf ("%s <%i>",
item->title,
item->count + 1);
else
combo_title = g_strdup (item->title);
combo_list = g_list_prepend (combo_list, combo_title);
}
combo_list = g_list_reverse (combo_list);
g_signal_handlers_block_by_func (GTK_COMBO (combo)->entry,
entry_changed_callback, combo);
gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
g_signal_handlers_unblock_by_func (GTK_COMBO (combo)->entry,
entry_changed_callback, combo);
for (list = combo_list; list; list = list->next)
g_free (list->data);
g_list_free (combo_list);
}
static void
title_changed (HtmlDocument *doc,
const gchar *new_title,
gpointer data)
{
gchar *title;
if (!new_title)
new_title = (_("<Untitled>"));
title = g_strstrip (g_strdup (new_title));
history_add (current_ref, title);
g_signal_handlers_block_by_func (GTK_COMBO (combo)->entry,
entry_changed_callback, combo);
gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), title);
g_signal_handlers_unblock_by_func (GTK_COMBO (combo)->entry,
entry_changed_callback, combo);
g_free (title);
}
static void
load_remote_page (const gchar *ref)
{
GimpParam *return_vals;
gint nreturn_vals;
/* try to call netscape through the web_browser interface */
return_vals = gimp_run_procedure ("extension_web_browser",
&nreturn_vals,
GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
GIMP_PDB_STRING, ref,
GIMP_PDB_INT32, FALSE,
GIMP_PDB_END);
gimp_destroy_params (return_vals, nreturn_vals);
}
static void
load_page (const gchar *ref,
gboolean add_to_queue)
{
HtmlDocument *doc = HTML_VIEW (html)->document;
gchar *abs;
gchar *new_ref;
gchar *anchor;
g_return_if_fail (ref != NULL);
abs = uri_to_abs (ref, current_ref);
g_return_if_fail (abs != NULL);
anchor = strchr (ref, '#');
if (anchor && anchor[0] && anchor[1])
{
new_ref = g_strconcat (abs, anchor, NULL);
anchor += 1;
}
else
{
new_ref = g_strdup (abs);
anchor = NULL;
}
if (strcmp (current_ref, abs))
{
if (!has_case_prefix (abs, "file:/"))
{
load_remote_page (ref);
return;
}
html_document_clear (doc);
html_document_open_stream (doc, "text/html");
gtk_adjustment_set_value (gtk_layout_get_vadjustment (GTK_LAYOUT (html)),
0);
request_url (doc, abs, doc->current_stream, NULL);
}
if (anchor)
html_view_jump_to_anchor (HTML_VIEW (html), anchor);
g_free (current_ref);
current_ref = new_ref;
if (add_to_queue)
queue_add (queue, new_ref);
update_toolbar ();
}
static void
link_clicked (HtmlDocument *doc,
const gchar *url,
gpointer data)
{
load_page (url, TRUE);
}
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 *name;
gchar *msg;
name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
msg = g_strdup_printf
("<html>"
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"
"<head><title>%s</title></head>"
"<body bgcolor=\"white\">"
"<div align=\"center\">"
"<div>%s</div>"
"<h3>%s</h3>"
"<tt>%s</tt>"
"</div>"
"<br /><br />"
"<div align=\"justify\">%s</div>"
"</body>"
"</html>",
_("Document Not Found"),
eek_png_tag,
_("Could not locate help documentation"),
name,
_("The requested document could not be found in your GIMP help "
"path as shown above. This means that the topic has not yet "
"been written or your installation is not complete. Ensure "
"that your installation is complete before reporting this "
"error as a bug."));
html_document_write_stream (doc, msg, strlen (msg));
g_free (msg);
g_free (name);
}
else
{
GIOChannel *io = g_io_channel_unix_new (fd);
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);
}
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
{
html_stream_close (stream);
g_io_channel_unref (io);
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,
gpointer data)
{
gtk_drag_set_icon_stock (context, GTK_STOCK_JUMP_TO, -8, -8);
}
static void
drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
if (! current_ref)
return;
gtk_selection_data_set (selection_data,
selection_data->target,
8,
current_ref,
strlen (current_ref));
}
static void
open_browser_dialog (const gchar *help_path,
const gchar *locale,
const gchar *help_file)
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *bbox;
GtkWidget *scroll;
GtkWidget *button;
GtkWidget *drag_source;
GtkWidget *image;
gchar *eek_png_path;
gimp_ui_init ("helpbrowser", TRUE);
eek_png_path = g_build_filename (gimp_help_root, "images", "eek.png", NULL);
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);
/* the dialog window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy",
G_CALLBACK (close_callback),
NULL);
gtk_window_set_wmclass (GTK_WINDOW (window), "helpbrowser", "Gimp");
gtk_window_set_title (GTK_WINDOW (window), _("GIMP Help Browser"));
gimp_help_connect (window, gimp_standard_help_func, "dialogs/help.html");
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);
/* buttons */
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
gtk_widget_show (bbox);
button = gtk_button_new_from_stock (GTK_STOCK_HOME);
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_widget_show (button);
g_signal_connect (button, "clicked",
G_CALLBACK (button_callback),
GINT_TO_POINTER (BUTTON_HOME));
button = gtk_button_new_from_stock (GTK_STOCK_INDEX);
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_widget_show (button);
g_signal_connect (button, "clicked",
G_CALLBACK (button_callback),
GINT_TO_POINTER (BUTTON_INDEX));
back_button = button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
g_signal_connect (button, "clicked",
G_CALLBACK (button_callback),
GINT_TO_POINTER (BUTTON_BACK));
gtk_widget_show (button);
forward_button = button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
g_signal_connect (button, "clicked",
G_CALLBACK (button_callback),
GINT_TO_POINTER (BUTTON_FORWARD));
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
/* the drag source */
drag_source = gtk_event_box_new ();
gtk_box_pack_start (GTK_BOX (hbox), drag_source, FALSE, FALSE, 4);
gtk_widget_show (drag_source);
gtk_drag_source_set (GTK_WIDGET (drag_source),
GDK_BUTTON1_MASK,
help_dnd_target_table,
G_N_ELEMENTS (help_dnd_target_table),
GDK_ACTION_MOVE | GDK_ACTION_COPY);
g_signal_connect (drag_source, "drag_begin",
G_CALLBACK (drag_begin),
NULL);
g_signal_connect (drag_source, "drag_data_get",
G_CALLBACK (drag_data_get),
NULL);
image = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_BUTTON);
gtk_container_add (GTK_CONTAINER (drag_source), image);
gtk_widget_show (image);
/* the title combo */
combo = gtk_combo_new ();
gtk_widget_set_size_request (GTK_WIDGET (combo), 360, -1);
gtk_combo_set_use_arrows (GTK_COMBO (combo), TRUE);
g_object_set (GTK_COMBO (combo)->entry, "editable", FALSE, NULL);
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
gtk_widget_show (combo);
g_signal_connect (GTK_COMBO (combo)->entry, "changed",
G_CALLBACK (entry_changed_callback),
combo);
/* HTML view */
html = html_view_new ();
queue = queue_new ();
gtk_widget_set_size_request (GTK_WIDGET (html), -1, 240);
scroll =
gtk_scrolled_window_new (gtk_layout_get_hadjustment (GTK_LAYOUT (html)),
gtk_layout_get_vadjustment (GTK_LAYOUT (html)));
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
gtk_widget_show (scroll);
gtk_container_add (GTK_CONTAINER (scroll), html);
gtk_widget_show (html);
html_view_set_document (HTML_VIEW (html), html_document_new ());
g_signal_connect (HTML_VIEW (html)->document, "title_changed",
G_CALLBACK (title_changed),
NULL);
g_signal_connect (HTML_VIEW (html)->document, "link_clicked",
G_CALLBACK (link_clicked),
NULL);
g_signal_connect (HTML_VIEW (html)->document, "request_url",
G_CALLBACK (request_url),
NULL);
gtk_widget_show (window);
current_ref = g_strconcat ("file://", help_path, "/", locale, "/", NULL);
load_page (help_file, TRUE);
}
static gboolean
idle_load_page (gpointer data)
{
gchar *path = data;
load_page (path, TRUE);
g_free (path);
return FALSE;
}
static void
run_temp_proc (gchar *name,
gint nparams,
GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
static GimpParam values[1];
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
gchar *help_path;
gchar *locale;
gchar *help_file;
gchar *path;
/* set default values */
help_path = g_strdup (gimp_help_root);
locale = g_strdup ("C");
help_file = g_strdup ("introduction.html");
/* Make sure all the arguments are there! */
if (nparams == 3)
{
if (param[0].data.d_string && strlen (param[0].data.d_string))
{
g_free (help_path);
help_path = g_strdup (param[0].data.d_string);
g_strdelimit (help_path, "/", G_DIR_SEPARATOR);
}
if (param[1].data.d_string && strlen (param[1].data.d_string))
{
g_free (locale);
locale = g_strdup (param[1].data.d_string);
}
if (param[2].data.d_string && strlen (param[2].data.d_string))
{
g_free (help_file);
help_file = g_strdup (param[2].data.d_string);
g_strdelimit (help_file, "/", G_DIR_SEPARATOR);
}
}
path = g_build_filename (help_path, locale, help_file, NULL);
g_free (help_path);
g_free (locale);
g_free (help_file);
g_idle_add (idle_load_page, path); /* frees path */
*nreturn_vals = 1;
*return_vals = values;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
}
/* from libgimp/gimp.c */
void
gimp_run_temp (void);
static gboolean
input_callback (GIOChannel *channel,
GIOCondition condition,
gpointer data)
{
/* We have some data in the wire - read it */
/* The below will only ever run a single proc */
gimp_run_temp ();
return TRUE;
}
static void
install_temp_proc (void)
{
static GimpParamDef args[] =
{
{ GIMP_PDB_STRING, "help_path", "" },
{ GIMP_PDB_STRING, "locale", "Language to use" },
{ GIMP_PDB_STRING, "help_file", "Path of a local document to open. "
"Can be relative to GIMP_HELP_PATH." }
};
gimp_install_temp_proc (GIMP_HELP_TEMP_EXT_NAME,
"DON'T USE THIS ONE",
"(Temporary procedure)",
"Sven Neumann <sven@gimp.org>, "
"Michael Natterer <mitch@gimp.org>",
"Sven Neumann & Michael Natterer",
"1999-2002",
NULL,
"",
GIMP_TEMPORARY,
G_N_ELEMENTS (args), 0,
args, NULL,
run_temp_proc);
/* Tie into the gdk input function */
g_io_add_watch (_readchannel, G_IO_IN | G_IO_PRI, input_callback, NULL);
temp_proc_installed = TRUE;
}
static void
open_url (const gchar *help_path,
const gchar *locale,
const gchar *help_file)
{
open_browser_dialog (help_path, locale, help_file);
install_temp_proc ();
gtk_main ();
}
MAIN ()
static void
query (void)
{
static GimpParamDef args[] =
{
{ GIMP_PDB_INT32, "run_mode", "Interactive" },
{ GIMP_PDB_STRING, "help_path", "" },
{ GIMP_PDB_STRING, "locale", "Language to use" },
{ GIMP_PDB_STRING, "help_file", "Path of a local document to open. "
"Can be relative to GIMP_HELP_PATH." }
};
gimp_install_procedure (GIMP_HELP_EXT_NAME,
"Browse the GIMP help pages",
"A small and simple HTML browser optimized for "
"browsing the GIMP help pages.",
"Sven Neumann <sven@gimp.org>, "
"Michael Natterer <mitch@gimp.org>",
"Sven Neumann & Michael Natterer",
"1999-2002",
NULL,
"",
GIMP_EXTENSION,
G_N_ELEMENTS (args), 0,
args, NULL);
}
static void
run (gchar *name,
gint nparams,
GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
static GimpParam values[1];
GimpRunMode run_mode;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
const gchar *env_root_dir = NULL;
gchar *help_path = NULL;
gchar *locale = NULL;
gchar *help_file = NULL;
run_mode = param[0].data.d_int32;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
INIT_I18N ();
if (strcmp (name, GIMP_HELP_EXT_NAME) == 0)
{
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
case GIMP_RUN_NONINTERACTIVE:
case GIMP_RUN_WITH_LAST_VALS:
/* set default values */
env_root_dir = g_getenv ("GIMP_HELP_ROOT");
if (env_root_dir)
{
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"
"(%s)"), env_root_dir);
status = GIMP_PDB_EXECUTION_ERROR;
break;
}
gimp_help_root = g_strdup (env_root_dir);
}
else
{
gimp_help_root = g_build_filename (gimp_data_directory (),
GIMP_HELP_PREFIX, NULL);
}
help_path = g_strdup (gimp_help_root);
locale = g_strdup ("C");
help_file = g_strdup ("introduction.html");
/* Make sure all the arguments are there! */
if (nparams == 4)
{
if (param[1].data.d_string && strlen (param[1].data.d_string))
{
g_free (help_path);
help_path = g_strdup (param[1].data.d_string);
}
if (param[2].data.d_string && strlen (param[2].data.d_string))
{
g_free (locale);
locale = g_strdup (param[2].data.d_string);
}
if (param[3].data.d_string && strlen (param[3].data.d_string))
{
g_free (help_file);
help_file = g_strdup (param[3].data.d_string);
}
}
break;
default:
status = GIMP_PDB_CALLING_ERROR;
break;
}
if (status == GIMP_PDB_SUCCESS)
{
open_url (help_path, locale, help_file);
g_free (help_path);
g_free (locale);
g_free (help_file);
}
values[0].data.d_status = status;
}
else
values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
}