Initial checkin of Pika from heckimp
This commit is contained in:
1348
plug-ins/help-browser/dialog.c
Normal file
1348
plug-ins/help-browser/dialog.c
Normal file
File diff suppressed because it is too large
Load Diff
48
plug-ins/help-browser/dialog.h
Normal file
48
plug-ins/help-browser/dialog.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* The PIKA Help Browser
|
||||
* Copyright (C) 1999-2003 Sven Neumann <sven@gimp.org>
|
||||
* Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* dialog.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DIALOG_H__
|
||||
#define __DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define PIKA_TYPE_HELP_BROWSER_DIALOG (pika_help_browser_dialog_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (PikaHelpBrowserDialog, pika_help_browser_dialog,
|
||||
PIKA, HELP_BROWSER_DIALOG,
|
||||
GtkApplicationWindow)
|
||||
|
||||
PikaHelpBrowserDialog * pika_help_browser_dialog_new (const char *plug_in_binary,
|
||||
GApplication *app);
|
||||
|
||||
void pika_help_browser_dialog_load (PikaHelpBrowserDialog *self,
|
||||
const char *uri);
|
||||
|
||||
void pika_help_browser_dialog_make_index (PikaHelpBrowserDialog *self,
|
||||
PikaHelpDomain *domain,
|
||||
PikaHelpLocale *locale);
|
||||
|
||||
#endif /* ! __DIALOG_H__ */
|
369
plug-ins/help-browser/help-browser.c
Normal file
369
plug-ins/help-browser/help-browser.c
Normal file
@ -0,0 +1,369 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* The PIKA Help Browser
|
||||
* Copyright (C) 1999-2008 Sven Neumann <sven@gimp.org>
|
||||
* Michael Natterer <mitch@gimp.org>
|
||||
* Henrik Brix Andersen <brix@gimp.org>
|
||||
*
|
||||
* Some code & ideas taken 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h> /* strlen, strcmp */
|
||||
|
||||
#include <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
#include "plug-ins/help/pikahelp.h"
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
|
||||
#define PIKA_HELP_BROWSER_EXT_PROC "extension-pika-help-browser"
|
||||
#define PIKA_HELP_BROWSER_TEMP_EXT_PROC "extension-pika-help-browser-temp"
|
||||
#define PLUG_IN_BINARY "help-browser"
|
||||
#define PLUG_IN_ROLE "pika-help-browser"
|
||||
|
||||
|
||||
#define PIKA_TYPE_HELP_BROWSER (pika_help_browser_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (PikaHelpBrowser, pika_help_browser,
|
||||
PIKA, HELP_BROWSER,
|
||||
PikaPlugIn)
|
||||
|
||||
static PikaValueArray * help_browser_run (PikaProcedure *procedure,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
|
||||
static void temp_proc_install (PikaPlugIn *plug_in);
|
||||
static PikaValueArray * temp_proc_run (PikaProcedure *procedure,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
|
||||
static PikaHelpProgress * help_browser_progress_new (void);
|
||||
|
||||
struct _PikaHelpBrowser
|
||||
{
|
||||
PikaPlugIn parent_instance;
|
||||
|
||||
GtkApplication *app;
|
||||
PikaHelpBrowserDialog *window;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (PikaHelpBrowser, pika_help_browser, PIKA_TYPE_PLUG_IN)
|
||||
|
||||
PIKA_MAIN (PIKA_TYPE_HELP_BROWSER)
|
||||
DEFINE_STD_SET_I18N
|
||||
|
||||
static GList *
|
||||
help_browser_query_procedures (PikaPlugIn *plug_in)
|
||||
{
|
||||
return g_list_append (NULL, g_strdup (PIKA_HELP_BROWSER_EXT_PROC));
|
||||
}
|
||||
|
||||
static PikaProcedure *
|
||||
help_browser_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name)
|
||||
{
|
||||
PikaProcedure *procedure = NULL;
|
||||
|
||||
if (! strcmp (name, PIKA_HELP_BROWSER_EXT_PROC))
|
||||
{
|
||||
procedure = pika_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_EXTENSION,
|
||||
help_browser_run, plug_in, NULL);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Browse the PIKA user manual",
|
||||
"A small and simple HTML browser "
|
||||
"optimized for browsing the PIKA "
|
||||
"user manual.",
|
||||
PIKA_HELP_BROWSER_EXT_PROC);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Sven Neumann <sven@gimp.org>, "
|
||||
"Michael Natterer <mitch@gimp.org>"
|
||||
"Henrik Brix Andersen <brix@gimp.org>",
|
||||
"Sven Neumann, Michael Natterer & "
|
||||
"Henrik Brix Andersen",
|
||||
"1999-2008");
|
||||
|
||||
PIKA_PROC_ARG_ENUM (procedure, "run-mode",
|
||||
"Run mode",
|
||||
"The run mode",
|
||||
PIKA_TYPE_RUN_MODE,
|
||||
PIKA_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_STRV (procedure, "domain-names",
|
||||
"Domain names",
|
||||
"Domain names",
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_STRV (procedure, "domain-uris",
|
||||
"Domain URIs",
|
||||
"Domain URIs",
|
||||
G_PARAM_READWRITE);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static void
|
||||
on_app_activate (GApplication *gapp,
|
||||
gpointer user_data)
|
||||
{
|
||||
PikaHelpBrowser *browser = PIKA_HELP_BROWSER (user_data);
|
||||
GtkApplication *app = GTK_APPLICATION (gapp);
|
||||
|
||||
browser->window = pika_help_browser_dialog_new (PLUG_IN_BINARY, gapp);
|
||||
|
||||
gtk_application_set_accels_for_action (app, "win.back", (const char*[]) { "<alt>Left", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.forward", (const char*[]) { "<alt>Right", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.reload", (const char*[]) { "<control>R", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.stop", (const char*[]) { "Escape", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.home", (const char*[]) { "<alt>Home", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.copy-selection", (const char*[]) { "<control>C", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.zoom-in", (const char*[]) { "<control>plus", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.zoom-out", (const char*[]) { "<control>minus", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.find", (const char*[]) { "<control>F", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.find-again", (const char*[]) { "<control>G", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.close", (const char*[]) { "<control>W", "<control>Q", NULL });
|
||||
gtk_application_set_accels_for_action (app, "win.show-index", (const char*[]) { "<control>I", NULL });
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
help_browser_run (PikaProcedure *procedure,
|
||||
const PikaValueArray *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
PikaHelpBrowser *browser = PIKA_HELP_BROWSER (user_data);
|
||||
|
||||
if (! pika_help_init (PIKA_VALUES_GET_STRV (args, 1),
|
||||
PIKA_VALUES_GET_STRV (args, 2)))
|
||||
{
|
||||
return pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_CALLING_ERROR,
|
||||
NULL);
|
||||
}
|
||||
|
||||
temp_proc_install (pika_procedure_get_plug_in (procedure));
|
||||
|
||||
pika_procedure_extension_ready (procedure);
|
||||
pika_plug_in_extension_enable (pika_procedure_get_plug_in (procedure));
|
||||
|
||||
#if GLIB_CHECK_VERSION(2,74,0)
|
||||
browser->app = gtk_application_new (NULL, G_APPLICATION_DEFAULT_FLAGS);
|
||||
#else
|
||||
browser->app = gtk_application_new (NULL, G_APPLICATION_FLAGS_NONE);
|
||||
#endif
|
||||
g_signal_connect (browser->app, "activate", G_CALLBACK (on_app_activate), browser);
|
||||
|
||||
g_application_run (G_APPLICATION (browser->app), 0, NULL);
|
||||
|
||||
g_clear_object (&browser->app);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
temp_proc_install (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaProcedure *procedure;
|
||||
|
||||
procedure = pika_procedure_new (plug_in, PIKA_HELP_BROWSER_TEMP_EXT_PROC,
|
||||
PIKA_PDB_PROC_TYPE_TEMPORARY,
|
||||
temp_proc_run, plug_in, NULL);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"DON'T USE THIS ONE",
|
||||
"(Temporary procedure)",
|
||||
NULL);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Sven Neumann <sven@gimp.org>, "
|
||||
"Michael Natterer <mitch@gimp.org>"
|
||||
"Henrik Brix Andersen <brix@gimp.org>",
|
||||
"Sven Neumann, Michael Natterer & "
|
||||
"Henrik Brix Andersen",
|
||||
"1999-2008");
|
||||
|
||||
PIKA_PROC_ARG_STRING (procedure, "help-domain",
|
||||
"Help domain",
|
||||
"Help domain to use",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_STRING (procedure, "help-locales",
|
||||
"Help locales",
|
||||
"Language to use",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_STRING (procedure, "help-id",
|
||||
"Help ID",
|
||||
"Help ID to open",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
pika_plug_in_add_temp_procedure (plug_in, procedure);
|
||||
g_object_unref (procedure);
|
||||
}
|
||||
|
||||
typedef struct _IdleClosure
|
||||
{
|
||||
PikaHelpBrowser *browser;
|
||||
char *help_domain;
|
||||
char *help_locales;
|
||||
char *help_id;
|
||||
} IdleClosure;
|
||||
|
||||
static void
|
||||
idle_closure_free (gpointer data)
|
||||
{
|
||||
IdleClosure *closure = data;
|
||||
|
||||
g_free (closure->help_domain);
|
||||
g_free (closure->help_locales);
|
||||
g_free (closure->help_id);
|
||||
g_free (closure);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_help_on_idle (gpointer user_data)
|
||||
{
|
||||
IdleClosure *closure = user_data;
|
||||
PikaHelpDomain *domain;
|
||||
PikaHelpProgress *progress = NULL;
|
||||
PikaHelpLocale *locale;
|
||||
GList *locales;
|
||||
char *uri;
|
||||
gboolean fatal_error;
|
||||
|
||||
/* First get the URI to load */
|
||||
domain = pika_help_lookup_domain (closure->help_domain);
|
||||
if (!domain)
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
locales = pika_help_parse_locales (closure->help_locales);
|
||||
|
||||
if (! g_str_has_prefix (domain->help_uri, "file:"))
|
||||
progress = help_browser_progress_new ();
|
||||
|
||||
uri = pika_help_domain_map (domain, locales, closure->help_id,
|
||||
progress, &locale, &fatal_error);
|
||||
|
||||
if (progress)
|
||||
pika_help_progress_free (progress);
|
||||
|
||||
g_list_free_full (locales, (GDestroyNotify) g_free);
|
||||
|
||||
/* Now actually load it */
|
||||
if (uri)
|
||||
{
|
||||
pika_help_browser_dialog_make_index (closure->browser->window, domain, locale);
|
||||
pika_help_browser_dialog_load (closure->browser->window, uri);
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
temp_proc_run (PikaProcedure *procedure,
|
||||
const PikaValueArray *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
PikaHelpBrowser *browser = PIKA_HELP_BROWSER (user_data);
|
||||
IdleClosure *closure;
|
||||
const char *str;
|
||||
|
||||
closure = g_new0 (IdleClosure, 1);
|
||||
closure->browser = browser;
|
||||
|
||||
str = PIKA_VALUES_GET_STRING (args, 0);
|
||||
closure->help_domain = g_strdup ((str && *str)? str : PIKA_HELP_DEFAULT_DOMAIN);
|
||||
|
||||
str = PIKA_VALUES_GET_STRING (args, 1);
|
||||
if (str && *str)
|
||||
closure->help_locales = g_strdup (str);
|
||||
|
||||
str = PIKA_VALUES_GET_STRING (args, 2);
|
||||
closure->help_id = g_strdup ((str && *str)? str : PIKA_HELP_DEFAULT_ID);
|
||||
|
||||
/* Do this on idle, to make sure everything is initialized already */
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
show_help_on_idle,
|
||||
closure, idle_closure_free);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
help_browser_progress_start (const gchar *message,
|
||||
gboolean cancelable,
|
||||
gpointer user_data)
|
||||
{
|
||||
pika_progress_init (message);
|
||||
}
|
||||
|
||||
static void
|
||||
help_browser_progress_update (gdouble value,
|
||||
gpointer user_data)
|
||||
{
|
||||
pika_progress_update (value);
|
||||
}
|
||||
|
||||
static void
|
||||
help_browser_progress_end (gpointer user_data)
|
||||
{
|
||||
pika_progress_end ();
|
||||
}
|
||||
|
||||
static PikaHelpProgress *
|
||||
help_browser_progress_new (void)
|
||||
{
|
||||
static const PikaHelpProgressVTable vtable =
|
||||
{
|
||||
help_browser_progress_start,
|
||||
help_browser_progress_end,
|
||||
help_browser_progress_update
|
||||
};
|
||||
|
||||
return pika_help_progress_new (&vtable, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_help_browser_class_init (PikaHelpBrowserClass *klass)
|
||||
{
|
||||
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
|
||||
|
||||
plug_in_class->query_procedures = help_browser_query_procedures;
|
||||
plug_in_class->create_procedure = help_browser_create_procedure;
|
||||
plug_in_class->set_i18n = STD_SET_I18N;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_help_browser_init (PikaHelpBrowser *help_browser)
|
||||
{
|
||||
}
|
71
plug-ins/help-browser/help-menu.ui
Normal file
71
plug-ins/help-browser/help-menu.ui
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<menu id="help_browser_popup_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Back</attribute>
|
||||
<attribute name="action">win.back</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Previous</attribute>
|
||||
<attribute name="action">win.forward</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Reload</attribute>
|
||||
<attribute name="action">win.reload</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Stop</attribute>
|
||||
<attribute name="action">win.stop</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Home</attribute>
|
||||
<attribute name="action">win.home</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">C_opy location</attribute>
|
||||
<attribute name="action">win.copy-location</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">S_how index</attribute>
|
||||
<attribute name="action">win.show-index</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Find</attribute>
|
||||
<attribute name="action">win.find</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Find _Again</attribute>
|
||||
<attribute name="action">win.find-again</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Zoom in</attribute>
|
||||
<attribute name="action">win.zoom-in</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Zoom out</attribute>
|
||||
<attribute name="action">win.zoom-out</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Close</attribute>
|
||||
<attribute name="action">win.close</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<menu id="help_browser_copy_popup_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Copy selection</attribute>
|
||||
<attribute name="action">win.copy-selection</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
</interface>
|
6
plug-ins/help-browser/help-menus.gresource.xml
Normal file
6
plug-ins/help-browser/help-menus.gresource.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/technology.heckin/help/">
|
||||
<file preprocess="xml-stripblanks">help-menu.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
44
plug-ins/help-browser/meson.build
Normal file
44
plug-ins/help-browser/meson.build
Normal file
@ -0,0 +1,44 @@
|
||||
if get_option('webkit-unmaintained')
|
||||
|
||||
plugin_name = 'help-browser'
|
||||
|
||||
plugin_sources = [
|
||||
'dialog.c',
|
||||
'help-browser.c',
|
||||
'uri.c',
|
||||
]
|
||||
|
||||
plugin_sources += gnome.compile_resources(
|
||||
'help-menus',
|
||||
'help-menus.gresource.xml',
|
||||
)
|
||||
|
||||
if platform_windows
|
||||
plugin_sources += windows.compile_resources(
|
||||
pika_plugins_rc,
|
||||
args: [
|
||||
'--define', 'ORIGINALFILENAME_STR="@0@"'.format(plugin_name+'.exe'),
|
||||
'--define', 'INTERNALNAME_STR="@0@"' .format(plugin_name),
|
||||
'--define', 'TOP_SRCDIR="@0@"' .format(meson.project_source_root()),
|
||||
],
|
||||
include_directories: [
|
||||
rootInclude, appInclude,
|
||||
],
|
||||
)
|
||||
endif
|
||||
|
||||
executable(plugin_name,
|
||||
plugin_sources,
|
||||
dependencies: [
|
||||
libpikaui_dep,
|
||||
gio,
|
||||
webkit,
|
||||
],
|
||||
link_with: [
|
||||
help_plugin_lib,
|
||||
],
|
||||
install: true,
|
||||
install_dir: pikaplugindir / 'plug-ins' / plugin_name,
|
||||
)
|
||||
|
||||
endif
|
390
plug-ins/help-browser/uri.c
Normal file
390
plug-ins/help-browser/uri.c
Normal file
@ -0,0 +1,390 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* The PIKA 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
||||
|
||||
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)
|
||||
return NULL; /* neither uri nor base uri are absolute */
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* skip scheme */
|
||||
while ((c = *cptr++) && c != ':')
|
||||
; /* nada */
|
||||
|
||||
base_cnt = cptr - base_uri; /* incl : */
|
||||
|
||||
if (*cptr != '/')
|
||||
{
|
||||
/* completion not possible */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uri_type == URI_NETPATH)
|
||||
break;
|
||||
|
||||
/* skip authority */
|
||||
if (cptr[0] == '/' && cptr[1] == '/')
|
||||
{
|
||||
part = cptr;
|
||||
cptr += 2;
|
||||
|
||||
while ((c = *cptr++) && c != '/' && c != '?' && c != '#')
|
||||
; /* nada */
|
||||
|
||||
cptr--;
|
||||
base_cnt += cptr - part;
|
||||
}
|
||||
|
||||
if (uri_type == URI_ABSPATH)
|
||||
break;
|
||||
|
||||
/* skip path */
|
||||
if (*cptr != '/')
|
||||
{
|
||||
sep_cnt = 1;
|
||||
sep_str = "/";
|
||||
break;
|
||||
}
|
||||
|
||||
part = cptr;
|
||||
|
||||
g_assert (*cptr == '/');
|
||||
|
||||
while ((c = *cptr++) && c != '?' && c != '#')
|
||||
{
|
||||
if (c == '/')
|
||||
last_segment = cptr - 1;
|
||||
};
|
||||
|
||||
g_assert (last_segment);
|
||||
|
||||
cptr = last_segment;
|
||||
|
||||
while ((c = *uri) && c == '.' && cptr > part)
|
||||
{
|
||||
gint shift_segment = 0;
|
||||
|
||||
c = uri[1];
|
||||
|
||||
if (c == '.' )
|
||||
{
|
||||
c = uri[2];
|
||||
shift_segment = 1;
|
||||
}
|
||||
|
||||
if (c == '/')
|
||||
{
|
||||
uri += 2;
|
||||
}
|
||||
else if (c == 0 || c == '?' || c == '#')
|
||||
{
|
||||
uri += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert (*cptr == '/');
|
||||
|
||||
if (shift_segment)
|
||||
{
|
||||
uri += 1;
|
||||
while (cptr > part && *--cptr != '/')
|
||||
; /* nada */
|
||||
}
|
||||
}
|
||||
|
||||
base_cnt += cptr - part + 1;
|
||||
break;
|
||||
|
||||
case URI_EMPTY:
|
||||
case URI_FRAGMENT:
|
||||
/* use whole base uri */
|
||||
base_cnt = strlen (base_uri);
|
||||
break;
|
||||
|
||||
case URI_UNKNOWN:
|
||||
case URI_INVALID:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* do not include fragment part from the URI reference */
|
||||
for (cptr = uri; (c = *cptr) && c != '#'; cptr++)
|
||||
; /* nada */
|
||||
|
||||
uri_cnt = cptr - uri;
|
||||
|
||||
/* allocate string and copy characters */
|
||||
|
||||
retval = g_new (gchar, base_cnt + sep_cnt + uri_cnt + 1);
|
||||
|
||||
if (base_cnt)
|
||||
strncpy (retval, base_uri, base_cnt);
|
||||
|
||||
if (sep_cnt)
|
||||
strncpy (retval + base_cnt, sep_str, sep_cnt);
|
||||
|
||||
if (uri_cnt)
|
||||
strncpy (retval + base_cnt + sep_cnt, uri, uri_cnt);
|
||||
|
||||
retval[base_cnt + sep_cnt + uri_cnt] = '\0';
|
||||
|
||||
#ifdef URI_DEBUG
|
||||
g_print (" -> \"%s\"\n", retval);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
RFC 2396 URI Generic Syntax August 1998
|
||||
|
||||
|
||||
A. Collected BNF for URI
|
||||
|
||||
URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
|
||||
absoluteURI = scheme ":" ( hier_part | opaque_part )
|
||||
relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
|
||||
|
||||
hier_part = ( net_path | abs_path ) [ "?" query ]
|
||||
opaque_part = uric_no_slash *uric
|
||||
|
||||
uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
|
||||
"&" | "=" | "+" | "$" | ","
|
||||
|
||||
net_path = "//" authority [ abs_path ]
|
||||
abs_path = "/" path_segments
|
||||
rel_path = rel_segment [ abs_path ]
|
||||
|
||||
rel_segment = 1*( unreserved | escaped |
|
||||
";" | "@" | "&" | "=" | "+" | "$" | "," )
|
||||
|
||||
scheme = alpha *( alpha | digit | "+" | "-" | "." )
|
||||
|
||||
authority = server | reg_name
|
||||
|
||||
reg_name = 1*( unreserved | escaped | "$" | "," |
|
||||
";" | ":" | "@" | "&" | "=" | "+" )
|
||||
|
||||
server = [ [ userinfo "@" ] hostport ]
|
||||
userinfo = *( unreserved | escaped |
|
||||
";" | ":" | "&" | "=" | "+" | "$" | "," )
|
||||
|
||||
hostport = host [ ":" port ]
|
||||
host = hostname | IPv4address
|
||||
hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||
domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
||||
IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
|
||||
port = *digit
|
||||
|
||||
path = [ abs_path | opaque_part ]
|
||||
path_segments = segment *( "/" segment )
|
||||
segment = *pchar *( ";" param )
|
||||
param = *pchar
|
||||
pchar = unreserved | escaped |
|
||||
":" | "@" | "&" | "=" | "+" | "$" | ","
|
||||
|
||||
query = *uric
|
||||
|
||||
fragment = *uric
|
||||
|
||||
uric = reserved | unreserved | escaped
|
||||
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
|
||||
"$" | ","
|
||||
unreserved = alphanum | mark
|
||||
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
|
||||
"(" | ")"
|
||||
|
||||
escaped = "%" hex hex
|
||||
hex = digit | "A" | "B" | "C" | "D" | "E" | "F" |
|
||||
"a" | "b" | "c" | "d" | "e" | "f"
|
||||
|
||||
alphanum = alpha | digit
|
||||
alpha = lowalpha | upalpha
|
||||
|
||||
lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
|
||||
"j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
|
||||
"s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
|
||||
upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
|
||||
"J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
|
||||
"S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
|
||||
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
|
||||
"8" | "9"
|
||||
|
||||
#endif
|
26
plug-ins/help-browser/uri.h
Normal file
26
plug-ins/help-browser/uri.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* The PIKA 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
gchar * uri_to_abs (const gchar *uri,
|
||||
const gchar *base_uri);
|
Reference in New Issue
Block a user