Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/84ec9c2b2a8884c7bdb7e...
...commit
http://git.netsurf-browser.org/netsurf.git/commit/84ec9c2b2a8884c7bdb7e0f...
...tree
http://git.netsurf-browser.org/netsurf.git/tree/84ec9c2b2a8884c7bdb7e0fa4...
The branch, master has been updated
via 84ec9c2b2a8884c7bdb7e0fa461c8b2d9c495cb3 (commit)
via 3cf92011c27a0ae650eae61d5b7749e0a5c0f381 (commit)
from 9e3ef18255464ccf0b7e29db23a436ccdc371959 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=84ec9c2b2a8884c7bdb...
commit 84ec9c2b2a8884c7bdb7e0fa461c8b2d9c495cb3
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
tidy up GTK frontend initialisation
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index d4b0c71..a826b05 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -75,28 +75,176 @@
bool nsgtk_complete = false;
-char *nsgtk_config_home; /* exported global defined in gtk/gui.h */
+/* exported global defined in gtk/gui.h */
+char *nsgtk_config_home;
-GdkPixbuf *favicon_pixbuf; /** favicon default pixbuf */
-GdkPixbuf *win_default_icon_pixbuf; /** default window icon pixbuf */
+/** favicon default pixbuf */
+GdkPixbuf *favicon_pixbuf;
+
+/** default window icon pixbuf */
+GdkPixbuf *win_default_icon_pixbuf;
GtkBuilder *warning_builder;
-char **respaths; /** resource search path vector */
+/** resource search path vector */
+char **respaths;
-/**
- * Cause an abnormal program termination.
- *
- * \note This never returns and is intended to terminate without any cleanup.
- *
- * \param error The message to display to the user.
- */
-static void die(const char * const error)
+
+/* exported function documented in gtk/warn.h */
+nserror nsgtk_warning(const char *warning, const char *detail)
+{
+ char buf[300]; /* 300 is the size the RISC OS GUI uses */
+ static GtkWindow *nsgtk_warning_window;
+ GtkLabel *WarningLabel;
+
+ NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
+ fflush(stdout);
+
+ nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder,
"wndWarning"));
+ WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
+ "labelWarning"));
+
+ snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
+ detail ? detail : "");
+ buf[sizeof(buf) - 1] = 0;
+
+ gtk_label_set_text(WarningLabel, buf);
+
+ gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/gui.h */
+uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
{
- fprintf(stderr, "%s", error);
- exit(EXIT_FAILURE);
+ /* this function will need to become much more complex to support
+ * everything that the RISC OS version does. But this will do for
+ * now. I hope.
+ */
+ switch (key->keyval) {
+
+ case GDK_KEY(Tab):
+ return NS_KEY_TAB;
+
+ case GDK_KEY(BackSpace):
+ if (key->state & GDK_SHIFT_MASK)
+ return NS_KEY_DELETE_LINE_START;
+ else
+ return NS_KEY_DELETE_LEFT;
+
+ case GDK_KEY(Delete):
+ if (key->state & GDK_SHIFT_MASK)
+ return NS_KEY_DELETE_LINE_END;
+ else
+ return NS_KEY_DELETE_RIGHT;
+
+ case GDK_KEY(Linefeed):
+ return 13;
+
+ case GDK_KEY(Return):
+ return 10;
+
+ case GDK_KEY(Left):
+ case GDK_KEY(KP_Left):
+ return NS_KEY_LEFT;
+
+ case GDK_KEY(Right):
+ case GDK_KEY(KP_Right):
+ return NS_KEY_RIGHT;
+
+ case GDK_KEY(Up):
+ case GDK_KEY(KP_Up):
+ return NS_KEY_UP;
+
+ case GDK_KEY(Down):
+ case GDK_KEY(KP_Down):
+ return NS_KEY_DOWN;
+
+ case GDK_KEY(Home):
+ case GDK_KEY(KP_Home):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_START;
+ else
+ return NS_KEY_TEXT_START;
+
+ case GDK_KEY(End):
+ case GDK_KEY(KP_End):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_END;
+ else
+ return NS_KEY_TEXT_END;
+
+ case GDK_KEY(Page_Up):
+ case GDK_KEY(KP_Page_Up):
+ return NS_KEY_PAGE_UP;
+
+ case GDK_KEY(Page_Down):
+ case GDK_KEY(KP_Page_Down):
+ return NS_KEY_PAGE_DOWN;
+
+ case 'a':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_SELECT_ALL;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'u':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_LINE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'c':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_COPY_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'v':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_PASTE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'x':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_CUT_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'Z':
+ case 'y':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_REDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'z':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_UNDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case GDK_KEY(Escape):
+ return NS_KEY_ESCAPE;
+
+ /* Modifiers - do nothing for now */
+ case GDK_KEY(Shift_L):
+ case GDK_KEY(Shift_R):
+ case GDK_KEY(Control_L):
+ case GDK_KEY(Control_R):
+ case GDK_KEY(Caps_Lock):
+ case GDK_KEY(Shift_Lock):
+ case GDK_KEY(Meta_L):
+ case GDK_KEY(Meta_R):
+ case GDK_KEY(Alt_L):
+ case GDK_KEY(Alt_R):
+ case GDK_KEY(Super_L):
+ case GDK_KEY(Super_R):
+ case GDK_KEY(Hyper_L):
+ case GDK_KEY(Hyper_R):
+ return 0;
+
+ }
+ return gdk_keyval_to_unicode(key->keyval);
}
+
/**
* Create an array of valid paths to search for resources.
*
@@ -155,799 +303,732 @@ nsgtk_init_resource_path(const char *config_home)
/**
- * Set option defaults for gtk frontend.
- *
- * \param defaults The option table to update.
- * \return error status.
+ * create directory name and check it is acessible and a directory.
*/
-static nserror set_defaults(struct nsoption_s *defaults)
+static nserror
+check_dirname(const char *path, const char *leaf, char **dirname_out)
{
- char *fname;
- GtkSettings *settings;
- GtkIconSize tooliconsize;
- GtkToolbarStyle toolbarstyle;
-
- /* cookie file default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_file, fname);
- }
-
- /* cookie jar default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_jar, fname);
- }
+ nserror ret;
+ char *dirname = NULL;
+ struct stat dirname_stat;
- /* url database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
- if (fname != NULL) {
- nsoption_setnull_charp(url_file, fname);
+ ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
+ if (ret != NSERROR_OK) {
+ return ret;
}
- /* bookmark database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
- if (fname != NULL) {
- nsoption_setnull_charp(hotlist_path, fname);
+ /* ensure access is possible and the entry is actualy
+ * a directory.
+ */
+ if (stat(dirname, &dirname_stat) == 0) {
+ if (S_ISDIR(dirname_stat.st_mode)) {
+ if (access(dirname, R_OK | W_OK) == 0) {
+ *dirname_out = dirname;
+ return NSERROR_OK;
+ } else {
+ ret = NSERROR_PERMISSION;
+ }
+ } else {
+ ret = NSERROR_NOT_DIRECTORY;
+ }
+ } else {
+ ret = NSERROR_NOT_FOUND;
}
- /* download directory default */
- fname = getenv("HOME");
- if (fname != NULL) {
- nsoption_setnull_charp(downloads_directory, strdup(fname));
- }
+ free(dirname);
- if ((nsoption_charp(cookie_file) == NULL) ||
- (nsoption_charp(cookie_jar) == NULL) ||
- (nsoption_charp(url_file) == NULL) ||
- (nsoption_charp(hotlist_path) == NULL) ||
- (nsoption_charp(downloads_directory) == NULL)) {
- NSLOG(netsurf, INFO,
- "Failed initialising default resource paths");
- return NSERROR_BAD_PARAMETER;
- }
+ return ret;
+}
- /* set default font names */
- nsoption_set_charp(font_sans, strdup("Sans"));
- nsoption_set_charp(font_serif, strdup("Serif"));
- nsoption_set_charp(font_mono, strdup("Monospace"));
- nsoption_set_charp(font_cursive, strdup("Serif"));
- nsoption_set_charp(font_fantasy, strdup("Serif"));
- /* Default toolbar button type to system defaults */
+/**
+ * Get the path to the config directory.
+ *
+ * @param config_home_out Path to configuration directory.
+ * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
+ */
+static nserror get_config_home(char **config_home_out)
+{
+ nserror ret;
+ char *home_dir;
+ char *xdg_config_dir;
+ char *config_home;
- settings = gtk_settings_get_default();
- g_object_get(settings,
- "gtk-toolbar-icon-size", &tooliconsize,
- "gtk-toolbar-style", &toolbarstyle, NULL);
+ home_dir = getenv("HOME");
- switch (toolbarstyle) {
- case GTK_TOOLBAR_ICONS:
- if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
- nsoption_set_int(button_type, 1);
- } else {
- nsoption_set_int(button_type, 2);
+ /* The old $HOME/.netsurf/ directory should be used if it
+ * exists and is accessible.
+ */
+ if (home_dir != NULL) {
+ ret = check_dirname(home_dir, ".netsurf", &config_home);
+ if (ret == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+ *config_home_out = config_home;
+ return ret;
}
- break;
+ }
- case GTK_TOOLBAR_TEXT:
- nsoption_set_int(button_type, 4);
- break;
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
- case GTK_TOOLBAR_BOTH:
- case GTK_TOOLBAR_BOTH_HORIZ:
- /* no labels in default configuration */
- default:
- /* No system default, so use large icons */
- nsoption_set_int(button_type, 2);
- break;
- }
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ /* If $XDG_CONFIG_HOME is either not set or empty, a
+ * default equal to $HOME/.config should be used.
+ */
- /* set default items in toolbar */
- nsoption_set_charp(toolbar_items,
- strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
+ /** @todo the meaning of empty is never defined so I
+ * am assuming it is a zero length string but is it
+ * supposed to mean "whitespace" and if so what counts
+ * as whitespace? (are tabs etc. counted or should
+ * isspace() be used)
+ */
- /* set default for menu and tool bar visibility */
- nsoption_set_charp(bar_show, strdup("tool"));
+ /* the HOME envvar is required */
+ if (home_dir == NULL) {
+ return NSERROR_NOT_DIRECTORY;
+ }
- return NSERROR_OK;
-}
+ ret = check_dirname(home_dir, ".config/netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
-#if GTK_CHECK_VERSION(3,14,0)
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
-/**
- * adds named icons into gtk theme
- */
-static nserror nsgtk_add_named_icons_to_theme(void)
-{
- gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
- "/org/netsurf/icons");
+ *config_home_out = config_home;
return NSERROR_OK;
}
-#else
-static nserror
-add_builtin_icon(const char *prefix, const char *name, int x, int y)
+static nserror create_config_home(char **config_home_out)
{
- GdkPixbuf *pixbuf;
- nserror res;
- char *resname;
- int resnamelen;
+ char *config_home = NULL;
+ char *home_dir;
+ char *xdg_config_dir;
+ nserror ret;
- /* resource name string length allowing for / .png and termination */
- resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
- resname = malloc(resnamelen);
- if (resname == NULL) {
- return NSERROR_NOMEM;
+ NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
+
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ home_dir = getenv("HOME");
+
+ if ((home_dir == NULL) || (*home_dir == 0)) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = netsurf_mkpath(&config_home, NULL, 4, home_dir,
".config","netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf",
"/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
}
- snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
- res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
- NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
- free(resname);
- if (res != NSERROR_OK) {
- pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
+ /* ensure all elements of path exist (the trailing / is required) */
+ ret = netsurf_mkdir_all(config_home);
+ if (ret != NSERROR_OK) {
+ free(config_home);
+ return ret;
}
- gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
+
+ /* strip the trailing separator */
+ config_home[strlen(config_home) - 1] = 0;
+
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+
+ *config_home_out = config_home;
return NSERROR_OK;
}
+
/**
- * adds named icons into gtk theme
+ * Ensures output logging stream is correctly configured
*/
-static nserror nsgtk_add_named_icons_to_theme(void)
+static bool nslog_stream_configure(FILE *fptr)
{
- /* these must also be in gtk/resources.c pixbuf_resource *and*
- * gtk/res/netsurf.gresource.xml
- */
- add_builtin_icon("", "local-history", 8, 32);
- add_builtin_icon("", "show-cookie", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
- add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
- return NSERROR_OK;
+ return true;
}
-#endif
-
/**
- * setup GTK specific parts of the browser.
+ * Set option defaults for gtk frontend.
*
- * \param argc The number of arguments on the command line
- * \param argv A string vector of command line arguments.
- * \respath A string vector of the path elements of resources
+ * \param defaults The option table to update.
+ * \return error status.
*/
-static nserror nsgtk_setup(int argc, char** argv, char **respath)
+static nserror set_defaults(struct nsoption_s *defaults)
{
- char buf[PATH_MAX];
- char *resource_filename;
- char *addr = NULL;
- nsurl *url;
- nserror res;
+ char *fname;
+ GtkSettings *settings;
+ GtkIconSize tooliconsize;
+ GtkToolbarStyle toolbarstyle;
- /* Initialise gtk accelerator table */
- res = nsgtk_accelerator_init(respaths);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to load gtk accelerator configuration");
- /* not fatal if this does not load */
+ /* cookie file default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_file, fname);
}
- /* initialise warning dialog */
- res = nsgtk_builder_new_from_resname("warning", &warning_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
- return res;
+ /* cookie jar default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_jar, fname);
}
- gtk_builder_connect_signals(warning_builder, NULL);
-
- /* set default icon if its available */
- res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
- &win_default_icon_pixbuf);
- if (res == NSERROR_OK) {
- NSLOG(netsurf, INFO, "Seting default window icon");
- gtk_window_set_default_icon(win_default_icon_pixbuf);
+ /* url database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
+ if (fname != NULL) {
+ nsoption_setnull_charp(url_file, fname);
}
- /* Search engine sources */
- resource_filename = filepath_find(respath, "SearchEngines");
- search_web_init(resource_filename);
- if (resource_filename != NULL) {
- NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
- resource_filename);
- free(resource_filename);
+ /* bookmark database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
+ if (fname != NULL) {
+ nsoption_setnull_charp(hotlist_path, fname);
}
- search_web_select_provider(nsoption_int(search_provider));
- /* Default favicon */
- res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
- if (res != NSERROR_OK) {
- favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 16, 16);
+ /* download directory default */
+ fname = getenv("HOME");
+ if (fname != NULL) {
+ nsoption_setnull_charp(downloads_directory, strdup(fname));
}
- /* add named icons to gtk theme */
- res = nsgtk_add_named_icons_to_theme();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
- return res;
+ if ((nsoption_charp(cookie_file) == NULL) ||
+ (nsoption_charp(cookie_jar) == NULL) ||
+ (nsoption_charp(url_file) == NULL) ||
+ (nsoption_charp(hotlist_path) == NULL) ||
+ (nsoption_charp(downloads_directory) == NULL)) {
+ NSLOG(netsurf, INFO,
+ "Failed initialising default resource paths");
+ return NSERROR_BAD_PARAMETER;
}
- /* initialise throbber */
- res = nsgtk_throbber_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise throbber.");
- return res;
- }
+ /* set default font names */
+ nsoption_set_charp(font_sans, strdup("Sans"));
+ nsoption_set_charp(font_serif, strdup("Serif"));
+ nsoption_set_charp(font_mono, strdup("Monospace"));
+ nsoption_set_charp(font_cursive, strdup("Serif"));
+ nsoption_set_charp(font_fantasy, strdup("Serif"));
- /* Initialise completions - cannot fail */
- nsgtk_completion_init();
-
- /* The tree view system needs to know the screen's DPI, so we
- * find that out here, rather than when we create a first browser
- * window.
- */
- browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
- NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
-
- filepath_sfinddef(respath, buf, "mime.types", "/etc/");
- gtk_fetch_filetype_init(buf);
-
- save_complete_init();
-
- urldb_load(nsoption_charp(url_file));
- urldb_load_cookies(nsoption_charp(cookie_file));
- hotlist_init(nsoption_charp(hotlist_path),
- nsoption_charp(hotlist_path));
-
- /* Initialise top level UI elements */
- res = nsgtk_download_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise download window.");
- return res;
- }
+ /* Default toolbar button type to system defaults */
- /* If there is a url specified on the command line use it */
- if (argc > 1) {
- struct stat fs;
- if (stat(argv[1], &fs) == 0) {
- size_t addrlen;
- char *rp = realpath(argv[1], NULL);
- assert(rp != NULL);
+ settings = gtk_settings_get_default();
+ g_object_get(settings,
+ "gtk-toolbar-icon-size", &tooliconsize,
+ "gtk-toolbar-style", &toolbarstyle, NULL);
- /* calculate file url length including terminator */
- addrlen = SLEN("file://") + strlen(rp) + 1;
- addr = malloc(addrlen);
- assert(addr != NULL);
- snprintf(addr, addrlen, "file://%s", rp);
- free(rp);
+ switch (toolbarstyle) {
+ case GTK_TOOLBAR_ICONS:
+ if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
+ nsoption_set_int(button_type, 1);
} else {
- addr = strdup(argv[1]);
+ nsoption_set_int(button_type, 2);
}
- }
- if (addr != NULL) {
- /* managed to set up based on local launch */
- } else if (nsoption_charp(homepage_url) != NULL) {
- addr = strdup(nsoption_charp(homepage_url));
- } else {
- addr = strdup(NETSURF_HOMEPAGE);
- }
+ break;
- /* create an initial browser window */
- res = nsurl_create(addr, &url);
- if (res == NSERROR_OK) {
- res = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
+ case GTK_TOOLBAR_TEXT:
+ nsoption_set_int(button_type, 4);
+ break;
+
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ /* no labels in default configuration */
+ default:
+ /* No system default, so use large icons */
+ nsoption_set_int(button_type, 2);
+ break;
}
- free(addr);
+ /* set default items in toolbar */
+ nsoption_set_charp(toolbar_items,
+ strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
- return res;
-}
+ /* set default for menu and tool bar visibility */
+ nsoption_set_charp(bar_show, strdup("tool"));
+ return NSERROR_OK;
+}
/**
- * Ensures output logging stream is correctly configured
+ * Initialise user options
+ *
+ * Initialise the browser configuration options. These are set by:
+ * - set generic defaults suitable for the gtk frontend
+ * - user choices loaded from Choices file
+ * - command line parameters
*/
-static bool nslog_stream_configure(FILE *fptr)
-{
- /* set log stream to be non-buffering */
- setbuf(fptr, NULL);
-
- return true;
-}
-
-
-
-
-
-
-/* exported function documented in gtk/warn.h */
-nserror nsgtk_warning(const char *warning, const char *detail)
+static nserror nsgtk_option_init(int *pargc, char** argv)
{
- char buf[300]; /* 300 is the size the RISC OS GUI uses */
- static GtkWindow *nsgtk_warning_window;
- GtkLabel *WarningLabel;
+ nserror ret;
+ char *choices = NULL;
- NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
- fflush(stdout);
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
- nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder,
"wndWarning"));
- WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
- "labelWarning"));
+ /* Attempt to load the user choices */
+ ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (ret == NSERROR_OK) {
+ nsoption_read(choices, nsoptions);
+ free(choices);
+ }
- snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
- detail ? detail : "");
- buf[sizeof(buf) - 1] = 0;
+ /* overide loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
- gtk_label_set_text(WarningLabel, buf);
+ /* ensure all options fall within sensible bounds */
- gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
+ /* Attempt to handle nonsense status bar widths. These may exist
+ * in people's Choices as the GTK front end used to abuse the
+ * status bar width option by using it for an absolute value in px.
+ * The GTK front end now correctly uses it as a proportion of window
+ * width. Here we assume that a value of less than 15% is wrong
+ * and set to the default two thirds. */
+ if (nsoption_int(toolbar_status_size) < 1500) {
+ nsoption_set_int(toolbar_status_size, 6667);
+ }
return NSERROR_OK;
}
-
-
-uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
-{
- /* this function will need to become much more complex to support
- * everything that the RISC OS version does. But this will do for
- * now. I hope.
- */
- switch (key->keyval) {
-
- case GDK_KEY(Tab):
- return NS_KEY_TAB;
-
- case GDK_KEY(BackSpace):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_START;
- else
- return NS_KEY_DELETE_LEFT;
-
- case GDK_KEY(Delete):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_END;
- else
- return NS_KEY_DELETE_RIGHT;
-
- case GDK_KEY(Linefeed):
- return 13;
-
- case GDK_KEY(Return):
- return 10;
-
- case GDK_KEY(Left):
- case GDK_KEY(KP_Left):
- return NS_KEY_LEFT;
-
- case GDK_KEY(Right):
- case GDK_KEY(KP_Right):
- return NS_KEY_RIGHT;
-
- case GDK_KEY(Up):
- case GDK_KEY(KP_Up):
- return NS_KEY_UP;
-
- case GDK_KEY(Down):
- case GDK_KEY(KP_Down):
- return NS_KEY_DOWN;
-
- case GDK_KEY(Home):
- case GDK_KEY(KP_Home):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_START;
- else
- return NS_KEY_TEXT_START;
-
- case GDK_KEY(End):
- case GDK_KEY(KP_End):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_END;
- else
- return NS_KEY_TEXT_END;
-
- case GDK_KEY(Page_Up):
- case GDK_KEY(KP_Page_Up):
- return NS_KEY_PAGE_UP;
-
- case GDK_KEY(Page_Down):
- case GDK_KEY(KP_Page_Down):
- return NS_KEY_PAGE_DOWN;
-
- case 'a':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_SELECT_ALL;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'u':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_DELETE_LINE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'c':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_COPY_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'v':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_PASTE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'x':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_CUT_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'Z':
- case 'y':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_REDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'z':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_UNDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case GDK_KEY(Escape):
- return NS_KEY_ESCAPE;
-
- /* Modifiers - do nothing for now */
- case GDK_KEY(Shift_L):
- case GDK_KEY(Shift_R):
- case GDK_KEY(Control_L):
- case GDK_KEY(Control_R):
- case GDK_KEY(Caps_Lock):
- case GDK_KEY(Shift_Lock):
- case GDK_KEY(Meta_L):
- case GDK_KEY(Meta_R):
- case GDK_KEY(Alt_L):
- case GDK_KEY(Alt_R):
- case GDK_KEY(Super_L):
- case GDK_KEY(Super_R):
- case GDK_KEY(Hyper_L):
- case GDK_KEY(Hyper_R):
- return 0;
-
- }
- return gdk_keyval_to_unicode(key->keyval);
-}
-
-
/**
- * create directory name and check it is acessible and a directory.
+ * initialise message translation
*/
-static nserror
-check_dirname(const char *path, const char *leaf, char **dirname_out)
+static nserror nsgtk_messages_init(char **respaths)
{
+ const char *messages;
nserror ret;
- char *dirname = NULL;
- struct stat dirname_stat;
-
- ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
- if (ret != NSERROR_OK) {
- return ret;
- }
-
- /* ensure access is possible and the entry is actualy
- * a directory.
- */
- if (stat(dirname, &dirname_stat) == 0) {
- if (S_ISDIR(dirname_stat.st_mode)) {
- if (access(dirname, R_OK | W_OK) == 0) {
- *dirname_out = dirname;
- return NSERROR_OK;
- } else {
- ret = NSERROR_PERMISSION;
- }
- } else {
- ret = NSERROR_NOT_DIRECTORY;
- }
+ const uint8_t *data;
+ size_t data_size;
+
+ ret = nsgtk_data_from_resname("Messages", &data, &data_size);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_inline(data, data_size);
} else {
- ret = NSERROR_NOT_FOUND;
+ /* Obtain path to messages */
+ ret = nsgtk_path_from_resname("Messages", &messages);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_file(messages);
+ }
}
-
- free(dirname);
-
return ret;
}
+
/**
- * Get the path to the config directory.
+ * Get the path to the cache directory.
*
- * @param config_home_out Path to configuration directory.
- * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
+ * @param cache_home_out Path to cache directory.
+ * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
*/
-static nserror get_config_home(char **config_home_out)
+static nserror get_cache_home(char **cache_home_out)
{
nserror ret;
+ char *xdg_cache_dir;
+ char *cache_home;
char *home_dir;
- char *xdg_config_dir;
- char *config_home;
-
- home_dir = getenv("HOME");
-
- /* The old $HOME/.netsurf/ directory should be used if it
- * exists and is accessible.
- */
- if (home_dir != NULL) {
- ret = check_dirname(home_dir, ".netsurf", &config_home);
- if (ret == NSERROR_OK) {
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
- *config_home_out = config_home;
- return ret;
- }
- }
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
- * should be stored.
+ /* $XDG_CACHE_HOME defines the base directory relative to
+ * which user specific non-essential data files should be
+ * stored.
*/
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
- /* If $XDG_CONFIG_HOME is either not set or empty, a
- * default equal to $HOME/.config should be used.
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
+ /* If $XDG_CACHE_HOME is either not set or empty, a
+ * default equal to $HOME/.cache should be used.
*/
- /** @todo the meaning of empty is never defined so I
- * am assuming it is a zero length string but is it
- * supposed to mean "whitespace" and if so what counts
- * as whitespace? (are tabs etc. counted or should
- * isspace() be used)
- */
+ home_dir = getenv("HOME");
/* the HOME envvar is required */
if (home_dir == NULL) {
return NSERROR_NOT_DIRECTORY;
}
- ret = check_dirname(home_dir, ".config/netsurf", &config_home);
+ ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
if (ret != NSERROR_OK) {
return ret;
}
} else {
- ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
+ ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
if (ret != NSERROR_OK) {
return ret;
}
}
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
- *config_home_out = config_home;
+ *cache_home_out = cache_home;
return NSERROR_OK;
}
-static nserror create_config_home(char **config_home_out)
+
+/**
+ * create a cache directory
+ */
+static nserror create_cache_home(char **cache_home_out)
{
- char *config_home = NULL;
+ char *cache_home = NULL;
char *home_dir;
- char *xdg_config_dir;
+ char *xdg_cache_dir;
nserror ret;
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+ NSLOG(netsurf, INFO, "Attempting to create cache directory");
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
+ /* $XDG_CACHE_HOME defines the base directory
+ * relative to which user specific cache files
* should be stored.
*/
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
home_dir = getenv("HOME");
if ((home_dir == NULL) || (*home_dir == 0)) {
return NSERROR_NOT_DIRECTORY;
}
- ret = netsurf_mkpath(&config_home, NULL, 4, home_dir,
".config","netsurf", "/");
+ ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache",
"netsurf", "/");
if (ret != NSERROR_OK) {
return ret;
}
} else {
- ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf",
"/");
+ ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf",
"/");
if (ret != NSERROR_OK) {
return ret;
}
}
/* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(config_home);
+ ret = netsurf_mkdir_all(cache_home);
if (ret != NSERROR_OK) {
- free(config_home);
+ free(cache_home);
return ret;
}
/* strip the trailing separator */
- config_home[strlen(config_home) - 1] = 0;
+ cache_home[strlen(cache_home) - 1] = 0;
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
- *config_home_out = config_home;
+ *cache_home_out = cache_home;
return NSERROR_OK;
}
+
/**
- * Get the path to the cache directory.
- *
- * @param cache_home_out Path to cache directory.
- * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
+ * GTK specific initialisation
*/
-static nserror get_cache_home(char **cache_home_out)
+static nserror nsgtk_init(int *pargc, char ***pargv, char **cache_home)
{
nserror ret;
- char *xdg_cache_dir;
- char *cache_home;
- char *home_dir;
- /* $XDG_CACHE_HOME defines the base directory relative to
- * which user specific non-essential data files should be
- * stored.
+ /* Locate the correct user configuration directory path */
+ ret = get_config_home(&nsgtk_config_home);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no config directory exists yet so try to create one */
+ ret = create_config_home(&nsgtk_config_home);
+ }
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to locate a configuration directory.");
+ nsgtk_config_home = NULL;
+ }
+
+ /* Initialise gtk */
+ gtk_init(pargc, pargv);
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
*/
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
+ nslog_init(nslog_stream_configure, pargc, *pargv);
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- /* If $XDG_CACHE_HOME is either not set or empty, a
- * default equal to $HOME/.cache should be used.
- */
+ /* build the common resource path list */
+ respaths = nsgtk_init_resource_path(nsgtk_config_home);
+ if (respaths == NULL) {
+ fprintf(stderr, "Unable to locate resources\n");
+ return 1;
+ }
- home_dir = getenv("HOME");
+ /* initialise the gtk resource handling */
+ ret = nsgtk_init_resources(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "GTK resources failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
- /* the HOME envvar is required */
- if (home_dir == NULL) {
- return NSERROR_NOT_DIRECTORY;
- }
+ /* Initialise user options */
+ ret = nsgtk_option_init(pargc, *pargv);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Options failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
- ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
+ /* Initialise translated messages */
+ ret = nsgtk_messages_init(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Unable to load translated messages (%s)\n",
+ messages_get_errorcode(ret));
+ NSLOG(netsurf, INFO, "Unable to load translated messages");
+ /** \todo decide if message load faliure should be fatal */
+ }
+
+ /* Locate the correct user cache directory path */
+ ret = get_cache_home(cache_home);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no cache directory exists yet so try to create one */
+ ret = create_cache_home(cache_home);
+ }
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
}
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
- *cache_home_out = cache_home;
return NSERROR_OK;
}
-static nserror create_cache_home(char **cache_home_out)
+
+#if GTK_CHECK_VERSION(3,14,0)
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
{
- char *cache_home = NULL;
- char *home_dir;
- char *xdg_cache_dir;
- nserror ret;
+ gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
+ "/org/netsurf/icons");
+ return NSERROR_OK;
+}
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+#else
- /* $XDG_CACHE_HOME defines the base directory
- * relative to which user specific cache files
- * should be stored.
+static nserror
+add_builtin_icon(const char *prefix, const char *name, int x, int y)
+{
+ GdkPixbuf *pixbuf;
+ nserror res;
+ char *resname;
+ int resnamelen;
+
+ /* resource name string length allowing for / .png and termination */
+ resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
+ resname = malloc(resnamelen);
+ if (resname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
+
+ res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
+ NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
+ free(resname);
+ if (res != NSERROR_OK) {
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
+ }
+ gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ /* these must also be in gtk/resources.c pixbuf_resource *and*
+ * gtk/res/netsurf.gresource.xml
*/
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
+ add_builtin_icon("", "local-history", 8, 32);
+ add_builtin_icon("", "show-cookie", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
+ add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
+
+ return NSERROR_OK;
+}
+
+#endif
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- home_dir = getenv("HOME");
- if ((home_dir == NULL) || (*home_dir == 0)) {
- return NSERROR_NOT_DIRECTORY;
- }
+/**
+ * setup GTK specific parts of the browser.
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ * \respath A string vector of the path elements of resources
+ */
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
+{
+ char buf[PATH_MAX];
+ char *resource_filename;
+ char *addr = NULL;
+ nsurl *url;
+ nserror res;
- ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache",
"netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf",
"/");
- if (ret != NSERROR_OK) {
- return ret;
- }
+ /* Initialise gtk accelerator table */
+ res = nsgtk_accelerator_init(respaths);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to load gtk accelerator configuration");
+ /* not fatal if this does not load */
}
- /* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(cache_home);
- if (ret != NSERROR_OK) {
- free(cache_home);
- return ret;
+ /* initialise warning dialog */
+ res = nsgtk_builder_new_from_resname("warning", &warning_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
+ return res;
}
- /* strip the trailing separator */
- cache_home[strlen(cache_home) - 1] = 0;
-
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+ gtk_builder_connect_signals(warning_builder, NULL);
- *cache_home_out = cache_home;
+ /* set default icon if its available */
+ res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
+ &win_default_icon_pixbuf);
+ if (res == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Seting default window icon");
+ gtk_window_set_default_icon(win_default_icon_pixbuf);
+ }
- return NSERROR_OK;
-}
+ /* Search engine sources */
+ resource_filename = filepath_find(respath, "SearchEngines");
+ search_web_init(resource_filename);
+ if (resource_filename != NULL) {
+ NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
+ resource_filename);
+ free(resource_filename);
+ }
+ search_web_select_provider(nsoption_int(search_provider));
-static nserror nsgtk_option_init(int *pargc, char** argv)
-{
- nserror ret;
- char *choices = NULL;
+ /* Default favicon */
+ res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
+ if (res != NSERROR_OK) {
+ favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+ false, 8, 16, 16);
+ }
- /* user options setup */
- ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
- if (ret != NSERROR_OK) {
- return ret;
+ /* add named icons to gtk theme */
+ res = nsgtk_add_named_icons_to_theme();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
+ return res;
}
- /* Attempt to load the user choices */
- ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (ret == NSERROR_OK) {
- nsoption_read(choices, nsoptions);
- free(choices);
+ /* initialise throbber */
+ res = nsgtk_throbber_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise throbber.");
+ return res;
}
- /* overide loaded options with those from commandline */
- nsoption_commandline(pargc, argv, nsoptions);
+ /* Initialise completions - cannot fail */
+ nsgtk_completion_init();
- /* ensure all options fall within sensible bounds */
+ /* The tree view system needs to know the screen's DPI, so we
+ * find that out here, rather than when we create a first browser
+ * window.
+ */
+ browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
+ NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
- /* Attempt to handle nonsense status bar widths. These may exist
- * in people's Choices as the GTK front end used to abuse the
- * status bar width option by using it for an absolute value in px.
- * The GTK front end now correctly uses it as a proportion of window
- * width. Here we assume that a value of less than 15% is wrong
- * and set to the default two thirds. */
- if (nsoption_int(toolbar_status_size) < 1500) {
- nsoption_set_int(toolbar_status_size, 6667);
- }
+ filepath_sfinddef(respath, buf, "mime.types", "/etc/");
+ gtk_fetch_filetype_init(buf);
- return NSERROR_OK;
-}
+ save_complete_init();
+ urldb_load(nsoption_charp(url_file));
+ urldb_load_cookies(nsoption_charp(cookie_file));
+ hotlist_init(nsoption_charp(hotlist_path),
+ nsoption_charp(hotlist_path));
+ /* Initialise top level UI elements */
+ res = nsgtk_download_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise download window.");
+ return res;
+ }
-static nserror nsgtk_messages_init(char **respaths)
-{
- const char *messages;
- nserror ret;
- const uint8_t *data;
- size_t data_size;
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
- ret = nsgtk_data_from_resname("Messages", &data, &data_size);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_inline(data, data_size);
- } else {
- /* Obtain path to messages */
- ret = nsgtk_path_from_resname("Messages", &messages);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_file(messages);
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
+ } else {
+ addr = strdup(argv[1]);
}
}
- return ret;
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
+ } else {
+ addr = strdup(NETSURF_HOMEPAGE);
+ }
+
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ free(addr);
+
+ return res;
}
@@ -1084,8 +1165,8 @@ static void nsgtk_finalise(void)
*/
int main(int argc, char** argv)
{
+ nserror res;
char *cache_home = NULL;
- nserror ret;
struct netsurf_table nsgtk_table = {
.misc = nsgtk_misc_table,
.window = nsgtk_window_table,
@@ -1099,94 +1180,43 @@ int main(int argc, char** argv)
.layout = nsgtk_layout_table,
};
- ret = netsurf_register(&nsgtk_table);
- if (ret != NSERROR_OK) {
- die("NetSurf operation table failed registration\n");
- }
-
- /* Locate the correct user configuration directory path */
- ret = get_config_home(&nsgtk_config_home);
- if (ret == NSERROR_NOT_FOUND) {
- /* no config directory exists yet so try to create one */
- ret = create_config_home(&nsgtk_config_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to locate a configuration directory.");
- nsgtk_config_home = NULL;
- }
-
- /* Initialise gtk */
- gtk_init(&argc, &argv);
-
- /* initialise logging. Not fatal if it fails but not much we
- * can do about it either.
- */
- nslog_init(nslog_stream_configure, &argc, argv);
-
- /* build the common resource path list */
- respaths = nsgtk_init_resource_path(nsgtk_config_home);
- if (respaths == NULL) {
- fprintf(stderr, "Unable to locate resources\n");
- return 1;
- }
-
- /* initialise the gtk resource handling */
- ret = nsgtk_init_resources(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "GTK resources failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
- }
-
- /* Initialise user options */
- ret = nsgtk_option_init(&argc, argv);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Options failed to initialise (%s)\n",
- messages_get_errorcode(ret));
+ res = netsurf_register(&nsgtk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
return 1;
}
- /* Initialise translated messages */
- ret = nsgtk_messages_init(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Unable to load translated messages (%s)\n",
- messages_get_errorcode(ret));
- NSLOG(netsurf, INFO, "Unable to load translated messages");
- /** \todo decide if message load faliure should be fatal */
- }
-
- /* Locate the correct user cache directory path */
- ret = get_cache_home(&cache_home);
- if (ret == NSERROR_NOT_FOUND) {
- /* no cache directory exists yet so try to create one */
- ret = create_cache_home(&cache_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
+ /* gtk specific initialisation */
+ res = nsgtk_init(&argc, &argv, &cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf gtk failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
}
/* core initialisation */
- ret = netsurf_init(cache_home);
+ res = netsurf_init(cache_home);
free(cache_home);
- if (ret != NSERROR_OK) {
+ if (res != NSERROR_OK) {
fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
+ messages_get_errorcode(res));
+ return 3;
}
/* gtk specific initalisation and main run loop */
- ret = nsgtk_setup(argc, argv, respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
- messages_get_errorcode(ret));
+ res = nsgtk_setup(argc, argv, respaths);
+ if (res != NSERROR_OK) {
nsgtk_finalise();
- return 2;
- }
+ fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
+ messages_get_errorcode(res));
+ return 4;
+ }
nsgtk_main();
nsgtk_finalise();
-
+
return 0;
}
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=3cf92011c27a0ae650e...
commit 3cf92011c27a0ae650eae61d5b7749e0a5c0f381
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
split out gtk misc operations from gui module
diff --git a/frontends/gtk/Makefile b/frontends/gtk/Makefile
index 3bf3ea0..4f3fd5f 100644
--- a/frontends/gtk/Makefile
+++ b/frontends/gtk/Makefile
@@ -166,11 +166,11 @@ endif
# ----------------------------------------------------------------------------
# S_FRONTEND are sources purely for the GTK frontend
-S_FRONTEND := gui.c schedule.c layout_pango.c bitmap.c plotters.c \
- scaffolding.c gdk.c completion.c throbber.c accelerator.c \
- selection.c window.c fetch.c download.c menu.c print.c \
- search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
- viewsource.c preferences.c about.c resources.c corewindow.c \
+S_FRONTEND := gui.c misc.c schedule.c layout_pango.c bitmap.c plotters.c \
+ scaffolding.c gdk.c completion.c throbber.c accelerator.c \
+ selection.c window.c fetch.c download.c menu.c print.c \
+ search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
+ viewsource.c preferences.c about.c resources.c corewindow.c \
local_history.c global_history.c cookies.c hotlist.c page_info.c
# This is the final source build list
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index e5006d9..d4b0c71 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -43,12 +43,10 @@
#include "netsurf/cookie_db.h"
#include "netsurf/browser.h"
#include "netsurf/browser_window.h"
-#include "netsurf/misc.h"
#include "netsurf/netsurf.h"
#include "content/fetch.h"
#include "content/backing_store.h"
#include "desktop/save_complete.h"
-#include "desktop/save_pdf.h"
#include "desktop/searchweb.h"
#include "desktop/hotlist.h"
@@ -70,6 +68,7 @@
#include "gtk/selection.h"
#include "gtk/search.h"
#include "gtk/bitmap.h"
+#include "gtk/misc.h"
#include "gtk/resources.h"
#include "gtk/layout_pango.h"
#include "gtk/accelerator.h"
@@ -327,13 +326,13 @@ static nserror nsgtk_add_named_icons_to_theme(void)
/**
- * Initialize GTK specific parts of the browser.
+ * setup GTK specific parts of the browser.
*
* \param argc The number of arguments on the command line
* \param argv A string vector of command line arguments.
* \respath A string vector of the path elements of resources
*/
-static nserror nsgtk_init(int argc, char** argv, char **respath)
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
{
char buf[PATH_MAX];
char *resource_filename;
@@ -480,136 +479,9 @@ static bool nslog_stream_configure(FILE *fptr)
}
-/**
- * Run the gtk event loop.
- *
- * The same as the standard gtk_main loop except this ensures active
- * FD are added to the gtk poll event set.
- */
-static void nsgtk_main(void)
-{
- fd_set read_fd_set, write_fd_set, exc_fd_set;
- int max_fd;
- GPollFD *fd_list[1000];
- unsigned int fd_count;
-
- while (!nsgtk_complete) {
- max_fd = -1;
- fd_count = 0;
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&exc_fd_set);
-
- while (gtk_events_pending())
- gtk_main_iteration_do(TRUE);
-
- schedule_run();
-
- fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
- for (int i = 0; i <= max_fd; i++) {
- if (FD_ISSET(i, &read_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &write_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_OUT | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &exc_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- }
-
- gtk_main_iteration();
-
- for (unsigned int i = 0; i != fd_count; i++) {
- g_main_context_remove_poll(0, fd_list[i]);
- free(fd_list[i]);
- }
- }
-}
-
-static void gui_quit(void)
-{
- nserror res;
-
- NSLOG(netsurf, INFO, "Quitting GUI");
- /* Ensure all scaffoldings are destroyed before we go into exit */
- nsgtk_download_destroy();
- urldb_save_cookies(nsoption_charp(cookie_jar));
- urldb_save(nsoption_charp(url_file));
- res = nsgtk_cookies_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_local_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising local history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_global_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising global history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_hotlist_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = hotlist_fini();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
- messages_get_errorcode(res));
- }
-
- res = save_complete_finalise();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising save complete: %s",
- messages_get_errorcode(res));
- }
-
- free(nsgtk_config_home);
-
- gtk_fetch_filetype_fin();
-}
-
-static nserror gui_launch_url(struct nsurl *url)
-{
- gboolean ok;
- GError *error = NULL;
-
- ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
- if (ok == TRUE) {
- return NSERROR_OK;
- }
-
- if (error) {
- nsgtk_warning(messages_get("URIOpenError"), error->message);
- g_error_free(error);
- }
- return NSERROR_NO_FETCH_HANDLER;
-}
/* exported function documented in gtk/warn.h */
nserror nsgtk_warning(const char *warning, const char *detail)
@@ -637,127 +509,6 @@ nserror nsgtk_warning(const char *warning, const char *detail)
}
-static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
-{
- char **owner_pass = ((void **)data)[0];
- char **user_pass = ((void **)data)[1];
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- char *op, *op1;
- char *up, *up1;
-
- op = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword"))));
- op1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword1"))));
- up = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword"))));
- up1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword1"))));
-
-
- if (op[0] == '\0') {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "Owner password must be at least 1 character long:");
- free(op);
- free(up);
- } else if (!strcmp(op, up)) {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "User and owner passwords must be different:");
- free(op);
- free(up);
- } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
-
- *owner_pass = op;
- if (up[0] == '\0')
- free(up);
- else
- *user_pass = up;
-
- free(data);
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
- } else {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")), "Passwords not confirmed:");
- free(op);
- free(up);
- }
-
- free(op1);
- free(up1);
-}
-
-static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
-{
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- free(data);
-
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
-}
-
-static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
-{
- GtkButton *ok, *no;
- GtkWindow *wnd;
- void **data;
- GtkBuilder *password_builder;
- nserror res;
-
- res = nsgtk_builder_new_from_resname("password", &password_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Password UI builder init failed");
- return;
- }
-
- gtk_builder_connect_signals(password_builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
- "wndPDFPassword"));
-
- data = malloc(5 * sizeof(void *));
-
- *owner_pass = NULL;
- *user_pass = NULL;
-
- data[0] = owner_pass;
- data[1] = user_pass;
- data[2] = wnd;
- data[3] = password_builder;
- data[4] = path;
-
- ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFSetPassword"));
- no = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFNoPassword"));
-
- g_signal_connect(G_OBJECT(ok), "clicked",
- G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
- g_signal_connect(G_OBJECT(no), "clicked",
- G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
-
- gtk_widget_show(GTK_WIDGET(wnd));
-}
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
@@ -1177,14 +928,6 @@ static nserror nsgtk_option_init(int *pargc, char** argv)
return NSERROR_OK;
}
-static struct gui_misc_table nsgtk_misc_table = {
- .schedule = nsgtk_schedule,
-
- .quit = gui_quit,
- .launch_url = gui_launch_url,
- .pdf_password = nsgtk_pdf_password,
- .present_cookies = nsgtk_cookies_present,
-};
static nserror nsgtk_messages_init(char **respaths)
@@ -1207,6 +950,135 @@ static nserror nsgtk_messages_init(char **respaths)
return ret;
}
+
+/**
+ * Run the gtk event loop.
+ *
+ * The same as the standard gtk_main loop except this ensures active
+ * FD are added to the gtk poll event set.
+ */
+static void nsgtk_main(void)
+{
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+ GPollFD *fd_list[1000];
+ unsigned int fd_count;
+
+ while (!nsgtk_complete) {
+ max_fd = -1;
+ fd_count = 0;
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
+
+ while (gtk_events_pending())
+ gtk_main_iteration_do(TRUE);
+
+ schedule_run();
+
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+ for (int i = 0; i <= max_fd; i++) {
+ if (FD_ISSET(i, &read_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &write_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_OUT | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &exc_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ }
+
+ gtk_main_iteration();
+
+ for (unsigned int i = 0; i != fd_count; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ }
+ }
+}
+
+
+/**
+ * finalise the browser
+ */
+static void nsgtk_finalise(void)
+{
+ nserror res;
+
+ NSLOG(netsurf, INFO, "Quitting GUI");
+
+ /* Ensure all scaffoldings are destroyed before we go into exit */
+ nsgtk_download_destroy();
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+ urldb_save(nsoption_charp(url_file));
+
+ res = nsgtk_cookies_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_local_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising local history viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_global_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising global history viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_hotlist_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = hotlist_fini();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = save_complete_finalise();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising save complete: %s",
+ messages_get_errorcode(res));
+ }
+
+ free(nsgtk_config_home);
+
+ gtk_fetch_filetype_fin();
+
+ /* common finalisation */
+ netsurf_exit();
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ /* finalise logging */
+ nslog_finalise();
+
+}
+
+
/**
* Main entry point from OS.
*/
@@ -1215,7 +1087,7 @@ int main(int argc, char** argv)
char *cache_home = NULL;
nserror ret;
struct netsurf_table nsgtk_table = {
- .misc = &nsgtk_misc_table,
+ .misc = nsgtk_misc_table,
.window = nsgtk_window_table,
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
@@ -1304,22 +1176,17 @@ int main(int argc, char** argv)
}
/* gtk specific initalisation and main run loop */
- ret = nsgtk_init(argc, argv, respaths);
+ ret = nsgtk_setup(argc, argv, respaths);
if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf gtk initialise failed (%s)\n",
+ fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
messages_get_errorcode(ret));
- } else {
- nsgtk_main();
- }
+ nsgtk_finalise();
+ return 2;
+ }
- /* common finalisation */
- netsurf_exit();
-
- /* finalise options */
- nsoption_finalise(nsoptions, nsoptions_default);
-
- /* finalise logging */
- nslog_finalise();
+ nsgtk_main();
+ nsgtk_finalise();
+
return 0;
}
diff --git a/frontends/gtk/misc.c b/frontends/gtk/misc.c
new file mode 100644
index 0000000..bda0dd6
--- /dev/null
+++ b/frontends/gtk/misc.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2021 Vincemt Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf 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 <
http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf miscellaneous operations table
+ */
+
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "netsurf/misc.h"
+#include "desktop/save_pdf.h"
+
+#include "gtk/compat.h"
+#include "gtk/warn.h"
+#include "gtk/schedule.h"
+#include "gtk/resources.h"
+#include "gtk/cookies.h"
+#include "gtk/misc.h"
+
+
+static nserror gui_launch_url(struct nsurl *url)
+{
+ gboolean ok;
+ GError *error = NULL;
+
+ ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
+ if (ok == TRUE) {
+ return NSERROR_OK;
+ }
+
+ if (error) {
+ nsgtk_warning(messages_get("URIOpenError"), error->message);
+ g_error_free(error);
+ }
+ return NSERROR_NO_FETCH_HANDLER;
+}
+
+static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
+{
+ char **owner_pass = ((void **)data)[0];
+ char **user_pass = ((void **)data)[1];
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ char *op, *op1;
+ char *up, *up1;
+
+ op = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword"))));
+ op1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword1"))));
+ up = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword"))));
+ up1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword1"))));
+
+
+ if (op[0] == '\0') {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "Owner password must be at least 1 character long:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, up)) {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "User and owner passwords must be different:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
+
+ *owner_pass = op;
+ if (up[0] == '\0')
+ free(up);
+ else
+ *user_pass = up;
+
+ free(data);
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+ } else {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")), "Passwords not confirmed:");
+ free(op);
+ free(up);
+ }
+
+ free(op1);
+ free(up1);
+}
+
+static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
+{
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ free(data);
+
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+}
+
+static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
+{
+ GtkButton *ok, *no;
+ GtkWindow *wnd;
+ void **data;
+ GtkBuilder *password_builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("password", &password_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Password UI builder init failed");
+ return;
+ }
+
+ gtk_builder_connect_signals(password_builder, NULL);
+
+ wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
+ "wndPDFPassword"));
+
+ data = malloc(5 * sizeof(void *));
+
+ *owner_pass = NULL;
+ *user_pass = NULL;
+
+ data[0] = owner_pass;
+ data[1] = user_pass;
+ data[2] = wnd;
+ data[3] = password_builder;
+ data[4] = path;
+
+ ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFSetPassword"));
+ no = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFNoPassword"));
+
+ g_signal_connect(G_OBJECT(ok), "clicked",
+ G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
+ g_signal_connect(G_OBJECT(no), "clicked",
+ G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
+
+ gtk_widget_show(GTK_WIDGET(wnd));
+}
+
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsgtk_schedule,
+
+ .launch_url = gui_launch_url,
+ .pdf_password = nsgtk_pdf_password,
+ .present_cookies = nsgtk_cookies_present,
+};
+
+struct gui_misc_table *nsgtk_misc_table = &misc_table;
diff --git a/frontends/gtk/misc.h b/frontends/gtk/misc.h
new file mode 100644
index 0000000..3a02c22
--- /dev/null
+++ b/frontends/gtk/misc.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Vincemt Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf 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 <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_GTK_MISC_H
+#define NETSURF_GTK_MISC_H 1
+
+extern struct gui_misc_table *nsgtk_misc_table;
+
+#endif
diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index a85efce..f5de514 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -143,14 +143,14 @@ struct gui_bitmap_table {
int (*get_height)(void *bitmap);
/**
- * The the *bytes* per pixel.
+ * Get the *bytes* per pixel.
*
* \param bitmap The bitmap
*/
size_t (*get_bpp)(void *bitmap);
/**
- * Savde a bitmap to disc.
+ * Save a bitmap to disc.
*
* \param bitmap The bitmap to save
* \param path The path to save the bitmap to.
-----------------------------------------------------------------------
Summary of changes:
frontends/gtk/Makefile | 10 +-
frontends/gtk/gui.c | 1793 +++++++++++++---------------
frontends/gtk/misc.c | 190 +++
frontends/{atari/filetype.h => gtk/misc.h} | 8 +-
include/netsurf/bitmap.h | 4 +-
5 files changed, 1046 insertions(+), 959 deletions(-)
create mode 100644 frontends/gtk/misc.c
copy frontends/{atari/filetype.h => gtk/misc.h} (80%)
diff --git a/frontends/gtk/Makefile b/frontends/gtk/Makefile
index 3bf3ea0..4f3fd5f 100644
--- a/frontends/gtk/Makefile
+++ b/frontends/gtk/Makefile
@@ -166,11 +166,11 @@ endif
# ----------------------------------------------------------------------------
# S_FRONTEND are sources purely for the GTK frontend
-S_FRONTEND := gui.c schedule.c layout_pango.c bitmap.c plotters.c \
- scaffolding.c gdk.c completion.c throbber.c accelerator.c \
- selection.c window.c fetch.c download.c menu.c print.c \
- search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
- viewsource.c preferences.c about.c resources.c corewindow.c \
+S_FRONTEND := gui.c misc.c schedule.c layout_pango.c bitmap.c plotters.c \
+ scaffolding.c gdk.c completion.c throbber.c accelerator.c \
+ selection.c window.c fetch.c download.c menu.c print.c \
+ search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
+ viewsource.c preferences.c about.c resources.c corewindow.c \
local_history.c global_history.c cookies.c hotlist.c page_info.c
# This is the final source build list
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index e5006d9..a826b05 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -43,12 +43,10 @@
#include "netsurf/cookie_db.h"
#include "netsurf/browser.h"
#include "netsurf/browser_window.h"
-#include "netsurf/misc.h"
#include "netsurf/netsurf.h"
#include "content/fetch.h"
#include "content/backing_store.h"
#include "desktop/save_complete.h"
-#include "desktop/save_pdf.h"
#include "desktop/searchweb.h"
#include "desktop/hotlist.h"
@@ -70,34 +68,183 @@
#include "gtk/selection.h"
#include "gtk/search.h"
#include "gtk/bitmap.h"
+#include "gtk/misc.h"
#include "gtk/resources.h"
#include "gtk/layout_pango.h"
#include "gtk/accelerator.h"
bool nsgtk_complete = false;
-char *nsgtk_config_home; /* exported global defined in gtk/gui.h */
+/* exported global defined in gtk/gui.h */
+char *nsgtk_config_home;
-GdkPixbuf *favicon_pixbuf; /** favicon default pixbuf */
-GdkPixbuf *win_default_icon_pixbuf; /** default window icon pixbuf */
+/** favicon default pixbuf */
+GdkPixbuf *favicon_pixbuf;
+
+/** default window icon pixbuf */
+GdkPixbuf *win_default_icon_pixbuf;
GtkBuilder *warning_builder;
-char **respaths; /** resource search path vector */
+/** resource search path vector */
+char **respaths;
-/**
- * Cause an abnormal program termination.
- *
- * \note This never returns and is intended to terminate without any cleanup.
- *
- * \param error The message to display to the user.
- */
-static void die(const char * const error)
+
+/* exported function documented in gtk/warn.h */
+nserror nsgtk_warning(const char *warning, const char *detail)
+{
+ char buf[300]; /* 300 is the size the RISC OS GUI uses */
+ static GtkWindow *nsgtk_warning_window;
+ GtkLabel *WarningLabel;
+
+ NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
+ fflush(stdout);
+
+ nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder,
"wndWarning"));
+ WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
+ "labelWarning"));
+
+ snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
+ detail ? detail : "");
+ buf[sizeof(buf) - 1] = 0;
+
+ gtk_label_set_text(WarningLabel, buf);
+
+ gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/gui.h */
+uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
{
- fprintf(stderr, "%s", error);
- exit(EXIT_FAILURE);
+ /* this function will need to become much more complex to support
+ * everything that the RISC OS version does. But this will do for
+ * now. I hope.
+ */
+ switch (key->keyval) {
+
+ case GDK_KEY(Tab):
+ return NS_KEY_TAB;
+
+ case GDK_KEY(BackSpace):
+ if (key->state & GDK_SHIFT_MASK)
+ return NS_KEY_DELETE_LINE_START;
+ else
+ return NS_KEY_DELETE_LEFT;
+
+ case GDK_KEY(Delete):
+ if (key->state & GDK_SHIFT_MASK)
+ return NS_KEY_DELETE_LINE_END;
+ else
+ return NS_KEY_DELETE_RIGHT;
+
+ case GDK_KEY(Linefeed):
+ return 13;
+
+ case GDK_KEY(Return):
+ return 10;
+
+ case GDK_KEY(Left):
+ case GDK_KEY(KP_Left):
+ return NS_KEY_LEFT;
+
+ case GDK_KEY(Right):
+ case GDK_KEY(KP_Right):
+ return NS_KEY_RIGHT;
+
+ case GDK_KEY(Up):
+ case GDK_KEY(KP_Up):
+ return NS_KEY_UP;
+
+ case GDK_KEY(Down):
+ case GDK_KEY(KP_Down):
+ return NS_KEY_DOWN;
+
+ case GDK_KEY(Home):
+ case GDK_KEY(KP_Home):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_START;
+ else
+ return NS_KEY_TEXT_START;
+
+ case GDK_KEY(End):
+ case GDK_KEY(KP_End):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_END;
+ else
+ return NS_KEY_TEXT_END;
+
+ case GDK_KEY(Page_Up):
+ case GDK_KEY(KP_Page_Up):
+ return NS_KEY_PAGE_UP;
+
+ case GDK_KEY(Page_Down):
+ case GDK_KEY(KP_Page_Down):
+ return NS_KEY_PAGE_DOWN;
+
+ case 'a':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_SELECT_ALL;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'u':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_LINE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'c':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_COPY_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'v':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_PASTE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'x':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_CUT_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'Z':
+ case 'y':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_REDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'z':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_UNDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case GDK_KEY(Escape):
+ return NS_KEY_ESCAPE;
+
+ /* Modifiers - do nothing for now */
+ case GDK_KEY(Shift_L):
+ case GDK_KEY(Shift_R):
+ case GDK_KEY(Control_L):
+ case GDK_KEY(Control_R):
+ case GDK_KEY(Caps_Lock):
+ case GDK_KEY(Shift_Lock):
+ case GDK_KEY(Meta_L):
+ case GDK_KEY(Meta_R):
+ case GDK_KEY(Alt_L):
+ case GDK_KEY(Alt_R):
+ case GDK_KEY(Super_L):
+ case GDK_KEY(Super_R):
+ case GDK_KEY(Hyper_L):
+ case GDK_KEY(Hyper_R):
+ return 0;
+
+ }
+ return gdk_keyval_to_unicode(key->keyval);
}
+
/**
* Create an array of valid paths to search for resources.
*
@@ -156,1066 +303,872 @@ nsgtk_init_resource_path(const char *config_home)
/**
- * Set option defaults for gtk frontend.
- *
- * \param defaults The option table to update.
- * \return error status.
+ * create directory name and check it is acessible and a directory.
*/
-static nserror set_defaults(struct nsoption_s *defaults)
+static nserror
+check_dirname(const char *path, const char *leaf, char **dirname_out)
{
- char *fname;
- GtkSettings *settings;
- GtkIconSize tooliconsize;
- GtkToolbarStyle toolbarstyle;
-
- /* cookie file default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_file, fname);
- }
-
- /* cookie jar default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_jar, fname);
- }
+ nserror ret;
+ char *dirname = NULL;
+ struct stat dirname_stat;
- /* url database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
- if (fname != NULL) {
- nsoption_setnull_charp(url_file, fname);
+ ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
+ if (ret != NSERROR_OK) {
+ return ret;
}
- /* bookmark database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
- if (fname != NULL) {
- nsoption_setnull_charp(hotlist_path, fname);
+ /* ensure access is possible and the entry is actualy
+ * a directory.
+ */
+ if (stat(dirname, &dirname_stat) == 0) {
+ if (S_ISDIR(dirname_stat.st_mode)) {
+ if (access(dirname, R_OK | W_OK) == 0) {
+ *dirname_out = dirname;
+ return NSERROR_OK;
+ } else {
+ ret = NSERROR_PERMISSION;
+ }
+ } else {
+ ret = NSERROR_NOT_DIRECTORY;
+ }
+ } else {
+ ret = NSERROR_NOT_FOUND;
}
- /* download directory default */
- fname = getenv("HOME");
- if (fname != NULL) {
- nsoption_setnull_charp(downloads_directory, strdup(fname));
- }
+ free(dirname);
- if ((nsoption_charp(cookie_file) == NULL) ||
- (nsoption_charp(cookie_jar) == NULL) ||
- (nsoption_charp(url_file) == NULL) ||
- (nsoption_charp(hotlist_path) == NULL) ||
- (nsoption_charp(downloads_directory) == NULL)) {
- NSLOG(netsurf, INFO,
- "Failed initialising default resource paths");
- return NSERROR_BAD_PARAMETER;
- }
+ return ret;
+}
- /* set default font names */
- nsoption_set_charp(font_sans, strdup("Sans"));
- nsoption_set_charp(font_serif, strdup("Serif"));
- nsoption_set_charp(font_mono, strdup("Monospace"));
- nsoption_set_charp(font_cursive, strdup("Serif"));
- nsoption_set_charp(font_fantasy, strdup("Serif"));
- /* Default toolbar button type to system defaults */
+/**
+ * Get the path to the config directory.
+ *
+ * @param config_home_out Path to configuration directory.
+ * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
+ */
+static nserror get_config_home(char **config_home_out)
+{
+ nserror ret;
+ char *home_dir;
+ char *xdg_config_dir;
+ char *config_home;
- settings = gtk_settings_get_default();
- g_object_get(settings,
- "gtk-toolbar-icon-size", &tooliconsize,
- "gtk-toolbar-style", &toolbarstyle, NULL);
+ home_dir = getenv("HOME");
- switch (toolbarstyle) {
- case GTK_TOOLBAR_ICONS:
- if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
- nsoption_set_int(button_type, 1);
- } else {
- nsoption_set_int(button_type, 2);
+ /* The old $HOME/.netsurf/ directory should be used if it
+ * exists and is accessible.
+ */
+ if (home_dir != NULL) {
+ ret = check_dirname(home_dir, ".netsurf", &config_home);
+ if (ret == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+ *config_home_out = config_home;
+ return ret;
}
- break;
+ }
- case GTK_TOOLBAR_TEXT:
- nsoption_set_int(button_type, 4);
- break;
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
- case GTK_TOOLBAR_BOTH:
- case GTK_TOOLBAR_BOTH_HORIZ:
- /* no labels in default configuration */
- default:
- /* No system default, so use large icons */
- nsoption_set_int(button_type, 2);
- break;
- }
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ /* If $XDG_CONFIG_HOME is either not set or empty, a
+ * default equal to $HOME/.config should be used.
+ */
- /* set default items in toolbar */
- nsoption_set_charp(toolbar_items,
- strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
+ /** @todo the meaning of empty is never defined so I
+ * am assuming it is a zero length string but is it
+ * supposed to mean "whitespace" and if so what counts
+ * as whitespace? (are tabs etc. counted or should
+ * isspace() be used)
+ */
- /* set default for menu and tool bar visibility */
- nsoption_set_charp(bar_show, strdup("tool"));
+ /* the HOME envvar is required */
+ if (home_dir == NULL) {
+ return NSERROR_NOT_DIRECTORY;
+ }
- return NSERROR_OK;
-}
+ ret = check_dirname(home_dir, ".config/netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
-#if GTK_CHECK_VERSION(3,14,0)
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
-/**
- * adds named icons into gtk theme
- */
-static nserror nsgtk_add_named_icons_to_theme(void)
-{
- gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
- "/org/netsurf/icons");
+ *config_home_out = config_home;
return NSERROR_OK;
}
-#else
-static nserror
-add_builtin_icon(const char *prefix, const char *name, int x, int y)
+static nserror create_config_home(char **config_home_out)
{
- GdkPixbuf *pixbuf;
- nserror res;
- char *resname;
- int resnamelen;
+ char *config_home = NULL;
+ char *home_dir;
+ char *xdg_config_dir;
+ nserror ret;
- /* resource name string length allowing for / .png and termination */
- resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
- resname = malloc(resnamelen);
- if (resname == NULL) {
- return NSERROR_NOMEM;
+ NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
+
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ home_dir = getenv("HOME");
+
+ if ((home_dir == NULL) || (*home_dir == 0)) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = netsurf_mkpath(&config_home, NULL, 4, home_dir,
".config","netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf",
"/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
}
- snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
- res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
- NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
- free(resname);
- if (res != NSERROR_OK) {
- pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
+ /* ensure all elements of path exist (the trailing / is required) */
+ ret = netsurf_mkdir_all(config_home);
+ if (ret != NSERROR_OK) {
+ free(config_home);
+ return ret;
}
- gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
+
+ /* strip the trailing separator */
+ config_home[strlen(config_home) - 1] = 0;
+
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+
+ *config_home_out = config_home;
return NSERROR_OK;
}
+
/**
- * adds named icons into gtk theme
+ * Ensures output logging stream is correctly configured
*/
-static nserror nsgtk_add_named_icons_to_theme(void)
+static bool nslog_stream_configure(FILE *fptr)
{
- /* these must also be in gtk/resources.c pixbuf_resource *and*
- * gtk/res/netsurf.gresource.xml
- */
- add_builtin_icon("", "local-history", 8, 32);
- add_builtin_icon("", "show-cookie", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
- add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
- add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
- add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
- return NSERROR_OK;
+ return true;
}
-#endif
-
/**
- * Initialize GTK specific parts of the browser.
+ * Set option defaults for gtk frontend.
*
- * \param argc The number of arguments on the command line
- * \param argv A string vector of command line arguments.
- * \respath A string vector of the path elements of resources
+ * \param defaults The option table to update.
+ * \return error status.
*/
-static nserror nsgtk_init(int argc, char** argv, char **respath)
+static nserror set_defaults(struct nsoption_s *defaults)
{
- char buf[PATH_MAX];
- char *resource_filename;
- char *addr = NULL;
- nsurl *url;
- nserror res;
+ char *fname;
+ GtkSettings *settings;
+ GtkIconSize tooliconsize;
+ GtkToolbarStyle toolbarstyle;
- /* Initialise gtk accelerator table */
- res = nsgtk_accelerator_init(respaths);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to load gtk accelerator configuration");
- /* not fatal if this does not load */
+ /* cookie file default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_file, fname);
}
- /* initialise warning dialog */
- res = nsgtk_builder_new_from_resname("warning", &warning_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
- return res;
+ /* cookie jar default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_jar, fname);
}
- gtk_builder_connect_signals(warning_builder, NULL);
-
- /* set default icon if its available */
- res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
- &win_default_icon_pixbuf);
- if (res == NSERROR_OK) {
- NSLOG(netsurf, INFO, "Seting default window icon");
- gtk_window_set_default_icon(win_default_icon_pixbuf);
+ /* url database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
+ if (fname != NULL) {
+ nsoption_setnull_charp(url_file, fname);
}
- /* Search engine sources */
- resource_filename = filepath_find(respath, "SearchEngines");
- search_web_init(resource_filename);
- if (resource_filename != NULL) {
- NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
- resource_filename);
- free(resource_filename);
+ /* bookmark database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
+ if (fname != NULL) {
+ nsoption_setnull_charp(hotlist_path, fname);
}
- search_web_select_provider(nsoption_int(search_provider));
- /* Default favicon */
- res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
- if (res != NSERROR_OK) {
- favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 16, 16);
+ /* download directory default */
+ fname = getenv("HOME");
+ if (fname != NULL) {
+ nsoption_setnull_charp(downloads_directory, strdup(fname));
}
- /* add named icons to gtk theme */
- res = nsgtk_add_named_icons_to_theme();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
- return res;
+ if ((nsoption_charp(cookie_file) == NULL) ||
+ (nsoption_charp(cookie_jar) == NULL) ||
+ (nsoption_charp(url_file) == NULL) ||
+ (nsoption_charp(hotlist_path) == NULL) ||
+ (nsoption_charp(downloads_directory) == NULL)) {
+ NSLOG(netsurf, INFO,
+ "Failed initialising default resource paths");
+ return NSERROR_BAD_PARAMETER;
}
- /* initialise throbber */
- res = nsgtk_throbber_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise throbber.");
- return res;
- }
+ /* set default font names */
+ nsoption_set_charp(font_sans, strdup("Sans"));
+ nsoption_set_charp(font_serif, strdup("Serif"));
+ nsoption_set_charp(font_mono, strdup("Monospace"));
+ nsoption_set_charp(font_cursive, strdup("Serif"));
+ nsoption_set_charp(font_fantasy, strdup("Serif"));
- /* Initialise completions - cannot fail */
- nsgtk_completion_init();
+ /* Default toolbar button type to system defaults */
- /* The tree view system needs to know the screen's DPI, so we
- * find that out here, rather than when we create a first browser
- * window.
- */
- browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
- NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
-
- filepath_sfinddef(respath, buf, "mime.types", "/etc/");
- gtk_fetch_filetype_init(buf);
+ settings = gtk_settings_get_default();
+ g_object_get(settings,
+ "gtk-toolbar-icon-size", &tooliconsize,
+ "gtk-toolbar-style", &toolbarstyle, NULL);
- save_complete_init();
+ switch (toolbarstyle) {
+ case GTK_TOOLBAR_ICONS:
+ if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
+ nsoption_set_int(button_type, 1);
+ } else {
+ nsoption_set_int(button_type, 2);
+ }
+ break;
- urldb_load(nsoption_charp(url_file));
- urldb_load_cookies(nsoption_charp(cookie_file));
- hotlist_init(nsoption_charp(hotlist_path),
- nsoption_charp(hotlist_path));
+ case GTK_TOOLBAR_TEXT:
+ nsoption_set_int(button_type, 4);
+ break;
- /* Initialise top level UI elements */
- res = nsgtk_download_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise download window.");
- return res;
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ /* no labels in default configuration */
+ default:
+ /* No system default, so use large icons */
+ nsoption_set_int(button_type, 2);
+ break;
}
- /* If there is a url specified on the command line use it */
- if (argc > 1) {
- struct stat fs;
- if (stat(argv[1], &fs) == 0) {
- size_t addrlen;
- char *rp = realpath(argv[1], NULL);
- assert(rp != NULL);
+ /* set default items in toolbar */
+ nsoption_set_charp(toolbar_items,
+ strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
- /* calculate file url length including terminator */
- addrlen = SLEN("file://") + strlen(rp) + 1;
- addr = malloc(addrlen);
- assert(addr != NULL);
- snprintf(addr, addrlen, "file://%s", rp);
- free(rp);
- } else {
- addr = strdup(argv[1]);
- }
- }
- if (addr != NULL) {
- /* managed to set up based on local launch */
- } else if (nsoption_charp(homepage_url) != NULL) {
- addr = strdup(nsoption_charp(homepage_url));
- } else {
- addr = strdup(NETSURF_HOMEPAGE);
+ /* set default for menu and tool bar visibility */
+ nsoption_set_charp(bar_show, strdup("tool"));
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Initialise user options
+ *
+ * Initialise the browser configuration options. These are set by:
+ * - set generic defaults suitable for the gtk frontend
+ * - user choices loaded from Choices file
+ * - command line parameters
+ */
+static nserror nsgtk_option_init(int *pargc, char** argv)
+{
+ nserror ret;
+ char *choices = NULL;
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ return ret;
}
- /* create an initial browser window */
- res = nsurl_create(addr, &url);
- if (res == NSERROR_OK) {
- res = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
+ /* Attempt to load the user choices */
+ ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (ret == NSERROR_OK) {
+ nsoption_read(choices, nsoptions);
+ free(choices);
}
- free(addr);
+ /* overide loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
- return res;
-}
+ /* ensure all options fall within sensible bounds */
+
+ /* Attempt to handle nonsense status bar widths. These may exist
+ * in people's Choices as the GTK front end used to abuse the
+ * status bar width option by using it for an absolute value in px.
+ * The GTK front end now correctly uses it as a proportion of window
+ * width. Here we assume that a value of less than 15% is wrong
+ * and set to the default two thirds. */
+ if (nsoption_int(toolbar_status_size) < 1500) {
+ nsoption_set_int(toolbar_status_size, 6667);
+ }
+ return NSERROR_OK;
+}
/**
- * Ensures output logging stream is correctly configured
+ * initialise message translation
*/
-static bool nslog_stream_configure(FILE *fptr)
+static nserror nsgtk_messages_init(char **respaths)
{
- /* set log stream to be non-buffering */
- setbuf(fptr, NULL);
+ const char *messages;
+ nserror ret;
+ const uint8_t *data;
+ size_t data_size;
- return true;
+ ret = nsgtk_data_from_resname("Messages", &data, &data_size);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_inline(data, data_size);
+ } else {
+ /* Obtain path to messages */
+ ret = nsgtk_path_from_resname("Messages", &messages);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_file(messages);
+ }
+ }
+ return ret;
}
/**
- * Run the gtk event loop.
+ * Get the path to the cache directory.
*
- * The same as the standard gtk_main loop except this ensures active
- * FD are added to the gtk poll event set.
+ * @param cache_home_out Path to cache directory.
+ * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
*/
-static void nsgtk_main(void)
+static nserror get_cache_home(char **cache_home_out)
{
- fd_set read_fd_set, write_fd_set, exc_fd_set;
- int max_fd;
- GPollFD *fd_list[1000];
- unsigned int fd_count;
+ nserror ret;
+ char *xdg_cache_dir;
+ char *cache_home;
+ char *home_dir;
- while (!nsgtk_complete) {
- max_fd = -1;
- fd_count = 0;
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&exc_fd_set);
+ /* $XDG_CACHE_HOME defines the base directory relative to
+ * which user specific non-essential data files should be
+ * stored.
+ */
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
- while (gtk_events_pending())
- gtk_main_iteration_do(TRUE);
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
+ /* If $XDG_CACHE_HOME is either not set or empty, a
+ * default equal to $HOME/.cache should be used.
+ */
- schedule_run();
+ home_dir = getenv("HOME");
- fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
- for (int i = 0; i <= max_fd; i++) {
- if (FD_ISSET(i, &read_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &write_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_OUT | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &exc_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
+ /* the HOME envvar is required */
+ if (home_dir == NULL) {
+ return NSERROR_NOT_DIRECTORY;
}
- gtk_main_iteration();
-
- for (unsigned int i = 0; i != fd_count; i++) {
- g_main_context_remove_poll(0, fd_list[i]);
- free(fd_list[i]);
+ ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
+ if (ret != NSERROR_OK) {
+ return ret;
}
}
+
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+
+ *cache_home_out = cache_home;
+ return NSERROR_OK;
}
-static void gui_quit(void)
+/**
+ * create a cache directory
+ */
+static nserror create_cache_home(char **cache_home_out)
{
- nserror res;
+ char *cache_home = NULL;
+ char *home_dir;
+ char *xdg_cache_dir;
+ nserror ret;
- NSLOG(netsurf, INFO, "Quitting GUI");
+ NSLOG(netsurf, INFO, "Attempting to create cache directory");
- /* Ensure all scaffoldings are destroyed before we go into exit */
- nsgtk_download_destroy();
- urldb_save_cookies(nsoption_charp(cookie_jar));
- urldb_save(nsoption_charp(url_file));
+ /* $XDG_CACHE_HOME defines the base directory
+ * relative to which user specific cache files
+ * should be stored.
+ */
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
- res = nsgtk_cookies_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
- messages_get_errorcode(res));
- }
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
+ home_dir = getenv("HOME");
- res = nsgtk_local_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising local history viewer: %s",
- messages_get_errorcode(res));
- }
+ if ((home_dir == NULL) || (*home_dir == 0)) {
+ return NSERROR_NOT_DIRECTORY;
+ }
- res = nsgtk_global_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising global history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_hotlist_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
- messages_get_errorcode(res));
+ ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache",
"netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf",
"/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
}
- res = hotlist_fini();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
- messages_get_errorcode(res));
+ /* ensure all elements of path exist (the trailing / is required) */
+ ret = netsurf_mkdir_all(cache_home);
+ if (ret != NSERROR_OK) {
+ free(cache_home);
+ return ret;
}
- res = save_complete_finalise();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising save complete: %s",
- messages_get_errorcode(res));
- }
+ /* strip the trailing separator */
+ cache_home[strlen(cache_home) - 1] = 0;
- free(nsgtk_config_home);
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
- gtk_fetch_filetype_fin();
+ *cache_home_out = cache_home;
+
+ return NSERROR_OK;
}
-static nserror gui_launch_url(struct nsurl *url)
+
+/**
+ * GTK specific initialisation
+ */
+static nserror nsgtk_init(int *pargc, char ***pargv, char **cache_home)
{
- gboolean ok;
- GError *error = NULL;
+ nserror ret;
- ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
- if (ok == TRUE) {
- return NSERROR_OK;
+ /* Locate the correct user configuration directory path */
+ ret = get_config_home(&nsgtk_config_home);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no config directory exists yet so try to create one */
+ ret = create_config_home(&nsgtk_config_home);
}
-
- if (error) {
- nsgtk_warning(messages_get("URIOpenError"), error->message);
- g_error_free(error);
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to locate a configuration directory.");
+ nsgtk_config_home = NULL;
}
- return NSERROR_NO_FETCH_HANDLER;
-}
-/* exported function documented in gtk/warn.h */
-nserror nsgtk_warning(const char *warning, const char *detail)
-{
- char buf[300]; /* 300 is the size the RISC OS GUI uses */
- static GtkWindow *nsgtk_warning_window;
- GtkLabel *WarningLabel;
+ /* Initialise gtk */
+ gtk_init(pargc, pargv);
- NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
- fflush(stdout);
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, pargc, *pargv);
- nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder,
"wndWarning"));
- WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
- "labelWarning"));
+ /* build the common resource path list */
+ respaths = nsgtk_init_resource_path(nsgtk_config_home);
+ if (respaths == NULL) {
+ fprintf(stderr, "Unable to locate resources\n");
+ return 1;
+ }
- snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
- detail ? detail : "");
- buf[sizeof(buf) - 1] = 0;
+ /* initialise the gtk resource handling */
+ ret = nsgtk_init_resources(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "GTK resources failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
- gtk_label_set_text(WarningLabel, buf);
+ /* Initialise user options */
+ ret = nsgtk_option_init(pargc, *pargv);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Options failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
+
+ /* Initialise translated messages */
+ ret = nsgtk_messages_init(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Unable to load translated messages (%s)\n",
+ messages_get_errorcode(ret));
+ NSLOG(netsurf, INFO, "Unable to load translated messages");
+ /** \todo decide if message load faliure should be fatal */
+ }
+
+ /* Locate the correct user cache directory path */
+ ret = get_cache_home(cache_home);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no cache directory exists yet so try to create one */
+ ret = create_cache_home(cache_home);
+ }
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
+ }
- gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
return NSERROR_OK;
}
-static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
+#if GTK_CHECK_VERSION(3,14,0)
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
{
- char **owner_pass = ((void **)data)[0];
- char **user_pass = ((void **)data)[1];
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- char *op, *op1;
- char *up, *up1;
-
- op = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword"))));
- op1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword1"))));
- up = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword"))));
- up1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword1"))));
-
-
- if (op[0] == '\0') {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "Owner password must be at least 1 character long:");
- free(op);
- free(up);
- } else if (!strcmp(op, up)) {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "User and owner passwords must be different:");
- free(op);
- free(up);
- } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
-
- *owner_pass = op;
- if (up[0] == '\0')
- free(up);
- else
- *user_pass = up;
+ gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
+ "/org/netsurf/icons");
+ return NSERROR_OK;
+}
- free(data);
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
+#else
- save_pdf(path);
+static nserror
+add_builtin_icon(const char *prefix, const char *name, int x, int y)
+{
+ GdkPixbuf *pixbuf;
+ nserror res;
+ char *resname;
+ int resnamelen;
- free(path);
- } else {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")), "Passwords not confirmed:");
- free(op);
- free(up);
+ /* resource name string length allowing for / .png and termination */
+ resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
+ resname = malloc(resnamelen);
+ if (resname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
+
+ res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
+ NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
+ free(resname);
+ if (res != NSERROR_OK) {
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
}
+ gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
- free(op1);
- free(up1);
+ return NSERROR_OK;
}
-static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
-{
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
- free(data);
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ /* these must also be in gtk/resources.c pixbuf_resource *and*
+ * gtk/res/netsurf.gresource.xml
+ */
+ add_builtin_icon("", "local-history", 8, 32);
+ add_builtin_icon("", "show-cookie", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
+ add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
+ return NSERROR_OK;
+}
- save_pdf(path);
+#endif
- free(path);
-}
-static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
+/**
+ * setup GTK specific parts of the browser.
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ * \respath A string vector of the path elements of resources
+ */
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
{
- GtkButton *ok, *no;
- GtkWindow *wnd;
- void **data;
- GtkBuilder *password_builder;
+ char buf[PATH_MAX];
+ char *resource_filename;
+ char *addr = NULL;
+ nsurl *url;
nserror res;
- res = nsgtk_builder_new_from_resname("password", &password_builder);
+ /* Initialise gtk accelerator table */
+ res = nsgtk_accelerator_init(respaths);
if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Password UI builder init failed");
- return;
+ NSLOG(netsurf, INFO,
+ "Unable to load gtk accelerator configuration");
+ /* not fatal if this does not load */
}
- gtk_builder_connect_signals(password_builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
- "wndPDFPassword"));
+ /* initialise warning dialog */
+ res = nsgtk_builder_new_from_resname("warning", &warning_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
+ return res;
+ }
- data = malloc(5 * sizeof(void *));
+ gtk_builder_connect_signals(warning_builder, NULL);
- *owner_pass = NULL;
- *user_pass = NULL;
+ /* set default icon if its available */
+ res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
+ &win_default_icon_pixbuf);
+ if (res == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Seting default window icon");
+ gtk_window_set_default_icon(win_default_icon_pixbuf);
+ }
- data[0] = owner_pass;
- data[1] = user_pass;
- data[2] = wnd;
- data[3] = password_builder;
- data[4] = path;
+ /* Search engine sources */
+ resource_filename = filepath_find(respath, "SearchEngines");
+ search_web_init(resource_filename);
+ if (resource_filename != NULL) {
+ NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
+ resource_filename);
+ free(resource_filename);
+ }
+ search_web_select_provider(nsoption_int(search_provider));
- ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFSetPassword"));
- no = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFNoPassword"));
+ /* Default favicon */
+ res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
+ if (res != NSERROR_OK) {
+ favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+ false, 8, 16, 16);
+ }
- g_signal_connect(G_OBJECT(ok), "clicked",
- G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
- g_signal_connect(G_OBJECT(no), "clicked",
- G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
+ /* add named icons to gtk theme */
+ res = nsgtk_add_named_icons_to_theme();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
+ return res;
+ }
- gtk_widget_show(GTK_WIDGET(wnd));
-}
+ /* initialise throbber */
+ res = nsgtk_throbber_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise throbber.");
+ return res;
+ }
+ /* Initialise completions - cannot fail */
+ nsgtk_completion_init();
-uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
-{
- /* this function will need to become much more complex to support
- * everything that the RISC OS version does. But this will do for
- * now. I hope.
+ /* The tree view system needs to know the screen's DPI, so we
+ * find that out here, rather than when we create a first browser
+ * window.
*/
- switch (key->keyval) {
-
- case GDK_KEY(Tab):
- return NS_KEY_TAB;
+ browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
+ NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
- case GDK_KEY(BackSpace):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_START;
- else
- return NS_KEY_DELETE_LEFT;
+ filepath_sfinddef(respath, buf, "mime.types", "/etc/");
+ gtk_fetch_filetype_init(buf);
- case GDK_KEY(Delete):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_END;
- else
- return NS_KEY_DELETE_RIGHT;
+ save_complete_init();
- case GDK_KEY(Linefeed):
- return 13;
-
- case GDK_KEY(Return):
- return 10;
-
- case GDK_KEY(Left):
- case GDK_KEY(KP_Left):
- return NS_KEY_LEFT;
-
- case GDK_KEY(Right):
- case GDK_KEY(KP_Right):
- return NS_KEY_RIGHT;
-
- case GDK_KEY(Up):
- case GDK_KEY(KP_Up):
- return NS_KEY_UP;
-
- case GDK_KEY(Down):
- case GDK_KEY(KP_Down):
- return NS_KEY_DOWN;
-
- case GDK_KEY(Home):
- case GDK_KEY(KP_Home):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_START;
- else
- return NS_KEY_TEXT_START;
-
- case GDK_KEY(End):
- case GDK_KEY(KP_End):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_END;
- else
- return NS_KEY_TEXT_END;
-
- case GDK_KEY(Page_Up):
- case GDK_KEY(KP_Page_Up):
- return NS_KEY_PAGE_UP;
-
- case GDK_KEY(Page_Down):
- case GDK_KEY(KP_Page_Down):
- return NS_KEY_PAGE_DOWN;
-
- case 'a':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_SELECT_ALL;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'u':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_DELETE_LINE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'c':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_COPY_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'v':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_PASTE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'x':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_CUT_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'Z':
- case 'y':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_REDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'z':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_UNDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case GDK_KEY(Escape):
- return NS_KEY_ESCAPE;
-
- /* Modifiers - do nothing for now */
- case GDK_KEY(Shift_L):
- case GDK_KEY(Shift_R):
- case GDK_KEY(Control_L):
- case GDK_KEY(Control_R):
- case GDK_KEY(Caps_Lock):
- case GDK_KEY(Shift_Lock):
- case GDK_KEY(Meta_L):
- case GDK_KEY(Meta_R):
- case GDK_KEY(Alt_L):
- case GDK_KEY(Alt_R):
- case GDK_KEY(Super_L):
- case GDK_KEY(Super_R):
- case GDK_KEY(Hyper_L):
- case GDK_KEY(Hyper_R):
- return 0;
+ urldb_load(nsoption_charp(url_file));
+ urldb_load_cookies(nsoption_charp(cookie_file));
+ hotlist_init(nsoption_charp(hotlist_path),
+ nsoption_charp(hotlist_path));
+ /* Initialise top level UI elements */
+ res = nsgtk_download_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise download window.");
+ return res;
}
- return gdk_keyval_to_unicode(key->keyval);
-}
-
-
-/**
- * create directory name and check it is acessible and a directory.
- */
-static nserror
-check_dirname(const char *path, const char *leaf, char **dirname_out)
-{
- nserror ret;
- char *dirname = NULL;
- struct stat dirname_stat;
- ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
- if (ret != NSERROR_OK) {
- return ret;
- }
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
- /* ensure access is possible and the entry is actualy
- * a directory.
- */
- if (stat(dirname, &dirname_stat) == 0) {
- if (S_ISDIR(dirname_stat.st_mode)) {
- if (access(dirname, R_OK | W_OK) == 0) {
- *dirname_out = dirname;
- return NSERROR_OK;
- } else {
- ret = NSERROR_PERMISSION;
- }
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
} else {
- ret = NSERROR_NOT_DIRECTORY;
- }
- } else {
- ret = NSERROR_NOT_FOUND;
- }
-
- free(dirname);
-
- return ret;
-}
-
-/**
- * Get the path to the config directory.
- *
- * @param config_home_out Path to configuration directory.
- * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
- */
-static nserror get_config_home(char **config_home_out)
-{
- nserror ret;
- char *home_dir;
- char *xdg_config_dir;
- char *config_home;
-
- home_dir = getenv("HOME");
-
- /* The old $HOME/.netsurf/ directory should be used if it
- * exists and is accessible.
- */
- if (home_dir != NULL) {
- ret = check_dirname(home_dir, ".netsurf", &config_home);
- if (ret == NSERROR_OK) {
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
- *config_home_out = config_home;
- return ret;
- }
- }
-
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
- * should be stored.
- */
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
-
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
- /* If $XDG_CONFIG_HOME is either not set or empty, a
- * default equal to $HOME/.config should be used.
- */
-
- /** @todo the meaning of empty is never defined so I
- * am assuming it is a zero length string but is it
- * supposed to mean "whitespace" and if so what counts
- * as whitespace? (are tabs etc. counted or should
- * isspace() be used)
- */
-
- /* the HOME envvar is required */
- if (home_dir == NULL) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = check_dirname(home_dir, ".config/netsurf", &config_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
- if (ret != NSERROR_OK) {
- return ret;
+ addr = strdup(argv[1]);
}
}
-
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
-
- *config_home_out = config_home;
- return NSERROR_OK;
-}
-
-static nserror create_config_home(char **config_home_out)
-{
- char *config_home = NULL;
- char *home_dir;
- char *xdg_config_dir;
- nserror ret;
-
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
-
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
- * should be stored.
- */
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
-
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
- home_dir = getenv("HOME");
-
- if ((home_dir == NULL) || (*home_dir == 0)) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = netsurf_mkpath(&config_home, NULL, 4, home_dir,
".config","netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
} else {
- ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf",
"/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
-
- /* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(config_home);
- if (ret != NSERROR_OK) {
- free(config_home);
- return ret;
+ addr = strdup(NETSURF_HOMEPAGE);
}
- /* strip the trailing separator */
- config_home[strlen(config_home) - 1] = 0;
-
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
-
- *config_home_out = config_home;
-
- return NSERROR_OK;
-}
-
-/**
- * Get the path to the cache directory.
- *
- * @param cache_home_out Path to cache directory.
- * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
- */
-static nserror get_cache_home(char **cache_home_out)
-{
- nserror ret;
- char *xdg_cache_dir;
- char *cache_home;
- char *home_dir;
-
- /* $XDG_CACHE_HOME defines the base directory relative to
- * which user specific non-essential data files should be
- * stored.
- */
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
-
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- /* If $XDG_CACHE_HOME is either not set or empty, a
- * default equal to $HOME/.cache should be used.
- */
-
- home_dir = getenv("HOME");
-
- /* the HOME envvar is required */
- if (home_dir == NULL) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
}
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+ free(addr);
- *cache_home_out = cache_home;
- return NSERROR_OK;
+ return res;
}
-static nserror create_cache_home(char **cache_home_out)
+
+/**
+ * Run the gtk event loop.
+ *
+ * The same as the standard gtk_main loop except this ensures active
+ * FD are added to the gtk poll event set.
+ */
+static void nsgtk_main(void)
{
- char *cache_home = NULL;
- char *home_dir;
- char *xdg_cache_dir;
- nserror ret;
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+ GPollFD *fd_list[1000];
+ unsigned int fd_count;
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+ while (!nsgtk_complete) {
+ max_fd = -1;
+ fd_count = 0;
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
- /* $XDG_CACHE_HOME defines the base directory
- * relative to which user specific cache files
- * should be stored.
- */
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
+ while (gtk_events_pending())
+ gtk_main_iteration_do(TRUE);
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- home_dir = getenv("HOME");
+ schedule_run();
- if ((home_dir == NULL) || (*home_dir == 0)) {
- return NSERROR_NOT_DIRECTORY;
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+ for (int i = 0; i <= max_fd; i++) {
+ if (FD_ISSET(i, &read_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &write_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_OUT | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &exc_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
}
- ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache",
"netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf",
"/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
+ gtk_main_iteration();
- /* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(cache_home);
- if (ret != NSERROR_OK) {
- free(cache_home);
- return ret;
+ for (unsigned int i = 0; i != fd_count; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ }
}
+}
- /* strip the trailing separator */
- cache_home[strlen(cache_home) - 1] = 0;
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+/**
+ * finalise the browser
+ */
+static void nsgtk_finalise(void)
+{
+ nserror res;
- *cache_home_out = cache_home;
+ NSLOG(netsurf, INFO, "Quitting GUI");
- return NSERROR_OK;
-}
+ /* Ensure all scaffoldings are destroyed before we go into exit */
+ nsgtk_download_destroy();
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+ urldb_save(nsoption_charp(url_file));
-static nserror nsgtk_option_init(int *pargc, char** argv)
-{
- nserror ret;
- char *choices = NULL;
+ res = nsgtk_cookies_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
+ messages_get_errorcode(res));
+ }
- /* user options setup */
- ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
- if (ret != NSERROR_OK) {
- return ret;
+ res = nsgtk_local_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising local history viewer: %s",
+ messages_get_errorcode(res));
}
- /* Attempt to load the user choices */
- ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (ret == NSERROR_OK) {
- nsoption_read(choices, nsoptions);
- free(choices);
+ res = nsgtk_global_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising global history viewer: %s",
+ messages_get_errorcode(res));
}
- /* overide loaded options with those from commandline */
- nsoption_commandline(pargc, argv, nsoptions);
+ res = nsgtk_hotlist_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
+ messages_get_errorcode(res));
+ }
- /* ensure all options fall within sensible bounds */
+ res = hotlist_fini();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
+ messages_get_errorcode(res));
+ }
- /* Attempt to handle nonsense status bar widths. These may exist
- * in people's Choices as the GTK front end used to abuse the
- * status bar width option by using it for an absolute value in px.
- * The GTK front end now correctly uses it as a proportion of window
- * width. Here we assume that a value of less than 15% is wrong
- * and set to the default two thirds. */
- if (nsoption_int(toolbar_status_size) < 1500) {
- nsoption_set_int(toolbar_status_size, 6667);
+ res = save_complete_finalise();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising save complete: %s",
+ messages_get_errorcode(res));
}
- return NSERROR_OK;
-}
+ free(nsgtk_config_home);
-static struct gui_misc_table nsgtk_misc_table = {
- .schedule = nsgtk_schedule,
+ gtk_fetch_filetype_fin();
- .quit = gui_quit,
- .launch_url = gui_launch_url,
- .pdf_password = nsgtk_pdf_password,
- .present_cookies = nsgtk_cookies_present,
-};
+ /* common finalisation */
+ netsurf_exit();
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
-static nserror nsgtk_messages_init(char **respaths)
-{
- const char *messages;
- nserror ret;
- const uint8_t *data;
- size_t data_size;
+ /* finalise logging */
+ nslog_finalise();
- ret = nsgtk_data_from_resname("Messages", &data, &data_size);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_inline(data, data_size);
- } else {
- /* Obtain path to messages */
- ret = nsgtk_path_from_resname("Messages", &messages);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_file(messages);
- }
- }
- return ret;
}
+
/**
* Main entry point from OS.
*/
int main(int argc, char** argv)
{
+ nserror res;
char *cache_home = NULL;
- nserror ret;
struct netsurf_table nsgtk_table = {
- .misc = &nsgtk_misc_table,
+ .misc = nsgtk_misc_table,
.window = nsgtk_window_table,
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
@@ -1227,99 +1180,43 @@ int main(int argc, char** argv)
.layout = nsgtk_layout_table,
};
- ret = netsurf_register(&nsgtk_table);
- if (ret != NSERROR_OK) {
- die("NetSurf operation table failed registration\n");
- }
-
- /* Locate the correct user configuration directory path */
- ret = get_config_home(&nsgtk_config_home);
- if (ret == NSERROR_NOT_FOUND) {
- /* no config directory exists yet so try to create one */
- ret = create_config_home(&nsgtk_config_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to locate a configuration directory.");
- nsgtk_config_home = NULL;
- }
-
- /* Initialise gtk */
- gtk_init(&argc, &argv);
-
- /* initialise logging. Not fatal if it fails but not much we
- * can do about it either.
- */
- nslog_init(nslog_stream_configure, &argc, argv);
-
- /* build the common resource path list */
- respaths = nsgtk_init_resource_path(nsgtk_config_home);
- if (respaths == NULL) {
- fprintf(stderr, "Unable to locate resources\n");
- return 1;
- }
-
- /* initialise the gtk resource handling */
- ret = nsgtk_init_resources(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "GTK resources failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
- }
-
- /* Initialise user options */
- ret = nsgtk_option_init(&argc, argv);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Options failed to initialise (%s)\n",
- messages_get_errorcode(ret));
+ res = netsurf_register(&nsgtk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
return 1;
}
- /* Initialise translated messages */
- ret = nsgtk_messages_init(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Unable to load translated messages (%s)\n",
- messages_get_errorcode(ret));
- NSLOG(netsurf, INFO, "Unable to load translated messages");
- /** \todo decide if message load faliure should be fatal */
- }
-
- /* Locate the correct user cache directory path */
- ret = get_cache_home(&cache_home);
- if (ret == NSERROR_NOT_FOUND) {
- /* no cache directory exists yet so try to create one */
- ret = create_cache_home(&cache_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
+ /* gtk specific initialisation */
+ res = nsgtk_init(&argc, &argv, &cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf gtk failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
}
/* core initialisation */
- ret = netsurf_init(cache_home);
+ res = netsurf_init(cache_home);
free(cache_home);
- if (ret != NSERROR_OK) {
+ if (res != NSERROR_OK) {
fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
+ messages_get_errorcode(res));
+ return 3;
}
/* gtk specific initalisation and main run loop */
- ret = nsgtk_init(argc, argv, respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf gtk initialise failed (%s)\n",
- messages_get_errorcode(ret));
- } else {
- nsgtk_main();
+ res = nsgtk_setup(argc, argv, respaths);
+ if (res != NSERROR_OK) {
+ nsgtk_finalise();
+ fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
+ messages_get_errorcode(res));
+ return 4;
}
- /* common finalisation */
- netsurf_exit();
-
- /* finalise options */
- nsoption_finalise(nsoptions, nsoptions_default);
+ nsgtk_main();
- /* finalise logging */
- nslog_finalise();
+ nsgtk_finalise();
return 0;
}
diff --git a/frontends/gtk/misc.c b/frontends/gtk/misc.c
new file mode 100644
index 0000000..bda0dd6
--- /dev/null
+++ b/frontends/gtk/misc.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2021 Vincemt Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf 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 <
http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf miscellaneous operations table
+ */
+
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "netsurf/misc.h"
+#include "desktop/save_pdf.h"
+
+#include "gtk/compat.h"
+#include "gtk/warn.h"
+#include "gtk/schedule.h"
+#include "gtk/resources.h"
+#include "gtk/cookies.h"
+#include "gtk/misc.h"
+
+
+static nserror gui_launch_url(struct nsurl *url)
+{
+ gboolean ok;
+ GError *error = NULL;
+
+ ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
+ if (ok == TRUE) {
+ return NSERROR_OK;
+ }
+
+ if (error) {
+ nsgtk_warning(messages_get("URIOpenError"), error->message);
+ g_error_free(error);
+ }
+ return NSERROR_NO_FETCH_HANDLER;
+}
+
+static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
+{
+ char **owner_pass = ((void **)data)[0];
+ char **user_pass = ((void **)data)[1];
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ char *op, *op1;
+ char *up, *up1;
+
+ op = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword"))));
+ op1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword1"))));
+ up = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword"))));
+ up1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword1"))));
+
+
+ if (op[0] == '\0') {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "Owner password must be at least 1 character long:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, up)) {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "User and owner passwords must be different:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
+
+ *owner_pass = op;
+ if (up[0] == '\0')
+ free(up);
+ else
+ *user_pass = up;
+
+ free(data);
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+ } else {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")), "Passwords not confirmed:");
+ free(op);
+ free(up);
+ }
+
+ free(op1);
+ free(up1);
+}
+
+static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
+{
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ free(data);
+
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+}
+
+static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
+{
+ GtkButton *ok, *no;
+ GtkWindow *wnd;
+ void **data;
+ GtkBuilder *password_builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("password", &password_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Password UI builder init failed");
+ return;
+ }
+
+ gtk_builder_connect_signals(password_builder, NULL);
+
+ wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
+ "wndPDFPassword"));
+
+ data = malloc(5 * sizeof(void *));
+
+ *owner_pass = NULL;
+ *user_pass = NULL;
+
+ data[0] = owner_pass;
+ data[1] = user_pass;
+ data[2] = wnd;
+ data[3] = password_builder;
+ data[4] = path;
+
+ ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFSetPassword"));
+ no = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFNoPassword"));
+
+ g_signal_connect(G_OBJECT(ok), "clicked",
+ G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
+ g_signal_connect(G_OBJECT(no), "clicked",
+ G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
+
+ gtk_widget_show(GTK_WIDGET(wnd));
+}
+
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsgtk_schedule,
+
+ .launch_url = gui_launch_url,
+ .pdf_password = nsgtk_pdf_password,
+ .present_cookies = nsgtk_cookies_present,
+};
+
+struct gui_misc_table *nsgtk_misc_table = &misc_table;
diff --git a/frontends/atari/filetype.h b/frontends/gtk/misc.h
similarity index 80%
copy from frontends/atari/filetype.h
copy to frontends/gtk/misc.h
index 97ba75b..3a02c22 100644
--- a/frontends/atari/filetype.h
+++ b/frontends/gtk/misc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Ole Loots <ole(a)monochrom.net>
+ * Copyright 2021 Vincemt Sanders <vince(a)netsurf-browser.org>
*
* This file is part of NetSurf,
http://www.netsurf-browser.org/
*
@@ -16,9 +16,9 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-#ifndef NS_ATARI_FILETYPE_H_
-#define NS_ATARI_FILETYPE_H_
+#ifndef NETSURF_GTK_MISC_H
+#define NETSURF_GTK_MISC_H 1
-const char *fetch_filetype(const char *unix_path);
+extern struct gui_misc_table *nsgtk_misc_table;
#endif
diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index a85efce..f5de514 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -143,14 +143,14 @@ struct gui_bitmap_table {
int (*get_height)(void *bitmap);
/**
- * The the *bytes* per pixel.
+ * Get the *bytes* per pixel.
*
* \param bitmap The bitmap
*/
size_t (*get_bpp)(void *bitmap);
/**
- * Savde a bitmap to disc.
+ * Save a bitmap to disc.
*
* \param bitmap The bitmap to save
* \param path The path to save the bitmap to.
--
NetSurf Browser