File 27-allow-opening-in-browser-again.patch of Package dvdisaster
From: Carlos Maddela <e7appew@gmail.com>
Date: Thu, 5 Jan 2017 19:11:38 +1100
Subject: Resurrect old code to support opening URLs in a browser.
Description: Resurrect old code to support opening URLs in a browser.
Author: Carlos Maddela <e7appew@gmail.com>
Forwarded: not-needed
Last-Update: 2016-12-21
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
---
closure.c | 2 +
dvdisaster.h | 7 +
help-dialogs.c | 3 +-
show-html.c | 402 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 413 insertions(+), 1 deletion(-)
create mode 100644 show-html.c
diff --git a/closure.c b/closure.c
index fa52f09..24c1e8c 100644
--- a/closure.c
+++ b/closure.c
@@ -474,6 +474,7 @@ void InitClosure()
Closure->deviceNames = g_ptr_array_new();
Closure->deviceNodes = g_ptr_array_new();
Closure->viewer = g_strdup("xdg-open");
+ Closure->browser = g_strdup("xdg-open");
Closure->methodList = g_ptr_array_new();
Closure->methodName = g_strdup("RS01");
Closure->dDumpDir = g_strdup(Closure->homeDir);
@@ -589,6 +590,7 @@ void FreeClosure()
cond_free(Closure->binDir);
cond_free(Closure->docDir);
cond_free(Closure->viewer);
+ cond_free(Closure->browser);
cond_free(Closure->errorTitle);
cond_free(Closure->simulateCD);
cond_free(Closure->dDumpDir);
diff --git a/dvdisaster.h b/dvdisaster.h
index 9acd094..f536040 100644
--- a/dvdisaster.h
+++ b/dvdisaster.h
@@ -229,6 +229,7 @@ typedef struct _GlobalClosure
char *binDir; /* place where the binary resides */
char *docDir; /* place where our documentation resides */
char *viewer; /* Name of preferred PDF viewer */
+ char *browser; /* Name of preferred browser */
GMutex progressLock; /* A mutex protected the stuff below */
char bs[256]; /* A string of 255 backspace characters */
@@ -1348,6 +1349,12 @@ int ProbeAltiVec(void);
void ShowPDF(char*);
+/***
+ *** show-html.c
+ ***/
+
+void ShowHTML(char*);
+
/***
*** smart-lec.c
***/
diff --git a/help-dialogs.c b/help-dialogs.c
index 75a615e..dc5b440 100644
--- a/help-dialogs.c
+++ b/help-dialogs.c
@@ -599,7 +599,8 @@ static gint about_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{ case GDK_BUTTON_PRESS:
if(!inside) return FALSE; /* Defect in certain Gtk versions? */
if(!strcmp(label,"GPL")) ShowGPL();
- else if(!strcmp(label,"MODIFYING")) show_modifying();
+ else if(!strcmp(label,"MODIFYING")) show_modifying();
+ else if(strlen(label) > 4 && !strncmp(label, "http", 4)) ShowHTML(g_strdup(label));
else ShowPDF(g_strdup(label));
break;
case GDK_ENTER_NOTIFY:
diff --git a/show-html.c b/show-html.c
new file mode 100644
index 0000000..608e8ec
--- /dev/null
+++ b/show-html.c
@@ -0,0 +1,402 @@
+/* dvdisaster: Additional error correction for optical media.
+ * Copyright (C) 2004-2012 Carsten Gnoerlich.
+ * Project home page: http://www.dvdisaster.com
+ * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
+ *
+ * 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,
+ * or direct your browser at http://www.gnu.org.
+ */
+
+#include "dvdisaster.h"
+
+#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD)
+#include <sys/wait.h>
+#endif
+
+#ifdef SYS_MINGW
+#include "windows.h"
+#include "shellapi.h"
+#endif
+
+/***
+ *** Ask user to specify his browser
+ ***/
+
+#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD)
+
+#define SEARCH_BUTTON 1
+
+typedef struct
+{ GtkWidget *dialog;
+ GtkWidget *entry;
+ GtkWidget *search;
+ GtkWidget *filesel;
+ GtkWidget *fileok;
+ GtkWidget *filecancel;
+ char *url;
+} browser_dialog_info;
+
+static void response_cb(GtkWidget *widget, int response, gpointer data)
+{ browser_dialog_info *bdi = (browser_dialog_info*)data;
+
+ switch(response)
+ { case GTK_RESPONSE_ACCEPT:
+ if(Closure->browser) g_free(Closure->browser);
+ Closure->browser = g_strdup(gtk_entry_get_text(GTK_ENTRY(bdi->entry)));
+ ShowHTML(bdi->url);
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ if(bdi->url) g_free(bdi->url);
+ break;
+ }
+ gtk_widget_destroy(widget);
+ if(bdi->filesel)
+ gtk_widget_destroy(bdi->filesel);
+ g_free(bdi);
+}
+
+static void search_cb(GtkWidget *widget, gpointer data)
+{ browser_dialog_info *bdi = (browser_dialog_info*)data;
+
+ if(widget == bdi->search)
+ { bdi->filesel = gtk_file_selection_new(_utf("windowtitle|Choose a browser"));
+ bdi->fileok = GTK_FILE_SELECTION(bdi->filesel)->ok_button;
+ bdi->filecancel = GTK_FILE_SELECTION(bdi->filesel)->cancel_button;
+ ReverseCancelOK(GTK_DIALOG(bdi->filesel));
+ gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(bdi->filesel));
+ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(bdi->filesel)->ok_button), "clicked",
+ G_CALLBACK(search_cb), bdi);
+
+ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(bdi->filesel)->cancel_button), "clicked",
+ G_CALLBACK(search_cb), bdi);
+
+ gtk_widget_show(bdi->filesel);
+ }
+
+ if(widget == bdi->fileok)
+ {
+ if(Closure->browser) g_free(Closure->browser);
+ Closure->browser = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(bdi->filesel)));
+ ShowHTML(bdi->url);
+ gtk_widget_destroy(bdi->filesel);
+ gtk_widget_destroy(bdi->dialog);
+ g_free(bdi);
+ return;
+ }
+
+ if(widget == bdi->filecancel)
+ { gtk_widget_destroy(bdi->filesel);
+ bdi->filesel = NULL;
+ }
+}
+
+static void browser_dialog(char *url)
+{ GtkWidget *dialog, *vbox, *hbox, *label, *entry, *button;
+ browser_dialog_info *bdi = g_malloc0(sizeof(browser_dialog_info));
+
+ /* Create the dialog */
+
+ dialog = gtk_dialog_new_with_buttons(_utf("windowtitle|Browser required"),
+ Closure->window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
+ bdi->dialog = dialog;
+ if(url)
+ { bdi->url = g_strdup(url);
+ }
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+
+ /* Insert the contents */
+
+ label = gtk_label_new(NULL);
+ gtk_label_set_markup(GTK_LABEL(label), _utf("<b>Could not find a suitable browser.</b>\n\n"
+ "Which browser would you like to use\n"
+ "for reading the online documentation?\n\n"
+ "Please enter its name (e.g. mozilla) or\n"
+ "use the \"Search\" button for a file dialog.\n")),
+ gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 10);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10);
+
+ bdi->entry = entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 10);
+
+ bdi->search = button = gtk_button_new_with_label(_utf("Search"));
+ g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(search_cb), bdi);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10);
+
+ /* Show it */
+
+ g_signal_connect(dialog, "response", G_CALLBACK(response_cb), bdi);
+
+ gtk_widget_show_all(dialog);
+}
+#endif /* SYS_ unix-like */
+
+/***
+ *** Show the manual in an external browser
+ ***/
+
+/*
+ * Check the child processes exit status
+ * to find whether the browser could be invoked.
+ */
+
+typedef struct
+{ pid_t pid;
+ char *url;
+ GtkWidget *msg;
+ int seconds;
+} browser_info;
+
+
+static void msg_destroy_cb(GtkWidget *widget, gpointer data)
+{ browser_info *bi = (browser_info*)data;
+
+ bi->msg = NULL;
+}
+
+#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD)
+
+/*
+ * The following list of browsers and html wrappers
+ * will be tried one at a time until one entry succeeds by:
+ * - returning zero
+ * - not returning within 60 seconds
+ */
+
+static int browser_index;
+static void try_browser(browser_info*);
+
+static char *browsers[] =
+{ "user-selection",
+ "xdg-open",
+ "gnome-open",
+ "htmlview",
+ "firefox",
+ "mozilla",
+ "konqueror",
+ "epiphany",
+ "opera",
+ "/Applications/Safari.app/Contents/MacOS/Safari", /* better way to do this? */
+ NULL
+};
+
+static gboolean browser_timeout_func(gpointer data)
+{ browser_info *bi = (browser_info*)data;
+ int status;
+
+ waitpid(bi->pid, &status, WNOHANG);
+
+ /* At least mozilla returns random values under FreeBSD on success,
+ so we can't rely on the return value exept our own 110 one. */
+
+ if(WIFEXITED(status))
+ {
+ switch(WEXITSTATUS(status))
+ { case 110: /* browser did not execute */
+ browser_index++;
+ if(!browsers[browser_index]) /* all browsers from the list failed */
+ { browser_dialog(bi->url);
+
+ if(bi->msg)
+ gtk_widget_destroy(bi->msg);
+ if(bi->url)
+ g_free(bi->url);
+ g_free(bi);
+ }
+ else /* try next browser from list */
+ { bi->seconds = 0;
+ try_browser(bi);
+ }
+ return FALSE;
+
+ case 0: /* browser assumed to be successful */
+ default:
+ if(bi->msg)
+ gtk_widget_destroy(bi->msg);
+ if(bi->url)
+ g_free(bi->url);
+ g_free(bi);
+ return FALSE;
+ }
+ }
+
+ bi->seconds++;
+ if(bi->seconds == 10 && bi->msg)
+ { gtk_widget_destroy(bi->msg);
+ bi->msg = NULL;
+ }
+
+ return bi->seconds > 60 ? FALSE : TRUE;
+}
+#endif /* SYS_ unix-like */
+
+#ifdef SYS_MINGW
+static gboolean browser_timeout_func(gpointer data)
+{ browser_info *bi = (browser_info*)data;
+
+ bi->seconds++;
+
+ if(bi->seconds >= 10)
+ { if(bi->msg)
+ { gtk_widget_destroy(bi->msg);
+ bi->msg = NULL;
+ }
+ if(bi->url) g_free(bi->url);
+ g_free(bi);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif /* SYS_MINGW */
+
+/*
+ * Invoke the browser
+ */
+
+#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD)
+static void try_browser(browser_info *bi)
+{ pid_t pid;
+
+ bi->pid = pid = fork();
+
+ if(pid == -1)
+ { printf("fork failed\n");
+ return;
+ }
+
+ /* make the parent remember and wait() for the browser */
+
+ if(pid > 0)
+ { g_timeout_add(1000, browser_timeout_func, (gpointer)bi);
+
+ if(browser_index)
+ { g_free(Closure->browser);
+ Closure->browser = g_strdup(browsers[browser_index]);
+ }
+ }
+
+ /* try calling the browser */
+
+ if(pid == 0)
+ { char *argv[10];
+ int argc = 0;
+
+ argv[argc++] = browser_index ? browsers[browser_index] : Closure->browser;
+ argv[argc++] = bi->url;
+ argv[argc++] = NULL;
+ execvp(argv[0], argv);
+
+ _exit(110); /* couldn't execute */
+ }
+}
+#endif /* SYS_ unix-like */
+
+
+void ShowHTML(char *target)
+{ browser_info *bi = g_malloc0(sizeof(browser_info));
+ guint64 ignore;
+ const char *lang;
+ char *path = NULL;
+ int http_url;
+
+ /* If no target is given, select between translations of the manual. */
+
+ if(!target) target = g_strdup("index.html");
+
+ http_url = strlen(target) > 4 && !strncmp(target, "http", 4);
+
+ if(!http_url && !strchr(target, '/')) /* create full path */
+ {
+ if(!Closure->docDir)
+ {
+ CreateMessage(_("Documentation not installed."), GTK_MESSAGE_ERROR);
+ g_free(bi);
+ return;
+ }
+
+ lang = g_getenv("LANG");
+
+ if(lang)
+ { if(!strncmp(lang, "ru", 2))
+#ifdef SYS_MINGW
+ path = g_strdup_printf("%s\\ru\\%s",Closure->docDir,target);
+#else
+ path = g_strdup_printf("%s/ru/%s",Closure->docDir,target);
+#endif
+ else if(!strncmp(lang, "de", 2))
+#ifdef SYS_MINGW
+ path = g_strdup_printf("%s\\de\\%s",Closure->docDir,target);
+#else
+ path = g_strdup_printf("%s/de/%s",Closure->docDir,target);
+#endif
+ }
+
+ if(!path)
+ {
+#ifdef SYS_MINGW
+ path = g_strdup_printf("%s\\en\\%s",Closure->docDir,target);
+#else
+ path = g_strdup_printf("%s/en/%s",Closure->docDir,target);
+#endif
+ }
+
+#ifdef SYS_MINGW
+ if(!LargeStat(path, &ignore))
+ {
+ g_free(path); /* the local dir is Windows specific */
+ path = g_strdup_printf("%s\\local\\%s",Closure->docDir,target);
+ }
+#endif
+ g_free(target);
+ bi->url = path;
+ }
+ else bi->url = target;
+
+ if(!http_url && !LargeStat(bi->url, &ignore))
+ {
+ CreateMessage(_("Documentation file\n%s\nnot found.\n"), GTK_MESSAGE_ERROR, bi->url);
+ g_free(bi);
+ g_free(bi->url);
+ return;
+ }
+
+ /* Lock the help button and show a message for 10 seconds. */
+
+ TimedInsensitive(Closure->helpButton, 10000);
+ bi->msg = CreateMessage(_("Please hang on until the browser comes up!"), GTK_MESSAGE_INFO);
+ g_signal_connect(G_OBJECT(bi->msg), "destroy", G_CALLBACK(msg_destroy_cb), bi);
+
+#ifdef SYS_MINGW
+ /* Okay, Billy wins big time here ;-) */
+
+ ShellExecute(NULL, "open", bi->url, NULL, NULL, SW_SHOWNORMAL);
+ g_timeout_add(1000, browser_timeout_func, (gpointer)bi);
+#endif
+
+#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD)
+ /* Try the first browser */
+
+ browser_index = 0;
+ try_browser(bi);
+#endif
+}