diff options
Diffstat (limited to 'gtk')
68 files changed, 7898 insertions, 2813 deletions
diff --git a/gtk/dialogs/gtk_about.c b/gtk/dialogs/gtk_about.c index da97195c7..2862f9f03 100644 --- a/gtk/dialogs/gtk_about.c +++ b/gtk/dialogs/gtk_about.c @@ -30,8 +30,9 @@ static const gchar *authors[] = { "Matthew Hambley", "Rob Jackson", "Jeffrey Lee", "Phil Mellor", "Philip Pemberton", "Darren Salt", "Andrew Timmins", "John Tytgat", "Chris Williams", - "\nGoogle Summer of Code Contributors:", "Adam Blokus", - "Sean Fox", "Michael Lester", "Andrew Sidwell", NULL + "\nGoogle Summer of Code Contributors:", "Mark Benjamin", + "Adam Blokus", "Paul Blokus", "Sean Fox", + "Michael Lester", "Andrew Sidwell", "Bo Yang", NULL }; static const gchar *translators = "Sebastian Barthel\nBruno D'Arcangeli\n" diff --git a/gtk/dialogs/gtk_options.c b/gtk/dialogs/gtk_options.c index 472b8c58d..00f73e97e 100644 --- a/gtk/dialogs/gtk_options.c +++ b/gtk/dialogs/gtk_options.c @@ -2,6 +2,7 @@ * Copyright 2006 Rob Kendrick <rjek@rjek.com> * Copyright 2008 Mike Lester <element3260@gmail.com> * Copyright 2009 Daniel Silverstone <dsilvers@netsurf-browser.org> + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -27,17 +28,20 @@ #include <glade/glade.h> #include "desktop/options.h" #include "desktop/print.h" +#include "desktop/searchweb.h" #include "gtk/options.h" #include "gtk/gtk_gui.h" #include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_theme.h" #include "gtk/dialogs/gtk_options.h" #include "gtk/gtk_window.h" #include "utils/log.h" #include "utils/utils.h" +#include "utils/messages.h" -GtkDialog *wndPreferences; +GtkDialog *wndPreferences = NULL; static GladeXML *gladeFile; -static gchar *glade_location; + static struct browser_window *current_browser; static int proxy_type; @@ -45,6 +49,7 @@ static float animation_delay; static void dialog_response_handler (GtkDialog *dlg, gint res_id); static gboolean on_dialog_close (GtkDialog *dlg, gboolean stay_alive); +static void nsgtk_options_theme_combo(void); /* Declares both widget and callback */ #define DECLARE(x) \ @@ -97,6 +102,12 @@ DECLARE(checkRequestOverwrite); DECLARE(fileChooserDownloads); DECLARE(checkFocusNew); DECLARE(checkNewBlank); +DECLARE(checkUrlSearch); +DECLARE(comboSearch); +DECLARE(combotheme); +DECLARE(buttonaddtheme); +DECLARE(sourceButtonTab); +static GtkWidget *sourceButtonWindow; DECLARE(spinMarginTop); DECLARE(spinMarginBottom); @@ -125,7 +136,9 @@ DECLARE(setDefaultExportOptions); GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent) { - glade_location = g_strconcat(res_dir_location, "options.glade", NULL); + char glade_location[strlen(res_dir_location) + SLEN("options.glade") + + 1]; + sprintf(glade_location, "%soptions.glade", res_dir_location); LOG(("Using '%s' as Glade template file", glade_location)); gladeFile = glade_xml_new(glade_location, NULL, NULL); @@ -133,7 +146,13 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent) wndPreferences = GTK_DIALOG(glade_xml_get_widget(gladeFile, "dlgPreferences")); gtk_window_set_transient_for (GTK_WINDOW(wndPreferences), parent); - + + FIND_WIDGET(sourceButtonTab); + FIND_WIDGET(sourceButtonWindow); + GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON( + sourceButtonWindow)); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(sourceButtonTab), group); + /* set the widgets to reflect the current options */ nsgtk_options_load(); @@ -188,6 +207,12 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent) CONNECT(checkFocusNew, "toggled"); CONNECT(checkNewBlank, "toggled"); + CONNECT(checkUrlSearch, "toggled"); + CONNECT(comboSearch, "changed"); + + CONNECT(combotheme, "changed"); + CONNECT(buttonaddtheme, "clicked"); + CONNECT(sourceButtonTab, "toggled"); CONNECT(spinMarginTop, "value-changed"); CONNECT(spinMarginBottom, "value-changed"); @@ -247,11 +272,11 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent) (value)); \ } while (0) -#define SET_FILE_CHOOSER(widgt, value) \ +#define SET_FILE_CHOOSER(widget, value) \ do { \ - (widgt) = glade_xml_get_widget(gladeFile, #widgt); \ - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER((widgt)), \ - (value)); \ + (widget) = glade_xml_get_widget(gladeFile, #widget); \ + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(\ + (widget)), (value)); \ } while (0) #define SET_BUTTON(widget) \ @@ -262,22 +287,21 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent) void nsgtk_options_load(void) { - GtkVBox *combolanguagevbox; - gchar *languagefile; + GtkBox *box; + char languagefile[strlen(res_dir_location) + SLEN("languages") + 1]; const char *default_accept_language = option_accept_language ? option_accept_language : "en"; int combo_row_count = 0; int active_language = 0; int proxytype = 0; FILE *fp; - char buf[20]; + char buf[50]; /* Create combobox */ - combolanguagevbox = - GTK_VBOX(glade_xml_get_widget(gladeFile, "combolanguagevbox")); + box = GTK_BOX(glade_xml_get_widget(gladeFile, "combolanguagevbox")); comboLanguage = gtk_combo_box_new_text(); - languagefile = g_strconcat(res_dir_location, "languages", NULL); + sprintf(languagefile, "%slanguages", res_dir_location); /* Populate combobox from languages file */ fp = fopen((const char *) languagefile, "r"); @@ -309,10 +333,11 @@ void nsgtk_options_load(void) /** \todo localisation */ gtk_widget_set_tooltip_text(GTK_WIDGET(comboLanguage), "set preferred language for web pages"); - gtk_box_pack_start(GTK_BOX(combolanguagevbox), - comboLanguage, FALSE, FALSE, 0); + gtk_box_pack_start(box, comboLanguage, FALSE, FALSE, 0); gtk_widget_show(comboLanguage); - + + nsgtk_options_theme_combo(); + SET_ENTRY(entryHomePageURL, option_homepage_url ? option_homepage_url : ""); SET_BUTTON(setCurrentPage); @@ -380,7 +405,12 @@ void nsgtk_options_load(void) SET_CHECK(checkFocusNew, option_focus_new); SET_CHECK(checkNewBlank, option_new_blank); + SET_CHECK(checkUrlSearch, option_search_url_bar); + SET_COMBO(comboSearch, option_search_provider); + SET_BUTTON(buttonaddtheme); + SET_CHECK(sourceButtonTab, option_source_tab); + SET_SPIN(spinMarginTop, option_margin_top); SET_SPIN(spinMarginBottom, option_margin_bottom); SET_SPIN(spinMarginLeft, option_margin_left); @@ -417,6 +447,48 @@ static gboolean on_dialog_close (GtkDialog *dlg, gboolean stay_alive) } return stay_alive; } + +static void nsgtk_options_theme_combo(void) { +/* populate theme combo from themelist file */ + GtkBox *box = GTK_BOX(glade_xml_get_widget(gladeFile, "themehbox")); + char buf[50]; + combotheme = gtk_combo_box_new_text(); + size_t len = SLEN("themelist") + strlen(res_dir_location) + 1; + char themefile[len]; + if ((combotheme == NULL) || (box == NULL)) { + warn_user(messages_get("NoMemory"), 0); + return; + } + snprintf(themefile, len, "%sthemelist", res_dir_location); + FILE *fp = fopen((const char *)themefile, "r"); + if (fp == NULL) { + LOG(("Failed opening themes file")); + warn_user("FileError", (const char *) themefile); + return; + } + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* Ignore blank lines */ + if (buf[0] == '\0') + continue; + + /* Remove trailing \n */ + buf[strlen(buf) - 1] = '\0'; + + gtk_combo_box_append_text(GTK_COMBO_BOX(combotheme), buf); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(combotheme), + option_current_theme); + gtk_box_pack_start(box, combotheme, FALSE, TRUE, 0); + gtk_widget_show(combotheme); +} + +bool nsgtk_options_combo_theme_add(const char *themename) +{ + if (wndPreferences == NULL) + return false; + gtk_combo_box_append_text(GTK_COMBO_BOX(combotheme), themename); + return true; +} /* Defines the callback functions for all widgets and specifies @@ -642,42 +714,44 @@ BUTTON_CLICKED(fontPreview) END_HANDLER COMBO_CHANGED(comboButtonType, option_button_type) - struct gui_window *current = window_list; - + nsgtk_scaffolding *current = scaf_list; + option_button_type++; + /* value of 0 is reserved for 'unset' */ while (current) { + nsgtk_scaffolding_reset_offset(current); switch(option_button_type) { - case 0: + case 1: gtk_toolbar_set_style( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_TOOLBAR_ICONS); gtk_toolbar_set_icon_size( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_ICON_SIZE_SMALL_TOOLBAR); break; - case 1: + case 2: gtk_toolbar_set_style( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_TOOLBAR_ICONS); gtk_toolbar_set_icon_size( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_ICON_SIZE_LARGE_TOOLBAR); break; - case 2: + case 3: gtk_toolbar_set_style( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_TOOLBAR_BOTH); gtk_toolbar_set_icon_size( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_ICON_SIZE_LARGE_TOOLBAR); break; - case 3: + case 4: gtk_toolbar_set_style( - GTK_TOOLBAR(current->scaffold->tool_bar), + GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)), GTK_TOOLBAR_TEXT); default: break; } - current = current->next; + current = nsgtk_scaffolding_iterate(current); } END_HANDLER @@ -703,6 +777,114 @@ END_HANDLER CHECK_CHANGED(checkNewBlank, option_new_blank) END_HANDLER +CHECK_CHANGED(checkUrlSearch, option_search_url_bar) +END_HANDLER + +COMBO_CHANGED(comboSearch, option_search_provider) + nsgtk_scaffolding *current = scaf_list; + char *name; + /* refresh web search prefs from file */ + search_web_provider_details(option_search_provider); + /* retrieve ico */ + search_web_retrieve_ico(false); + /* callback may handle changing gui */ + if (search_web_ico() != NULL) + gui_window_set_search_ico(search_web_ico()); + /* set entry */ + name = search_web_provider_name(); + if (name == NULL) { + warn_user(messages_get("NoMemory"), 0); + continue; + } + char content[strlen(name) + SLEN("Search ") + 1]; + sprintf(content, "Search %s", name); + free(name); + while (current) { + nsgtk_scaffolding_set_websearch(current, content); + current = nsgtk_scaffolding_iterate(current); + } +END_HANDLER + +COMBO_CHANGED(combotheme, option_current_theme) + nsgtk_scaffolding *current = scaf_list; + char *name; + if (option_current_theme != 0) { + if (nsgtk_theme_name() != NULL) + free(nsgtk_theme_name()); + name = strdup(gtk_combo_box_get_active_text( + GTK_COMBO_BOX(combotheme))); + if (name == NULL) { + warn_user(messages_get("NoMemory"), 0); + continue; + } + nsgtk_theme_set_name(name); + nsgtk_theme_prepare(); + } else if (nsgtk_theme_name() != NULL) { + free(nsgtk_theme_name()); + nsgtk_theme_set_name(NULL); + } + while (current) { + nsgtk_theme_implement(current); + current = nsgtk_scaffolding_iterate(current); + } +END_HANDLER + +BUTTON_CLICKED(buttonaddtheme) + char *filename, *directory; + size_t len; + GtkWidget *fc = gtk_file_chooser_dialog_new( + messages_get("gtkAddThemeTitle"), + GTK_WINDOW(wndPreferences), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + len = SLEN("themes") + strlen(res_dir_location) + 1; + char themesfolder[len]; + snprintf(themesfolder, len, "%sthemes", res_dir_location); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), + themesfolder); + gint res = gtk_dialog_run(GTK_DIALOG(fc)); + if (res == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_current_folder( + GTK_FILE_CHOOSER(fc)); + if (strcmp(filename, themesfolder) != 0) { + directory = strrchr(filename, '/'); + *directory = '\0'; + if (strcmp(filename, themesfolder) != 0) { + warn_user(messages_get( + "gtkThemeFolderInstructions"), + 0); + gtk_widget_destroy(GTK_WIDGET(fc)); + free(filename); + free(themesfolder); + return FALSE; + } else { + directory++; + } + } else { + free(filename); + filename = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(fc)); + if (strcmp(filename, themesfolder) == 0) { + warn_user(messages_get("gtkThemeFolderSub"), + 0); + gtk_widget_destroy(GTK_WIDGET(fc)); + free(filename); + free(themesfolder); + return FALSE; + } + directory = strrchr(filename, '/') + 1; + } + gtk_widget_destroy(GTK_WIDGET(fc)); + nsgtk_theme_add(directory); + free(filename); + } + +END_HANDLER + +CHECK_CHANGED(sourceButtonTab, option_source_tab) +END_HANDLER + SPIN_CHANGED(spinMarginTop, option_margin_top) END_HANDLER diff --git a/gtk/dialogs/gtk_options.h b/gtk/dialogs/gtk_options.h index cc269d178..9f6602593 100644 --- a/gtk/dialogs/gtk_options.h +++ b/gtk/dialogs/gtk_options.h @@ -1,5 +1,6 @@ /* * Copyright 2006 Rob Kendrick <rjek@rjek.com> + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -23,8 +24,11 @@ extern GtkDialog *wndPreferences; -GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent); /** Init options and load window */ +GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent); + /** Init options and load window */ void nsgtk_options_load(void); /** Load current options into window */ void nsgtk_options_save(void); /** Save options from window */ +bool nsgtk_options_combo_theme_add(const char *themename); + /** add new theme name to combo */ #endif diff --git a/gtk/dialogs/gtk_source.c b/gtk/dialogs/gtk_source.c index d52fbb25c..361bcabd9 100644 --- a/gtk/dialogs/gtk_source.c +++ b/gtk/dialogs/gtk_source.c @@ -28,8 +28,10 @@ #include "gtk/gtk_gui.h" #include "gtk/gtk_print.h" #include "gtk/gtk_selection.h" +#include "gtk/options.h" #include "desktop/netsurf.h" #include "desktop/print.h" +#include "desktop/options.h" #include "utils/messages.h" #include "utils/url.h" #include "utils/utils.h" @@ -57,10 +59,10 @@ struct menu_events { }; static GladeXML *glade_File; -static gchar *glade_Location; static struct nsgtk_source_window *nsgtk_source_list = 0; static char source_zoomlevel = 10; +void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw); static void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g); static gboolean nsgtk_source_delete_event(GtkWindow *window, gpointer g); static gboolean nsgtk_source_destroy_event(GtkWindow *window, gpointer g); @@ -102,112 +104,153 @@ MENUEVENT(source_about), }; void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw) -{ - if (bw->current_content->type == CONTENT_HTML) { - glade_Location = g_strconcat(res_dir_location, "source.glade", - NULL); - glade_File = glade_xml_new(glade_Location, NULL, NULL); - if (glade_File == NULL) { - LOG(("error loading glade tree")); - } - - char *data = NULL; +{ + char glade_Location[strlen(res_dir_location) + SLEN("source.glade") + + 1]; + if (bw->current_content->type != CONTENT_HTML) + return; + + if (option_source_tab) { + nsgtk_source_tab_init(parent, bw); + return; + } + + sprintf(glade_Location, "%ssource.glade", res_dir_location); + glade_File = glade_xml_new(glade_Location, NULL, NULL); + if (glade_File == NULL) { + LOG(("error loading glade tree")); + } - utf8_convert_ret r = utf8_from_enc( - bw->current_content->source_data, - bw->current_content->data.html.encoding, - bw->current_content->source_size, - &data); - if (r == UTF8_CONVERT_NOMEM) { - warn_user("NoMemory",0); - return; - } else if (r == UTF8_CONVERT_BADENC) { - warn_user("EncNotRec",0); - return; - } + char *data = NULL; + + utf8_convert_ret r = utf8_from_enc( + bw->current_content->source_data, + bw->current_content->data.html.encoding, + bw->current_content->source_size, + &data); + if (r == UTF8_CONVERT_NOMEM) { + warn_user("NoMemory",0); + return; + } else if (r == UTF8_CONVERT_BADENC) { + warn_user("EncNotRec",0); + return; + } - GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget( - glade_File, "wndSource")); - GtkWidget *cutbutton = glade_xml_get_widget( - glade_File, "source_cut"); - GtkWidget *pastebutton = glade_xml_get_widget( - glade_File, "source_paste"); - GtkWidget *deletebutton = glade_xml_get_widget( - glade_File, "source_delete"); - GtkWidget *printbutton = glade_xml_get_widget( - glade_File, "source_print"); - gtk_widget_set_sensitive(cutbutton, FALSE); - gtk_widget_set_sensitive(pastebutton, FALSE); - gtk_widget_set_sensitive(deletebutton, FALSE); - /* for now */ - gtk_widget_set_sensitive(printbutton, FALSE); - - struct nsgtk_source_window *thiswindow = - malloc(sizeof(struct nsgtk_source_window)); - if (thiswindow == NULL) { - free(data); - warn_user("NoMemory", 0); - return; - } + GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget( + glade_File, "wndSource")); + GtkWidget *cutbutton = glade_xml_get_widget( + glade_File, "source_cut"); + GtkWidget *pastebutton = glade_xml_get_widget( + glade_File, "source_paste"); + GtkWidget *deletebutton = glade_xml_get_widget( + glade_File, "source_delete"); + GtkWidget *printbutton = glade_xml_get_widget( + glade_File, "source_print"); + gtk_widget_set_sensitive(cutbutton, FALSE); + gtk_widget_set_sensitive(pastebutton, FALSE); + gtk_widget_set_sensitive(deletebutton, FALSE); + /* for now */ + gtk_widget_set_sensitive(printbutton, FALSE); + + struct nsgtk_source_window *thiswindow = + malloc(sizeof(struct nsgtk_source_window)); + if (thiswindow == NULL) { + free(data); + warn_user("NoMemory", 0); + return; + } - thiswindow->url = strdup(bw->current_content->url); - if (thiswindow->url == NULL) { - free(thiswindow); - free(data); - warn_user("NoMemory", 0); - return; - } + thiswindow->url = strdup(bw->current_content->url); + if (thiswindow->url == NULL) { + free(thiswindow); + free(data); + warn_user("NoMemory", 0); + return; + } - thiswindow->data = data; - - thiswindow->sourcewindow = wndSource; - thiswindow->bw = bw; + thiswindow->data = data; - char *title = malloc(strlen(bw->current_content->url) - + SLEN("Source of ") + 1); - if (title == NULL) { - free(thiswindow->url); - free(thiswindow); - free(data); - warn_user("NoMemory", 0); - return; - } - sprintf(title, "Source of %s", bw->current_content->url); - - thiswindow->next = nsgtk_source_list; - thiswindow->prev = NULL; - if (nsgtk_source_list != NULL) - nsgtk_source_list->prev = thiswindow; - nsgtk_source_list = thiswindow; - - nsgtk_attach_source_menu_handlers(glade_File, thiswindow); + thiswindow->sourcewindow = wndSource; + thiswindow->bw = bw; + + char title[strlen(bw->current_content->url) + SLEN("Source of ") + 1]; + sprintf(title, "Source of %s", bw->current_content->url); + + thiswindow->next = nsgtk_source_list; + thiswindow->prev = NULL; + if (nsgtk_source_list != NULL) + nsgtk_source_list->prev = thiswindow; + nsgtk_source_list = thiswindow; - gtk_window_set_title(wndSource, title); + nsgtk_attach_source_menu_handlers(glade_File, thiswindow); - g_signal_connect(G_OBJECT(wndSource), "destroy", - G_CALLBACK(nsgtk_source_destroy_event), - thiswindow); - g_signal_connect(G_OBJECT(wndSource), "delete-event", - G_CALLBACK(nsgtk_source_delete_event), - thiswindow); + gtk_window_set_title(wndSource, title); + + g_signal_connect(G_OBJECT(wndSource), "destroy", + G_CALLBACK(nsgtk_source_destroy_event), + thiswindow); + g_signal_connect(G_OBJECT(wndSource), "delete-event", + G_CALLBACK(nsgtk_source_delete_event), + thiswindow); + + GtkTextView *sourceview = GTK_TEXT_VIEW( + glade_xml_get_widget(glade_File, + "source_view")); + PangoFontDescription *fontdesc = + pango_font_description_from_string("Monospace 8"); + + thiswindow->gv = sourceview; + gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc); + GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview); + gtk_text_buffer_set_text(tb, thiswindow->data, -1); - GtkTextView *sourceview = GTK_TEXT_VIEW( - glade_xml_get_widget(glade_File, - "source_view")); - PangoFontDescription *fontdesc = - pango_font_description_from_string("Monospace 8"); - - thiswindow->gv = sourceview; - gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc); - GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview); - gtk_text_buffer_set_text(tb, thiswindow->data, -1); - - gtk_widget_show(GTK_WIDGET(wndSource)); + gtk_widget_show(GTK_WIDGET(wndSource)); - free(title); +} +void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw) +{ + char *ndata = 0; + utf8_convert_ret r = utf8_from_enc( + bw->current_content->source_data, + bw->current_content->data.html.encoding, + bw->current_content->source_size, + &ndata); + if (r == UTF8_CONVERT_NOMEM) { + warn_user("NoMemory",0); + return; + } else if (r == UTF8_CONVERT_BADENC) { + warn_user("EncNotRec",0); + return; + } + gchar *filename; + char *fileurl; + gint handle = g_file_open_tmp("nsgtksourceXXXXXX", &filename, NULL); + close (handle); /* in case it was binary mode */ + FILE *f = fopen(filename, "w"); + fprintf(f, "%s", ndata); + fclose(f); + free(ndata); + fileurl = path_to_url(filename); + g_free(filename); + if (fileurl == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + struct browser_window *newbw = browser_window_create(fileurl, bw, + NULL, false, true); + free(fileurl); + if (newbw->current_content) { + newbw->current_content->title = malloc( + strlen(bw->current_content->url) + + SLEN("source of ") + 1); + if (newbw->current_content->title == NULL) + return; + sprintf(newbw->current_content->title, "source of %s", + bw->current_content->url); } } + void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g) { struct menu_events *event = source_menu_events; @@ -264,7 +307,7 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename, { FILE *f; bool auth = true; - char temp[15]; + char temp[255]; GtkWidget *notif, *label; if (!(access(filename, F_OK))) { @@ -277,21 +320,18 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); - char *warn; const char *format = messages_get("gtkOverwrite"); - int len = strlen(filename) + strlen(format); - + int len = strlen(filename) + strlen(format) + SLEN("\n\n") + 1; + char warn[len]; auth = false; - warn = malloc(len); - if (warn == NULL) { - warn_user("NoMemory", 0); - return; - } - - snprintf(warn, len, format, filename); + warn[0] = '\n'; + snprintf(warn + 1, len - 2, format, filename); + len = strlen(warn); + warn[len - 1] = '\n'; + warn[len] = '\0'; - label = gtk_label_new(g_strconcat("\n",warn,"\n", NULL)); + label = gtk_label_new(warn); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(confd)->vbox), label); gtk_widget_show(label); @@ -299,16 +339,19 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename, auth = true; } gtk_widget_destroy(confd); - free(warn); } if (auth) { f = fopen(filename, "w+"); fprintf(f, "%s", data); fclose(f); - strcpy(temp, messages_get("gtkSaveConfirm")); + snprintf(temp, sizeof(temp), "\n %s" + " \n", + messages_get("gtkSaveConfirm")); } else { - strcpy(temp, messages_get("gtkSaveCancelled")); + snprintf(temp, sizeof(temp), "\n %s" + " \n", + messages_get("gtkSaveCancelled")); } notif = gtk_dialog_new_with_buttons(temp, @@ -316,8 +359,7 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename, GTK_RESPONSE_NONE, NULL); g_signal_connect_swapped(notif, "response", G_CALLBACK(gtk_widget_destroy), notif); - label = gtk_label_new(g_strconcat("\n ", temp, - " \n", NULL)); + label = gtk_label_new(temp); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(notif)->vbox), label); gtk_widget_show_all(notif); } diff --git a/gtk/gtk_download.c b/gtk/gtk_download.c index 23b30ef88..fb8541587 100644 --- a/gtk/gtk_download.c +++ b/gtk/gtk_download.c @@ -33,6 +33,7 @@ #include "gtk/gtk_scaffolding.h" #include "gtk/options.h" #include "gtk/gtk_download.h" +#include "gtk/gtk_window.h" #define UPDATE_RATE 500 /* In milliseconds */ #define GLADE_NAME "downloads.glade" @@ -86,9 +87,9 @@ static gboolean nsgtk_download_handle_error (GError *error); void nsgtk_download_init() { - gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + char glade_location[strlen(res_dir_location) + SLEN(GLADE_NAME) + 1]; + sprintf(glade_location, "%s" GLADE_NAME, res_dir_location); GladeXML *gladeFile = glade_xml_new(glade_location, NULL, NULL); - g_free(glade_location); nsgtk_download_buttons = glade_xml_get_widget_prefix(gladeFile, "button"); @@ -202,11 +203,12 @@ struct gui_download_window *gui_download_window_create(const char *url, gchar *filename; gchar *destination; gboolean unknown_size = total_size == 0; - const gchar *size = (total_size == 0 ? + const char *size = (total_size == 0 ? messages_get("gtkUnknownSize") : human_friendly_bytesize(total_size)); - nsgtk_download_parent = nsgtk_scaffolding_get_window(gui); + nsgtk_download_parent = nsgtk_scaffolding_window(nsgtk_get_scaffold( + gui)); struct gui_download_window *download = malloc(sizeof *download); if (url_nice(url, &filename, false) != URL_FUNC_OK) @@ -488,8 +490,9 @@ gboolean nsgtk_download_update(gboolean force_update) void nsgtk_download_store_update_item (struct gui_download_window *dl) { gchar *info = nsgtk_download_info_to_string(dl); - gchar *speed = g_strconcat(human_friendly_bytesize(dl->speed), "/s", - NULL); + char *human = human_friendly_bytesize(dl->speed); + char speed[strlen(human) + SLEN("/s") + 1]; + sprintf(speed, "%s/s", human); gchar *time = nsgtk_download_time_to_string(dl->time_remaining); gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING; @@ -508,7 +511,6 @@ void nsgtk_download_store_update_item (struct gui_download_window *dl) -1); g_free(info); - g_free(speed); g_free(time); } @@ -634,7 +636,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, { enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS }; GtkWidget *dialog; - gchar *destination = NULL; + char *destination = NULL; gchar *message = g_strdup(messages_get("gtkStartDownload")); gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename, domain, size); @@ -682,9 +684,15 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, break; } case GTK_RESPONSE_DOWNLOAD: { - destination = g_strconcat(option_downloads_directory, - "/", filename, NULL); - /* Test if file already exists and display overwrite + destination = malloc(strlen(option_downloads_directory) + + strlen(filename) + SLEN("/") + 1); + if (destination == NULL) { + warn_user(messages_get("NoMemory"), 0); + break; + } + sprintf(destination, "%s/%s", + option_downloads_directory, filename); + /* Test if file already exists and display overwrite * confirmation if needed */ if (g_file_test(destination, G_FILE_TEST_EXISTS) && option_request_overwrite) { @@ -711,7 +719,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock( "gtk-save", - GTK_ICON_SIZE_BUTTON)); + GTK_ICON_SIZE_BUTTON)); gint result = gtk_dialog_run(GTK_DIALOG( dialog)); diff --git a/gtk/gtk_gui.c b/gtk/gtk_gui.c index 971c3fbf2..43860e9ab 100644 --- a/gtk/gtk_gui.c +++ b/gtk/gtk_gui.c @@ -43,6 +43,7 @@ #include "desktop/netsurf.h" #include "desktop/options.h" #include "desktop/save_pdf/pdf_plotters.h" +#include "desktop/searchweb.h" #include "desktop/textinput.h" #include "gtk/gtk_gui.h" #include "gtk/dialogs/gtk_options.h" @@ -68,15 +69,23 @@ char *default_stylesheet_url; char *quirks_stylesheet_url; char *adblock_stylesheet_url; char *options_file_location; -char *glade_file_location; +char *glade_netsurf_file_location; +char *glade_password_file_location; +char *glade_warning_file_location; +char *glade_login_file_location; +char *glade_ssl_file_location; +char *glade_toolbar_file_location; +char *toolbar_indices_file_location; char *res_dir_location; char *print_options_file_location; -struct gui_window *search_current_window = 0; - GtkWindow *wndAbout; GtkWindow *wndWarning; -GladeXML *gladeWindows; +GladeXML *gladeNetsurf; +GladeXML *gladePassword; +GladeXML *gladeWarning; +GladeXML *gladeLogin; +GladeXML *gladeSsl; GtkWindow *wndTooltip; GtkLabel *labelTooltip; @@ -195,12 +204,28 @@ void gui_init(int argc, char** argv) check_homedir(); find_resource(buf, "netsurf.glade", "./gtk/res/netsurf.glade"); - LOG(("Using '%s' as Glade template file", buf)); - glade_file_location = strdup(buf); + LOG(("Using '%s' as Netsurf glade template file", buf)); + glade_netsurf_file_location = strdup(buf); buf[strlen(buf)- 13] = 0; LOG(("Using '%s' as Resources directory", buf)); res_dir_location = strdup(buf); + + find_resource(buf, "password.glade", "./gtk/res/password.glade"); + LOG(("Using '%s' as password glade template file", buf)); + glade_password_file_location = strdup(buf); + + find_resource(buf, "warning.glade", "./gtk/res/warning.glade"); + LOG(("Using '%s' as warning glade template file", buf)); + glade_warning_file_location = strdup(buf); + + find_resource(buf, "login.glade", "./gtk/res/login.glade"); + LOG(("Using '%s' as login glade template file", buf)); + glade_login_file_location = strdup(buf); + + find_resource(buf, "ssl.glade", "./gtk/res/ssl.glade"); + LOG(("Using '%s' as ssl glade template file", buf)); + glade_ssl_file_location = strdup(buf); find_resource(buf, "Aliases", "./gtk/res/Aliases"); LOG(("Using '%s' as Aliases file", buf)); @@ -208,17 +233,42 @@ void gui_init(int argc, char** argv) die("Unable to initialise HTML parsing library.\n"); glade_init(); - gladeWindows = glade_xml_new(glade_file_location, NULL, NULL); - if (gladeWindows == NULL) - die("Unable to load Glade window definitions.\n"); - glade_xml_signal_autoconnect(gladeWindows); + gladeWarning = glade_xml_new(glade_warning_file_location, NULL, NULL); + if (gladeWarning == NULL) + die("Unable to load glade warning window definitions.\n"); + glade_xml_signal_autoconnect(gladeWarning); + + gladeNetsurf = glade_xml_new(glade_netsurf_file_location, NULL, NULL); + if (gladeNetsurf == NULL) + die("Unable to load glade Netsurf window definitions.\n"); + glade_xml_signal_autoconnect(gladeNetsurf); + + gladePassword = glade_xml_new(glade_password_file_location, NULL, NULL); + if (gladePassword == NULL) + die("Unable to load glade password window definitions.\n"); + glade_xml_signal_autoconnect(gladePassword); + + gladeLogin = glade_xml_new(glade_login_file_location, NULL, NULL); + if (gladeLogin == NULL) + die("Unable to load glade login window definitions.\n"); + glade_xml_signal_autoconnect(gladeLogin); + + gladeSsl = glade_xml_new(glade_ssl_file_location, NULL, NULL); + if (gladeSsl == NULL) + die("Unable to load glade ssl window definitions.\n"); + glade_xml_signal_autoconnect(gladeSsl); + + find_resource(buf, "toolbar.glade", "./gtk/res/toolbar.glade"); + LOG(("Using '%s' as glade toolbar file", buf)); + glade_toolbar_file_location = strdup(buf); find_resource(buf, "netsurf.xpm", "./gtk/res/netsurf.xpm"); gtk_window_set_default_icon_from_file(buf, NULL); - wndTooltip = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndTooltip")); - labelTooltip = GTK_LABEL(glade_xml_get_widget(gladeWindows, "tooltip")); - + /* superfluous ? */ + wndTooltip = GTK_WINDOW(glade_xml_get_widget(gladeNetsurf, "wndTooltip")); + labelTooltip = GTK_LABEL(glade_xml_get_widget(gladeNetsurf, "tooltip")); + nsgtk_completion_init(); /* This is an ugly hack to just get the new-style throbber going. @@ -321,12 +371,25 @@ void gui_init(int argc, char** argv) LOG(("Using '%s' as Print Settings file", buf)); print_options_file_location = strdup(buf); + find_resource(buf, "SearchEngines", "./gtk/res/SearchEngines"); + LOG(("Using '%s' as Search Engines file", buf)); + search_engines_file_location = strdup(buf); + + find_resource(buf, "default.ico", "./gtk/res/default.ico"); + LOG(("Using '%s' as default search ico", buf)); + search_default_ico_location = strdup(buf); + + find_resource(buf, "toolbarIndices", "./gtk/res/toolbarIndices"); + LOG(("Using '%s' as custom toolbar settings file", buf)); + toolbar_indices_file_location = strdup(buf); + urldb_load(option_url_file); urldb_load_cookies(option_cookie_file); + + /* superfluous ? */ + wndAbout = GTK_WINDOW(glade_xml_get_widget(gladeNetsurf, "wndAbout")); - wndAbout = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndAbout")); - - wndWarning = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndWarning")); + wndWarning = GTK_WINDOW(glade_xml_get_widget(gladeWarning, "wndWarning")); nsgtk_history_init(); nsgtk_download_init(); @@ -428,6 +491,9 @@ void gui_quit(void) free(option_cookie_file); free(option_cookie_jar); free(print_options_file_location); + free(search_engines_file_location); + free(search_default_ico_location); + free(toolbar_indices_file_location); gtk_fetch_filetype_fin(); /* We don't care if this fails as we're about to die, anyway */ hubbub_finalise(myrealloc, NULL); @@ -490,15 +556,6 @@ void gui_launch_url(const char *url) { } - -bool gui_search_term_highlighted(struct gui_window *g, - unsigned start_offset, unsigned end_offset, - unsigned *start_idx, unsigned *end_idx) -{ - return false; -} - - void warn_user(const char *warning, const char *detail) { char buf[300]; /* 300 is the size the RISC OS GUI uses */ @@ -510,7 +567,7 @@ void warn_user(const char *warning, const char *detail) detail ? detail : ""); buf[sizeof(buf) - 1] = 0; - gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows, "labelWarning")), buf); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWarning, "labelWarning")), buf); gtk_widget_show_all(GTK_WIDGET(wndWarning)); } @@ -536,7 +593,7 @@ static void nsgtk_create_ssl_verify_window(struct browser_window *bw, struct content *c, const struct ssl_cert_info *certs, unsigned long num) { - GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL); + GladeXML *x = glade_xml_new(glade_ssl_file_location, NULL, NULL); GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndSSLProblem")); GtkButton *accept, *reject; void **session = calloc(sizeof(void *), 4); @@ -618,7 +675,7 @@ utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len, char *path_to_url(const char *path) { - char *r = malloc(strlen(path) + 7 + 1); + char *r = malloc(strlen(path) + SLEN("file://") + 1); strcpy(r, "file://"); strcat(r, path); @@ -640,7 +697,7 @@ bool cookies_update(const char *domain, const struct cookie_data *data) void PDF_Password(char **owner_pass, char **user_pass, char *path) { - GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL); + GladeXML *x = glade_xml_new(glade_password_file_location, NULL, NULL); GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndPDFPassword")); GtkButton *ok, *no; void **data = malloc(5 * sizeof(void *)); diff --git a/gtk/gtk_gui.h b/gtk/gtk_gui.h index 8c9aa0afb..21bc84202 100644 --- a/gtk/gtk_gui.h +++ b/gtk/gtk_gui.h @@ -25,8 +25,18 @@ #include <glade/glade.h> extern bool gui_in_multitask; -extern GladeXML *gladeWindows; -extern char *glade_file_location; +extern GladeXML *gladeNetsurf; +extern GladeXML *gladePassword; +extern GladeXML *gladeWarning; +extern GladeXML *gladeLogin; +extern GladeXML *gladeSsl; +extern char *glade_netsurf_file_location; +extern char *glade_password_file_location; +extern char *glade_warning_file_location; +extern char *glade_login_file_location; +extern char *glade_ssl_file_location; +extern char *glade_toolbar_file_location; +extern char *toolbar_indices_file_location; extern char *options_file_location; extern char *res_dir_location; extern char *print_options_file_location; diff --git a/gtk/gtk_history.c b/gtk/gtk_history.c index e0376dad5..9bcb584d6 100644 --- a/gtk/gtk_history.c +++ b/gtk/gtk_history.c @@ -107,9 +107,9 @@ void nsgtk_history_init(void) dateAt = messages_get("DateAt"); domainAll = messages_get("DomainAll"); - gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + char glade_location[strlen(res_dir_location) + SLEN(GLADE_NAME) + 1]; + sprintf(glade_location, "%s" GLADE_NAME, res_dir_location); gladeFile = glade_xml_new(glade_location, NULL, NULL); - g_free(glade_location); glade_xml_signal_autoconnect(gladeFile); wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile, @@ -500,23 +500,23 @@ void nsgtk_history_search_clear (GtkEntry *entry) gchar *nsgtk_history_date_parse(time_t visit_time) { - gchar *date_string = malloc(30); - gchar format[30]; + char *date_string = malloc(30); + char format[30]; time_t current_time = time(NULL); - gint current_day = localtime(¤t_time)->tm_yday; + int current_day = localtime(¤t_time)->tm_yday; struct tm *visit_date = localtime(&visit_time); if (visit_date->tm_yday == current_day) - g_snprintf(format, 30, "%s %s %%I:%%M %%p", + snprintf(format, 30, "%s %s %%I:%%M %%p", dateToday, dateAt); else if (current_day - visit_date->tm_yday == 1) - g_snprintf(format, 30, "%s %s %%I:%%M %%p", + snprintf(format, 30, "%s %s %%I:%%M %%p", dateYesterday, dateAt); else if (current_day - visit_date->tm_yday < 7) - g_snprintf(format, 30, "%%A %s %%I:%%M %%p", + snprintf(format, 30, "%%A %s %%I:%%M %%p", dateAt); else - g_snprintf(format, 30, "%%B %%d, %%Y"); + snprintf(format, 30, "%%B %%d, %%Y"); strftime(date_string, 30, format, visit_date); diff --git a/gtk/gtk_login.c b/gtk/gtk_login.c index d2535515e..3bb11a66b 100644 --- a/gtk/gtk_login.c +++ b/gtk/gtk_login.c @@ -74,7 +74,7 @@ void create_login_window(struct browser_window *bw, const char *host, * the widgets we're interested in. */ - GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL); + GladeXML *x = glade_xml_new(glade_login_file_location, NULL, NULL); GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndLogin")); GtkLabel *lhost, *lrealm; GtkEntry *euser, *epass; diff --git a/gtk/gtk_menu.c b/gtk/gtk_menu.c new file mode 100644 index 000000000..e7e02d77b --- /dev/null +++ b/gtk/gtk_menu.c @@ -0,0 +1,422 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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/>. + */ + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> +#include <stdlib.h> +#include "gtk/gtk_menu.h" +#include "utils/messages.h" +#include "utils/utils.h" + +static struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *); +static struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu( + GtkAccelGroup *); +static struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *); +static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu( + GtkAccelGroup *); +static struct nsgtk_debugging_submenu *nsgtk_menu_debugging_submenu( + GtkAccelGroup *); +static bool nsgtk_menu_add_image_item(GtkMenu *menu, + GtkImageMenuItem **item, const char *message, + const char *messageAccel, GtkAccelGroup *group); + +/** + * adds image menu item to specified menu + * \param menu the menu to add the item to + * \param item a pointer to the item's location in the menu struct + * \param message the menu item I18n lookup value + * \param messageAccel the menu item accelerator I18n lookup value + * \param group the 'global' in a gtk sense accelerator group + */ + +bool nsgtk_menu_add_image_item(GtkMenu *menu, + GtkImageMenuItem **item, const char *message, + const char *messageAccel, GtkAccelGroup *group) +{ + unsigned int key; + GdkModifierType mod; + *item = GTK_IMAGE_MENU_ITEM(gtk_image_menu_item_new_with_mnemonic( + messages_get(message))); + if (*item == NULL) + return false; + gtk_accelerator_parse(messages_get(messageAccel), &key, &mod); + if (key > 0) + gtk_widget_add_accelerator(GTK_WIDGET(*item), "activate", + group, key, mod, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(*item)); + gtk_widget_show(GTK_WIDGET(*item)); + return true; +} + +#define IMAGE_ITEM(p, q, r, s, t)\ + nsgtk_menu_add_image_item(s->p##_menu, &(s->q##_menuitem), #r,\ + #r "Accel", t); + +#define CHECK_ITEM(p, q, r, s)\ + s->q##_menuitem = GTK_CHECK_MENU_ITEM(\ + gtk_check_menu_item_new_with_mnemonic(\ + messages_get(#r)));\ + if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) {\ + gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu),\ + GTK_WIDGET(s->q##_menuitem));\ + gtk_widget_show(GTK_WIDGET(s->q##_menuitem));\ + } + +#define SET_SUBMENU(q, r)\ + r->q##_submenu = nsgtk_menu_##q##_submenu(group);\ + if ((r->q##_submenu != NULL) && (r->q##_submenu->q##_menu != NULL) && \ + (r->q##_menuitem != NULL)) {\ + gtk_menu_item_set_submenu(GTK_MENU_ITEM(r->q##_menuitem),\ + GTK_WIDGET(r->q##_submenu->q##_menu));\ + } + +#define ADD_SEP(q, r)\ + w = gtk_separator_menu_item_new();\ + if ((w != NULL) && (r->q##_menu != NULL)) {\ + gtk_menu_shell_append(GTK_MENU_SHELL(r->q##_menu), w);\ + gtk_widget_show(w);\ + } + +/** + * creates the a file menu + * \param group the 'global' in a gtk sense accelerator reference + */ +struct nsgtk_file_menu *nsgtk_menu_file_menu(GtkAccelGroup *group) +{ + GtkWidget *w; + struct nsgtk_file_menu *ret = malloc(sizeof(struct nsgtk_file_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->file_menu = GTK_MENU(gtk_menu_new()); + if (ret->file_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(file, newwindow, gtkNewWindow, ret, group) + IMAGE_ITEM(file, newtab, gtkNewTab, ret, group) + IMAGE_ITEM(file, openfile, gtkOpenFile, ret, group) + IMAGE_ITEM(file, closewindow, gtkCloseWindow, ret, group) + ADD_SEP(file, ret) + IMAGE_ITEM(file, savepage, gtkSavePage, ret, group) + IMAGE_ITEM(file, export, gtkExport, ret, group) + ADD_SEP(file, ret) + IMAGE_ITEM(file, printpreview, gtkPrintPreview, ret, group) + IMAGE_ITEM(file, print, gtkPrint, ret, group) + ADD_SEP(file, ret) + IMAGE_ITEM(file, quit, gtkQuitMenu, ret, group) + SET_SUBMENU(export, ret) + return ret; +} + +/** +* creates an edit menu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_edit_menu *nsgtk_menu_edit_menu(GtkAccelGroup *group) +{ + GtkWidget *w; + struct nsgtk_edit_menu *ret = malloc(sizeof(struct nsgtk_edit_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->edit_menu = GTK_MENU(gtk_menu_new()); + if (ret->edit_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(edit, cut, gtkCut, ret, group) + IMAGE_ITEM(edit, copy, gtkCopy, ret, group) + IMAGE_ITEM(edit, paste, gtkPaste, ret, group) + IMAGE_ITEM(edit, delete, gtkDelete, ret, group) + ADD_SEP(edit, ret) + IMAGE_ITEM(edit, selectall, gtkSelectAll, ret, group) + ADD_SEP(edit, ret) + IMAGE_ITEM(edit, find, gtkFind, ret, group) + ADD_SEP(edit, ret) + IMAGE_ITEM(edit, preferences, gtkPreferences, ret, group) + return ret; +} + +/** +* creates a view menu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_view_menu *nsgtk_menu_view_menu(GtkAccelGroup *group) +{ + GtkWidget *w; + struct nsgtk_view_menu *ret = malloc(sizeof(struct nsgtk_view_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->view_menu = GTK_MENU(gtk_menu_new()); + if (ret->view_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(view, stop, gtkStop, ret, group) + IMAGE_ITEM(view, reload, gtkReload, ret, group) + ADD_SEP(view, ret) + IMAGE_ITEM(view, scaleview, gtkScaleView, ret, group) + IMAGE_ITEM(view, fullscreen, gtkFullScreen, ret, group) + IMAGE_ITEM(view, viewsource, gtkViewSource, ret, group) + ADD_SEP(view, ret) + IMAGE_ITEM(view, images, gtkImages, ret, group) + IMAGE_ITEM(view, toolbars, gtkToolbars, ret, group) + ADD_SEP(view, ret) + IMAGE_ITEM(view, downloads, gtkDownloads, ret, group) + IMAGE_ITEM(view, savewindowsize, gtkSaveWindowSize, ret, group) + IMAGE_ITEM(view, debugging, gtkDebugging, ret, group) + SET_SUBMENU(scaleview, ret) + SET_SUBMENU(images, ret) + SET_SUBMENU(toolbars, ret) + SET_SUBMENU(debugging, ret) + return ret; +} + +/** +* creates a nav menu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group) +{ + GtkWidget *w; + struct nsgtk_nav_menu *ret = malloc(sizeof(struct nsgtk_nav_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->nav_menu = GTK_MENU(gtk_menu_new()); + if (ret->nav_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(nav, back, gtkBack, ret, group) + IMAGE_ITEM(nav, forward, gtkForward, ret, group) + IMAGE_ITEM(nav, home, gtkHome, ret, group) + ADD_SEP(nav, ret) + IMAGE_ITEM(nav, localhistory, gtkLocalHistory, ret, group) + IMAGE_ITEM(nav, globalhistory, gtkGlobalHistory, ret, group) + ADD_SEP(nav, ret) + IMAGE_ITEM(nav, addbookmarks, gtkAddBookMarks, ret, group) + IMAGE_ITEM(nav, showbookmarks, gtkShowBookMarks, ret, group) + ADD_SEP(nav, ret) + IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group) + return ret; +} + +/** +* creates a tabs menu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_tabs_menu *nsgtk_menu_tabs_menu(GtkAccelGroup *group) +{ + struct nsgtk_tabs_menu *ret = malloc(sizeof(struct nsgtk_tabs_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->tabs_menu = GTK_MENU(gtk_menu_new()); + if (ret->tabs_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(tabs, nexttab, gtkNextTab, ret, group) + IMAGE_ITEM(tabs, prevtab, gtkPrevTab, ret, group) + IMAGE_ITEM(tabs, closetab, gtkCloseTab, ret, group) + return ret; +} + +/** +* creates a help menu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_help_menu *nsgtk_menu_help_menu(GtkAccelGroup *group) +{ + GtkWidget *w; + struct nsgtk_help_menu *ret = malloc(sizeof(struct nsgtk_help_menu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->help_menu = GTK_MENU(gtk_menu_new()); + if (ret->help_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(help, contents, gtkContents, ret, group) + IMAGE_ITEM(help, guide, gtkGuide, ret, group) + IMAGE_ITEM(help, info, gtkUserInformation, ret, group) + ADD_SEP(help, ret) + IMAGE_ITEM(help, about, gtkAbout, ret, group) + return ret; +} + +/** +* creates an export submenu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *group) +{ + struct nsgtk_export_submenu *ret = malloc(sizeof(struct + nsgtk_export_submenu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->export_menu = GTK_MENU(gtk_menu_new()); + if (ret->export_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(export, plaintext, gtkPlainText, ret, group) + IMAGE_ITEM(export, drawfile, gtkDrawFile, ret, group) + IMAGE_ITEM(export, postscript, gtkPostScript, ret, group) + IMAGE_ITEM(export, pdf, gtkPDF, ret, group) + return ret; +} + +/** +* creates a scaleview submenu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu( + GtkAccelGroup *group) +{ + struct nsgtk_scaleview_submenu *ret = + malloc(sizeof(struct nsgtk_scaleview_submenu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->scaleview_menu = GTK_MENU(gtk_menu_new()); + if (ret->scaleview_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(scaleview, zoomplus, gtkZoomPlus, ret, group) + IMAGE_ITEM(scaleview, zoomnormal, gtkZoomNormal, ret, group) + IMAGE_ITEM(scaleview, zoomminus, gtkZoomMinus, ret, group) + return ret; +} + +/** +* creates an images submenu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *group) +{ + struct nsgtk_images_submenu *ret = + malloc(sizeof(struct nsgtk_images_submenu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->images_menu = GTK_MENU(gtk_menu_new()); + if (ret->images_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + CHECK_ITEM(images, foregroundimages, gtkForegroundImages, ret) + CHECK_ITEM(images, backgroundimages, gtkBackgroundImages, ret) + return ret; +} + +/** +* creates a toolbars submenu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu( + GtkAccelGroup *group) +{ + struct nsgtk_toolbars_submenu *ret = + malloc(sizeof(struct nsgtk_toolbars_submenu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->toolbars_menu = GTK_MENU(gtk_menu_new()); + if (ret->toolbars_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + CHECK_ITEM(toolbars, menubar, gtkMenuBar, ret) + if (ret->menubar_menuitem != NULL) + gtk_check_menu_item_set_active(ret->menubar_menuitem, TRUE); + CHECK_ITEM(toolbars, toolbar, gtkToolBar, ret) + if (ret->toolbar_menuitem != NULL) + gtk_check_menu_item_set_active(ret->toolbar_menuitem, TRUE); + CHECK_ITEM(toolbars, statusbar, gtkStatusBar, ret) + if (ret->statusbar_menuitem != NULL) + gtk_check_menu_item_set_active(ret->statusbar_menuitem, TRUE); + return ret; +} + +/** +* creates a debugging submenu +* \param group the 'global' in a gtk sense accelerator reference +*/ + +struct nsgtk_debugging_submenu *nsgtk_menu_debugging_submenu( + GtkAccelGroup *group) +{ + struct nsgtk_debugging_submenu *ret = + malloc(sizeof(struct nsgtk_debugging_submenu)); + if (ret == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + ret->debugging_menu = GTK_MENU(gtk_menu_new()); + if (ret->debugging_menu == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(ret); + return NULL; + } + IMAGE_ITEM(debugging, toggledebugging, gtkToggleDebugging, ret, group) + IMAGE_ITEM(debugging, saveboxtree, gtkSaveBoxTree, ret, group) + IMAGE_ITEM(debugging, savedomtree, gtkSaveDomTree, ret, group) + return ret; +} + +#undef CHECK_ITEM +#undef IMAGE_ITEM +#undef SET_SUBMENU +#undef ADD_SEP + diff --git a/gtk/gtk_menu.h b/gtk/gtk_menu.h new file mode 100644 index 000000000..77199604b --- /dev/null +++ b/gtk/gtk_menu.h @@ -0,0 +1,135 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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_MENU_H_ +#define _NETSURF_GTK_MENU_H_ + +#include <gtk/gtk.h> + +struct nsgtk_file_menu { + GtkMenu *file_menu; + GtkImageMenuItem *newwindow_menuitem; + GtkImageMenuItem *newtab_menuitem; + GtkImageMenuItem *openfile_menuitem; + GtkImageMenuItem *closewindow_menuitem; + GtkImageMenuItem *savepage_menuitem; + GtkImageMenuItem *export_menuitem; + struct nsgtk_export_submenu *export_submenu; + GtkImageMenuItem *printpreview_menuitem; + GtkImageMenuItem *print_menuitem; + GtkImageMenuItem *quit_menuitem; +}; + +struct nsgtk_edit_menu { + GtkMenu *edit_menu; + GtkImageMenuItem *cut_menuitem; + GtkImageMenuItem *copy_menuitem; + GtkImageMenuItem *paste_menuitem; + GtkImageMenuItem *delete_menuitem; + GtkImageMenuItem *selectall_menuitem; + GtkImageMenuItem *find_menuitem; + GtkImageMenuItem *preferences_menuitem; +}; + +struct nsgtk_view_menu { + GtkMenu *view_menu; + GtkImageMenuItem *stop_menuitem; + GtkImageMenuItem *reload_menuitem; + GtkImageMenuItem *scaleview_menuitem; + struct nsgtk_scaleview_submenu *scaleview_submenu; + GtkImageMenuItem *fullscreen_menuitem; + GtkImageMenuItem *viewsource_menuitem; + GtkImageMenuItem *images_menuitem; + struct nsgtk_images_submenu *images_submenu; + GtkImageMenuItem *toolbars_menuitem; + struct nsgtk_toolbars_submenu *toolbars_submenu; + GtkImageMenuItem *downloads_menuitem; + GtkImageMenuItem *savewindowsize_menuitem; + GtkImageMenuItem *debugging_menuitem; + struct nsgtk_debugging_submenu *debugging_submenu; +}; + +struct nsgtk_nav_menu { + GtkMenu *nav_menu; + GtkImageMenuItem *back_menuitem; + GtkImageMenuItem *forward_menuitem; + GtkImageMenuItem *home_menuitem; + GtkImageMenuItem *localhistory_menuitem; + GtkImageMenuItem *globalhistory_menuitem; + GtkImageMenuItem *addbookmarks_menuitem; + GtkImageMenuItem *showbookmarks_menuitem; + GtkImageMenuItem *openlocation_menuitem; +}; + +struct nsgtk_tabs_menu { + GtkMenu *tabs_menu; + GtkImageMenuItem *nexttab_menuitem; + GtkImageMenuItem *prevtab_menuitem; + GtkImageMenuItem *closetab_menuitem; +}; + +struct nsgtk_help_menu { + GtkMenu *help_menu; + GtkImageMenuItem *contents_menuitem; + GtkImageMenuItem *guide_menuitem; + GtkImageMenuItem *info_menuitem; + GtkImageMenuItem *about_menuitem; +}; + +struct nsgtk_export_submenu { + GtkMenu *export_menu; + GtkImageMenuItem *plaintext_menuitem; + GtkImageMenuItem *drawfile_menuitem; + GtkImageMenuItem *postscript_menuitem; + GtkImageMenuItem *pdf_menuitem; +}; + +struct nsgtk_scaleview_submenu { + GtkMenu *scaleview_menu; + GtkImageMenuItem *zoomplus_menuitem; + GtkImageMenuItem *zoomminus_menuitem; + GtkImageMenuItem *zoomnormal_menuitem; +}; + +struct nsgtk_images_submenu { + GtkMenu *images_menu; + GtkCheckMenuItem *foregroundimages_menuitem; + GtkCheckMenuItem *backgroundimages_menuitem; +}; + +struct nsgtk_toolbars_submenu { + GtkMenu *toolbars_menu; + GtkCheckMenuItem *menubar_menuitem; + GtkCheckMenuItem *toolbar_menuitem; + GtkCheckMenuItem *statusbar_menuitem; +}; + +struct nsgtk_debugging_submenu { + GtkMenu *debugging_menu; + GtkImageMenuItem *toggledebugging_menuitem; + GtkImageMenuItem *saveboxtree_menuitem; + GtkImageMenuItem *savedomtree_menuitem; +}; + +struct nsgtk_file_menu *nsgtk_menu_file_menu(GtkAccelGroup *group); +struct nsgtk_edit_menu *nsgtk_menu_edit_menu(GtkAccelGroup *group); +struct nsgtk_view_menu *nsgtk_menu_view_menu(GtkAccelGroup *group); +struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group); +struct nsgtk_tabs_menu *nsgtk_menu_tabs_menu(GtkAccelGroup *group); +struct nsgtk_help_menu *nsgtk_menu_help_menu(GtkAccelGroup *group); + +#endif diff --git a/gtk/gtk_save.c b/gtk/gtk_save.c new file mode 100644 index 000000000..fc03499ea --- /dev/null +++ b/gtk/gtk_save.c @@ -0,0 +1,81 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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/>. + */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <libxml/HTMLtree.h> +#include "content/content.h" +#include "desktop/save_complete.h" +#include "utils/utils.h" + +/** +* conducts the filesystem save appropriate to the gui +* \param path save path +* \param filename name of file to save +* \param len data length +* \param sourcedata pointer to data to save +* \param type content type +* \return true for success +*/ + +bool save_complete_gui_save(const char *path, const char *filename, + size_t len, const char *sourcedata, content_type type) +{ + int res; + int namelen; + namelen = strlen(path) + strlen(filename) + 2; /* '/', '\0' */ + char *fullpath = malloc(namelen); + if (!fullpath) { + warn_user("NoMemory", 0); + return false; + } + snprintf(fullpath, namelen, "%s/%s", path, filename); + FILE *f; + f = fopen(fullpath, "wb"); + free(fullpath); + if (f == NULL) + return false; + res = fwrite(sourcedata, len, 1, f); + fclose(f); + if (res != 1) + return false; + return true; +} + +/** +* wrapper for lib function htmlSaveFileFormat; front sets path from path +* + filename in a filesystem-specific way +*/ + +int save_complete_htmlSaveFileFormat(const char *path, const char *filename, + xmlDocPtr cur, const char *encoding, int format) +{ + int ret; + int len = strlen(path) + strlen(filename) + 2; + char *fullpath = malloc(len); + if (fullpath == NULL) { + warn_user("NoMemory", 0); + return -1; + } + snprintf(fullpath, len, "%s/%s", path, filename); + ret = htmlSaveFileFormat(fullpath, cur, encoding, format); + free(fullpath); + return ret; +} + diff --git a/gtk/gtk_scaffolding.c b/gtk/gtk_scaffolding.c index 942587c54..01eb2d4e6 100644 --- a/gtk/gtk_scaffolding.c +++ b/gtk/gtk_scaffolding.c @@ -1,5 +1,6 @@ /* * Copyright 2006 Rob Kendrick <rjek@rjek.com> + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -17,12 +18,16 @@ */ #include <assert.h> +#include <dirent.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include <gtk/gtk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> #include <libxml/debugXML.h> +#include "gtk/gtk_scaffolding.h" #include "content/content.h" #include "css/utils.h" #include "desktop/browser.h" @@ -32,27 +37,37 @@ #include "desktop/options.h" #include "desktop/plotters.h" #include "desktop/print.h" +#include "desktop/save_complete.h" #ifdef WITH_PDF_EXPORT #include "desktop/save_pdf/font_haru.h" #include "desktop/save_pdf/pdf_plotters.h" #endif +#include "desktop/save_text.h" +#include "desktop/search.h" +#include "desktop/searchweb.h" #include "desktop/selection.h" #include "desktop/textinput.h" #include "gtk/gtk_completion.h" #include "gtk/dialogs/gtk_options.h" #include "gtk/dialogs/gtk_about.h" #include "gtk/dialogs/gtk_source.h" +#include "gtk/gtk_bitmap.h" #include "gtk/gtk_download.h" #include "gtk/gtk_gui.h" #include "gtk/gtk_history.h" +#include "gtk/gtk_menu.h" #include "gtk/gtk_plotters.h" #include "gtk/gtk_print.h" -#include "gtk/gtk_scaffolding.h" #include "gtk/gtk_schedule.h" +#include "gtk/gtk_search.h" #include "gtk/gtk_tabs.h" +#include "gtk/gtk_theme.h" #include "gtk/gtk_throbber.h" +#include "gtk/gtk_toolbar.h" #include "gtk/gtk_window.h" #include "gtk/options.h" +#include "gtk/sexy_icon_entry.h" +#include "image/ico.h" #include "render/box.h" #include "render/font.h" #include "render/form.h" @@ -63,50 +78,85 @@ #include "utils/log.h" -struct gtk_history_window; +struct gtk_scaffolding { + GtkWindow *window; + GtkNotebook *notebook; + GtkWidget *url_bar; + GtkEntryCompletion *url_bar_completion; + GtkStatusbar *status_bar; + struct nsgtk_file_menu *file_menu; + struct nsgtk_file_menu *rclick_file_menu; + struct nsgtk_edit_menu *edit_menu; + struct nsgtk_edit_menu *rclick_edit_menu; + struct nsgtk_view_menu *view_menu; + struct nsgtk_view_menu *rclick_view_menu; + struct nsgtk_nav_menu *nav_menu; + struct nsgtk_nav_menu *rclick_nav_menu; + struct nsgtk_tabs_menu *tabs_menu; + struct nsgtk_tabs_menu *rclick_tabs_menu; + struct nsgtk_help_menu *help_menu; + struct nsgtk_help_menu *rclick_help_menu; + GtkMenuItem *edit_menu_item; + GtkMenuItem *tabs_menu_item; + GtkToolbar *tool_bar; + struct nsgtk_button_connect *buttons[PLACEHOLDER_BUTTON]; + GtkMenuBar *menu_bar; + GtkImage *throbber; + GtkImage *icoFav; + struct gtk_search *search; + GtkImage *webSearchIco; + GtkWidget *webSearchEntry; + GtkPaned *status_pane; + + int offset; + int toolbarmem; + int toolbarbase; + int historybase; + + GladeXML *xml; -struct gtk_history_window { - struct gtk_scaffolding *g; - GtkWindow *window; - GtkScrolledWindow *scrolled; - GtkDrawingArea *drawing_area; -}; + GladeXML *popup_xml; + GtkMenu *popup_menu; + + struct gtk_history_window *history_window; + GtkDialog *preferences_dialog; + + int throb_frame; + struct gui_window *top_level; + int being_destroyed; -struct menu_events { - const char *widget; - GCallback handler; + bool fullscreen; + + /* keep global linked list for gui interface adjustments */ + struct gtk_scaffolding *next, *prev; }; static int open_windows = 0; /**< current number of open browsers */ static struct gtk_scaffolding *current_model; /**< current window for model - dialogue use */ + dialogue use */ +nsgtk_scaffolding *scaf_list = NULL; /**< global list for interface changes */ static struct box *current_menu_link_box; /**< pointer to the box containing a link under the mouse, or 0 if none */ -static gboolean nsgtk_window_delete_event(GtkWidget *, gpointer); -static void nsgtk_window_destroy_event(GtkWidget *, gpointer); +static gboolean nsgtk_window_delete_event(GtkWidget *, GdkEvent *, gpointer); +static void nsgtk_window_close(struct gtk_scaffolding *g); static void nsgtk_window_update_back_forward(struct gtk_scaffolding *); static void nsgtk_throb(void *); +static gboolean nsgtk_filter_directory(const GtkFileFilterInfo *info, + gpointer data); static gboolean nsgtk_window_edit_menu_clicked(GtkWidget *widget, struct gtk_scaffolding *g); static gboolean nsgtk_window_edit_menu_hidden(GtkWidget *widget, struct gtk_scaffolding *g); static gboolean nsgtk_window_popup_menu_hidden(GtkWidget *widget, struct gtk_scaffolding *g); -static gboolean nsgtk_window_back_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_history_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_forward_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_stop_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_reload_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_home_button_clicked(GtkWidget *, gpointer); -static gboolean nsgtk_window_url_activate_event(GtkWidget *, gpointer); -static gboolean nsgtk_window_url_changed(GtkWidget *, GdkEventKey *, gpointer); - +static gboolean nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar, gint x, + gint y, gint button, gpointer data); static guint nsgtk_scaffolding_update_link_operations_sensitivity( struct gtk_scaffolding *g, GladeXML *xml, gdouble x, gdouble y, gboolean hide); static guint nsgtk_scaffolding_update_edit_actions_sensitivity( - struct gtk_scaffolding *g, GladeXML *xml, gboolean hide); + struct gtk_scaffolding *g, GladeXML *xml, bool hide); static void nsgtk_scaffolding_enable_link_operations_sensitivity( struct gtk_scaffolding *g, GladeXML *xml); static void nsgtk_scaffolding_enable_edit_actions_sensitivity( @@ -117,168 +167,69 @@ static gboolean nsgtk_history_expose_event(GtkWidget *, GdkEventExpose *, static gboolean nsgtk_history_button_press_event(GtkWidget *, GdkEventButton *, gpointer); -static void nsgtk_attach_menu_handlers(GladeXML *, gpointer); +static void nsgtk_attach_menu_handlers(struct gtk_scaffolding *); static void nsgtk_window_tabs_num_changed(GtkNotebook *notebook, GtkWidget *page, guint page_num, struct gtk_scaffolding *g); void nsgtk_openfile_open(const char *filename); -#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) } -#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \ - GtkMenuItem *widget, gpointer g) -/* prototypes for menu handlers */ -/* file menu */ -MENUPROTO(new_window); -MENUPROTO(new_tab); -MENUPROTO(open_location); -MENUPROTO(open_file); -#ifdef WITH_PDF_EXPORT -MENUPROTO(export_pdf); -#endif -MENUPROTO(print); -MENUPROTO(close_window); -MENUPROTO(quit); - -/* edit menu */ -MENUPROTO(cut); -MENUPROTO(copy); -MENUPROTO(paste); -MENUPROTO(select_all); -MENUPROTO(preferences); - -/* view menu */ -MENUPROTO(stop); -MENUPROTO(reload); -MENUPROTO(zoom_in); -MENUPROTO(normal_size); -MENUPROTO(zoom_out); -MENUPROTO(full_screen); -MENUPROTO(view_source); -MENUPROTO(menu_bar); -MENUPROTO(tool_bar); -MENUPROTO(status_bar); -MENUPROTO(downloads); -MENUPROTO(save_window_size); -MENUPROTO(toggle_debug_rendering); -MENUPROTO(save_box_tree); -MENUPROTO(save_dom_tree); - -/* navigate menu */ -MENUPROTO(back); -MENUPROTO(forward); -MENUPROTO(home); -MENUPROTO(local_history); -MENUPROTO(global_history); - -/* tabs menu */ -MENUPROTO(next_tab); -MENUPROTO(prev_tab); -MENUPROTO(close_tab); - -/* help menu */ -MENUPROTO(about); - -/* Popup context menu (also shares edit menu handlers) */ -MENUPROTO(save_link); -MENUPROTO(open_link_in_focused_tab); -MENUPROTO(open_link_in_background_tab); - -/* structure used by nsgtk_attach_menu_handlers to connect menu items to - * their handling functions. - */ -static struct menu_events menu_events[] = { - /* file menu */ - MENUEVENT(new_window), - MENUEVENT(new_tab), - MENUEVENT(open_location), - MENUEVENT(open_file), -#ifdef WITH_PDF_EXPORT - MENUEVENT(export_pdf), -#endif - MENUEVENT(print), - MENUEVENT(close_window), - MENUEVENT(quit), - - /* edit menu */ - MENUEVENT(cut), - MENUEVENT(copy), - MENUEVENT(paste), - MENUEVENT(select_all), - MENUEVENT(preferences), - - /* view menu */ - MENUEVENT(stop), - MENUEVENT(reload), - MENUEVENT(zoom_in), - MENUEVENT(normal_size), - MENUEVENT(zoom_out), - MENUEVENT(full_screen), - MENUEVENT(view_source), - MENUEVENT(menu_bar), - MENUEVENT(tool_bar), - MENUEVENT(status_bar), - MENUEVENT(downloads), - MENUEVENT(save_window_size), - MENUEVENT(toggle_debug_rendering), - MENUEVENT(save_box_tree), - MENUEVENT(save_dom_tree), - - /* navigate menu */ - MENUEVENT(back), - MENUEVENT(forward), - MENUEVENT(home), - MENUEVENT(local_history), - MENUEVENT(global_history), - - /* tab menu */ - MENUEVENT(next_tab), - MENUEVENT(prev_tab), - MENUEVENT(close_tab), - - /* help menu */ - MENUEVENT(about), - - /* sentinel */ - { NULL, NULL } -}; - -void nsgtk_attach_menu_handlers(GladeXML *xml, gpointer g) +void nsgtk_attach_menu_handlers(struct gtk_scaffolding *g) { - struct menu_events *event = menu_events; - - while (event->widget != NULL) - { - GtkWidget *w = glade_xml_get_widget(xml, event->widget); - g_signal_connect(G_OBJECT(w), "activate", event->handler, g); - event++; + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + if (g->buttons[i]->main != NULL) { + g_signal_connect(g->buttons[i]->main, "activate", + G_CALLBACK(g->buttons[i]->mhandler), g); + } + if (g->buttons[i]->rclick != NULL) { + g_signal_connect(g->buttons[i]->rclick, "activate", + G_CALLBACK(g->buttons[i]->mhandler), g); + } + if (g->buttons[i]->popup != NULL) { + g_signal_connect(g->buttons[i]->popup, "activate", + G_CALLBACK(g->buttons[i]->mhandler), g); + } } -} +#define CONNECT_CHECK(q)\ + g_signal_connect(g->view_menu->toolbars_submenu->q##_menuitem,\ + "toggled", G_CALLBACK(nsgtk_on_##q##_activate), g);\ + g_signal_connect(g->rclick_view_menu->toolbars_submenu->q##_menuitem,\ + "toggled", G_CALLBACK(nsgtk_on_##q##_activate), g) + CONNECT_CHECK(menubar); + CONNECT_CHECK(toolbar); + CONNECT_CHECK(statusbar); +#undef CONNECT_CHECK -GtkWindow *nsgtk_get_window_for_scaffold(struct gtk_scaffolding *g) -{ - return g->window; } /* event handlers and support functions for them */ -gboolean nsgtk_window_delete_event(GtkWidget *widget, gpointer data) +gboolean nsgtk_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer + data) { - struct gtk_scaffolding *g = data; - gtk_widget_destroy(GTK_WIDGET(g->window)); - if (open_windows == 1 && nsgtk_check_for_downloads(GTK_WINDOW(widget))) - return TRUE; - else - return FALSE; + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + if (open_windows != 1 || nsgtk_check_for_downloads(GTK_WINDOW( + widget)) == false) { + nsgtk_window_close(g); + gtk_widget_destroy(GTK_WIDGET(g->window)); + } + return TRUE; } -void nsgtk_window_destroy_event(GtkWidget *widget, gpointer data) +/** + * cleanup function + */ +void nsgtk_window_close(struct gtk_scaffolding *g) { - struct gtk_scaffolding *g = data; + /* close all tabs first */ + gint numbertabs = gtk_notebook_get_n_pages(g->notebook); + while (numbertabs-- > 1) { + nsgtk_tab_close_current(g->notebook); + } LOG(("Being Destroyed = %d", g->being_destroyed)); - if (g->history_window->window) { + + if ((g->history_window) && (g->history_window->window)) { gtk_widget_destroy(GTK_WIDGET(g->history_window->window)); } - gtk_widget_destroy(GTK_WIDGET(g->window)); - + if (--open_windows == 0) netsurf_quit = true; @@ -286,37 +237,37 @@ void nsgtk_window_destroy_event(GtkWidget *widget, gpointer data) g->being_destroyed = 1; nsgtk_window_destroy_browser(g->top_level); } + if (g->prev != NULL) + g->prev->next = g->next; + else + scaf_list = g->next; + + if (g->next != NULL) + g->next->prev = g->prev; + } -void nsgtk_scaffolding_destroy(nsgtk_scaffolding *scaffold) +void nsgtk_scaffolding_destroy(nsgtk_scaffolding *g) { /* Our top_level has asked us to die */ - LOG(("Being Destroyed = %d", scaffold->being_destroyed)); - if (scaffold->being_destroyed) return; - scaffold->being_destroyed = 1; - nsgtk_window_destroy_event(0, scaffold); + LOG(("Being Destroyed = %d", g->being_destroyed)); + if (g->being_destroyed) return; + g->being_destroyed = 1; + nsgtk_window_close(g); } void nsgtk_window_update_back_forward(struct gtk_scaffolding *g) { int width, height; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - gtk_widget_set_sensitive(GTK_WIDGET(g->back_button), - history_back_available(bw->history)); - gtk_widget_set_sensitive(GTK_WIDGET(g->forward_button), - history_forward_available(bw->history)); - - gtk_widget_set_sensitive(GTK_WIDGET(g->back_menu), - history_back_available(bw->history)); - gtk_widget_set_sensitive(GTK_WIDGET(g->forward_menu), - history_forward_available(bw->history)); - gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(g->popup_xml, - "popupBack")), history_back_available(bw->history)); - gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(g->popup_xml, - "popupForward")), - history_forward_available(bw->history)); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + + g->buttons[BACK_BUTTON]->sensitivity = + history_back_available(bw->history); + g->buttons[FORWARD_BUTTON]->sensitivity = history_forward_available( + bw->history); + + nsgtk_scaffolding_set_sensitivity(g); /* update the url bar, particularly necessary when tabbing */ if (bw->current_content != NULL && bw->current_content->url != NULL) @@ -351,7 +302,7 @@ void nsgtk_throb(void *p) static gboolean nsgtk_window_edit_menu_clicked(GtkWidget *widget, struct gtk_scaffolding *g) { - nsgtk_scaffolding_update_edit_actions_sensitivity (g, g->xml, FALSE); + nsgtk_scaffolding_update_edit_actions_sensitivity(g, g->xml, false); return TRUE; } @@ -371,97 +322,20 @@ static gboolean nsgtk_window_popup_menu_hidden(GtkWidget *widget, return TRUE; } -gboolean nsgtk_window_back_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *g = data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - if (!history_back_available(bw->history)) - return TRUE; - - history_back(bw, bw->history); - nsgtk_window_update_back_forward(g); - - return TRUE; -} - -/* TODO: add resize handling */ -gboolean nsgtk_window_history_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)data; - - /* if entries of the same url but different frag_ids have been added - * the history needs redrawing (what is done in the throbber code in - * other cases) - */ - nsgtk_window_update_back_forward(gw); - - gtk_window_set_default_size(gw->history_window->window, 500, 150); - gtk_window_set_position(gw->history_window->window, GTK_WIN_POS_MOUSE); - gtk_window_set_transient_for(gw->history_window->window, gw->window); - gtk_window_set_opacity(gw->history_window->window, 0.9); - gtk_widget_show(GTK_WIDGET(gw->history_window->window)); - gdk_window_raise(GTK_WIDGET(gw->history_window->window)->window); - - return TRUE; -} - -gboolean nsgtk_window_forward_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *g = data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - if (!history_forward_available(bw->history)) - return TRUE; - - history_forward(bw, bw->history); - nsgtk_window_update_back_forward(g); - - return TRUE; -} - -gboolean nsgtk_window_stop_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *g = data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - browser_window_stop(bw); - - return TRUE; -} - -gboolean nsgtk_window_reload_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *g = data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - browser_window_reload(bw, true); - - return TRUE; -} - -gboolean nsgtk_window_home_button_clicked(GtkWidget *widget, gpointer data) -{ - struct gtk_scaffolding *g = data; - static const char *addr = NETSURF_HOMEPAGE; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - if (option_homepage_url != NULL && option_homepage_url[0] != '\0') - addr = option_homepage_url; - - browser_window_go(bw, addr, 0, true); - - return TRUE; -} - gboolean nsgtk_window_url_activate_event(GtkWidget *widget, gpointer data) { struct gtk_scaffolding *g = data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); - - browser_window_go(bw, gtk_entry_get_text(GTK_ENTRY(g->url_bar)), - 0, true); - + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + char *url; + if (search_is_url(gtk_entry_get_text(GTK_ENTRY(g->url_bar))) + == false) + url = search_web_from_term(gtk_entry_get_text(GTK_ENTRY( + g->url_bar))); + else + url = strdup(gtk_entry_get_text(GTK_ENTRY(g->url_bar))); + browser_window_go(bw, url, 0, true); + if (url != NULL) + free(url); return TRUE; } @@ -477,69 +351,107 @@ gboolean nsgtk_window_url_changed(GtkWidget *widget, GdkEventKey *event, return TRUE; } +gboolean nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar, gint x, gint y, + gint button, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + /* set visibility for right-click menu */ + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "sep2")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "save_link_popup")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, + "open_link_in_focused_tab_popup")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, + "open_link_in_background_tab_popup")); + gtk_widget_show(glade_xml_get_widget(g->popup_xml, "customize_popup")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "copy_popup")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "cut_popup")); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "paste_popup")); + gtk_menu_popup(g->popup_menu, NULL, NULL, NULL, NULL, 0, + gtk_get_current_event_time()); + return TRUE; +} void nsgtk_window_tabs_num_changed(GtkNotebook *notebook, GtkWidget *page, guint page_num, struct gtk_scaffolding *g) { gboolean visible = gtk_notebook_get_show_tabs(g->notebook); - g_object_set(g->tabs_menu, "visible", visible, NULL); + g_object_set(g->tabs_menu_item, "visible", visible, NULL); + g->buttons[NEXTTAB_BUTTON]->sensitivity = visible; + g->buttons[PREVTAB_BUTTON]->sensitivity = visible; + g->buttons[CLOSETAB_BUTTON]->sensitivity = visible; + nsgtk_scaffolding_set_sensitivity(g); } void nsgtk_openfile_open(const char *filename) { - struct browser_window *bw = nsgtk_get_browser_for_gui( + struct browser_window *bw = gui_window_get_browser_window( current_model->top_level); - char *url = malloc(strlen(filename) + sizeof("file://")); + char url[strlen(filename) + SLEN("file://") + 1]; sprintf(url, "file://%s", filename); browser_window_go(bw, url, 0, true); - free(url); } /* signal handlers for menu entries */ -#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \ - gpointer g) - -MENUHANDLER(new_window) -{ - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - const char *url = gtk_entry_get_text(GTK_ENTRY(gw->url_bar)); +#define MULTIHANDLER(q)\ +gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)\ +{\ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;\ + return nsgtk_on_##q##_activate(g);\ +}\ +gboolean nsgtk_on_##q##_activate_button(GtkButton *widget, gpointer data)\ +{\ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;\ + return nsgtk_on_##q##_activate(g);\ +}\ +gboolean nsgtk_on_##q##_activate(struct gtk_scaffolding *g) + +#define MENUHANDLER(q)\ +gboolean nsgtk_on_##q##_activate(GtkMenuItem *widget, gpointer data) + +#define BUTTONHANDLER(q)\ +gboolean nsgtk_on_##q##_activate(GtkButton *widget, gpointer data) + +MULTIHANDLER(newwindow) +{ + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + const char *url = gtk_entry_get_text(GTK_ENTRY(g->url_bar)); browser_window_create(url, bw, NULL, false, false); return TRUE; } -MENUHANDLER(new_tab) +MULTIHANDLER(newtab) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - const char *url = gtk_entry_get_text(GTK_ENTRY(gw->url_bar)); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + const char *url = gtk_entry_get_text(GTK_ENTRY(g->url_bar)); - if (option_new_blank) + if (option_new_blank) { browser_window_create(0, bw, NULL, false, true); - + GtkWidget *window = gtk_notebook_get_nth_page(g->notebook, -1); + gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &((GdkColor) + {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF})); + } + else browser_window_create(url, bw, NULL, false, true); return TRUE; } -MENUHANDLER(open_location) +MULTIHANDLER(open_location) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - - gtk_widget_grab_focus(GTK_WIDGET(gw->url_bar)); + gtk_widget_grab_focus(GTK_WIDGET(g->url_bar)); return TRUE; } -MENUHANDLER(open_file) +MULTIHANDLER(openfile) { - current_model = (struct gtk_scaffolding *)g; + current_model = g; GtkWidget *dlgOpen = gtk_file_chooser_dialog_new("Open File", current_model->window, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, -6, GTK_STOCK_OPEN, -5, NULL); @@ -558,12 +470,76 @@ MENUHANDLER(open_file) return TRUE; } -#ifdef WITH_PDF_EXPORT -MENUHANDLER(export_pdf) +MULTIHANDLER(savepage) +{ + if (gui_window_get_browser_window(g->top_level)->current_content + == NULL) + return FALSE; + + GtkWidget *fc = gtk_file_chooser_dialog_new( + messages_get("gtkcompleteSave"), g->window, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT, + NULL); + DIR *d; + char *path; + url_func_result res; + GtkFileFilter *filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "directory"); + gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + nsgtk_filter_directory, NULL, NULL); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fc), filter); + + res = url_nice(gui_window_get_browser_window( + g->top_level)->current_content->url, &path, false); + if (res != URL_FUNC_OK) { + path = strdup(messages_get("SaveText")); + if (path == NULL) { + warn_user("NoMemory", 0); + return FALSE; + } + } + + if (access(path, F_OK) != 0) + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), path); + free(path); + + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc), + TRUE); + + if (gtk_dialog_run(GTK_DIALOG(fc)) != GTK_RESPONSE_ACCEPT) + return TRUE; + path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc)); + d = opendir(path); + if (d == NULL) { + printf("d NULL\n"); + if (errno == ENOTDIR) + warn_user("NoDirError", path); + else + warn_user("gtkFileError", path); + g_free(path); + return TRUE; + } + closedir(d); + save_complete_init(); + save_complete(gui_window_get_browser_window( + g->top_level)->current_content, path); + g_free(path); + + gtk_widget_destroy(fc); + + return TRUE; +} + + +MULTIHANDLER(pdf) { +#ifdef WITH_PDF_EXPORT + GtkWidget *save_dialog; - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); struct print_settings *settings; char filename[PATH_MAX]; char dirname[PATH_MAX]; @@ -593,7 +569,7 @@ MENUHANDLER(export_pdf) used by the all-purpose print interface*/ haru_nsfont_set_scale((float)option_export_scale / 100); - save_dialog = gtk_file_chooser_dialog_new("Export to PDF", gw->window, + save_dialog = gtk_file_chooser_dialog_new("Export to PDF", g->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, @@ -625,14 +601,72 @@ MENUHANDLER(export_pdf) gtk_widget_destroy(save_dialog); +#endif /* WITH_PDF_EXPORT */ + return TRUE; } -#endif /* WITH_PDF_EXPORT */ -MENUHANDLER(print) +MULTIHANDLER(plaintext) +{ + if (gui_window_get_browser_window(g->top_level)->current_content + == NULL) + return FALSE; + + GtkWidget *fc = gtk_file_chooser_dialog_new( + messages_get("gtkplainSave"), g->window, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + char *filename; + url_func_result res; + + res = url_nice(gui_window_get_browser_window( + g->top_level)->current_content->url, &filename, false); + if (res != URL_FUNC_OK) { + filename = strdup(messages_get("SaveText")); + if (filename == NULL) { + warn_user("NoMemory", 0); + return FALSE; + } + } + + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), filename); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc), + TRUE); + + free(filename); + + if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc)); + save_as_text(gui_window_get_browser_window( + g->top_level)->current_content, filename); + g_free(filename); + } + + gtk_widget_destroy(fc); + return TRUE; +} + +MULTIHANDLER(drawfile) +{ + return TRUE; +} + +MULTIHANDLER(postscript) +{ + return TRUE; +} + +MULTIHANDLER(printpreview) +{ + return TRUE; +} + + +MULTIHANDLER(print) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); GtkPrintOperation *print_op; GtkPageSetup *page_setup; @@ -659,7 +693,7 @@ MENUHANDLER(print) content_to_print = bw->current_content; - page_setup = gtk_print_run_page_setup_dialog(gw->window, NULL, NULL); + page_setup = gtk_print_run_page_setup_dialog(g->window, NULL, NULL); if (page_setup == NULL) { warn_user(messages_get("NoMemory"), 0); g_object_unref(print_op); @@ -678,7 +712,7 @@ MENUHANDLER(print) if (bw->current_content->type != CONTENT_TEXTPLAIN) res = gtk_print_operation_run(print_op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, - gw->window, + g->window, NULL); /* if the settings were used save them for future use */ @@ -698,50 +732,46 @@ MENUHANDLER(print) return TRUE; } -MENUHANDLER(close_window) +MULTIHANDLER(closewindow) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - /* close all tabs first */ - gint numbertabs = gtk_notebook_get_n_pages(gw->notebook); + gint numbertabs = gtk_notebook_get_n_pages(g->notebook); while (numbertabs-- > 1) { - nsgtk_tab_close_current(gw->notebook); + nsgtk_tab_close_current(g->notebook); } - gtk_widget_destroy(GTK_WIDGET(gw->window)); - + nsgtk_window_close(g); + gtk_widget_destroy(GTK_WIDGET(g->window)); return TRUE; } -MENUHANDLER(quit) +MULTIHANDLER(quit) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - - if (nsgtk_check_for_downloads(gw->window) == false) + if (nsgtk_check_for_downloads(g->window) == false) netsurf_quit = true; return TRUE; } -MENUHANDLER(save_link) +MENUHANDLER(savelink) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct gui_window *gui = gw->top_level; - struct browser_window *bw = nsgtk_get_browser_for_gui(gui); - - if (!current_menu_link_box) - return FALSE; - - browser_window_download(bw, current_menu_link_box->href, - bw->current_content->url); + struct gtk_scaffolding *g = (struct gtk_scaffolding *) data; + struct gui_window *gui = g->top_level; + struct browser_window *bw = gui_window_get_browser_window(gui); + + if (!current_menu_link_box) + return FALSE; + + browser_window_download(bw, current_menu_link_box->href, + bw->current_content->url); - return TRUE; + return TRUE; } -MENUHANDLER(open_link_in_focused_tab) +MENUHANDLER(linkfocused) { + struct gtk_scaffolding *g = (struct gtk_scaffolding *) data; temp_open_background = 0; - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct gui_window *gui = gw->top_level; - struct browser_window *bw = nsgtk_get_browser_for_gui(gui); + struct gui_window *gui = g->top_level; + struct browser_window *bw = gui_window_get_browser_window(gui); if (current_menu_link_box == NULL) return FALSE; @@ -753,11 +783,11 @@ MENUHANDLER(open_link_in_focused_tab) return TRUE; } -MENUHANDLER(open_link_in_background_tab) +MENUHANDLER(linkbackground) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct gui_window *gui = gw->top_level; - struct browser_window *bw = nsgtk_get_browser_for_gui(gui); + struct gtk_scaffolding *g = (struct gtk_scaffolding *) data; + struct gui_window *gui = g->top_level; + struct browser_window *bw = gui_window_get_browser_window(gui); temp_open_background = 1; @@ -772,41 +802,38 @@ MENUHANDLER(open_link_in_background_tab) } -MENUHANDLER(cut) +MULTIHANDLER(cut) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - GtkWidget *focused = gtk_window_get_focus(gw->window); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + GtkWidget *focused = gtk_window_get_focus(g->window); /* If the url bar has focus, let gtk handle it */ if (GTK_IS_EDITABLE (focused)) - gtk_editable_cut_clipboard (GTK_EDITABLE(gw->url_bar)); + gtk_editable_cut_clipboard (GTK_EDITABLE(g->url_bar)); else browser_window_key_press(bw, KEY_CUT_SELECTION); return TRUE; } -MENUHANDLER(copy) +MULTIHANDLER(copy) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - GtkWidget *focused = gtk_window_get_focus(gw->window); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + GtkWidget *focused = gtk_window_get_focus(g->window); /* If the url bar has focus, let gtk handle it */ if (GTK_IS_EDITABLE (focused)) - gtk_editable_copy_clipboard(GTK_EDITABLE(gw->url_bar)); + gtk_editable_copy_clipboard(GTK_EDITABLE(g->url_bar)); else gui_copy_to_clipboard(bw->sel); return TRUE; } -MENUHANDLER(paste) +MULTIHANDLER(paste) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct gui_window *gui = gw->top_level; - GtkWidget *focused = gtk_window_get_focus(gw->window); + struct gui_window *gui = g->top_level; + GtkWidget *focused = gtk_window_get_focus(g->window); /* If the url bar has focus, let gtk handle it */ if (GTK_IS_EDITABLE (focused)) @@ -817,14 +844,25 @@ MENUHANDLER(paste) return TRUE; } -MENUHANDLER(select_all) +MULTIHANDLER(delete) +{ + return TRUE; +} + +MENUHANDLER(customize) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + nsgtk_toolbar_customization_init(g); + return TRUE; +} + +MULTIHANDLER(selectall) +{ + struct browser_window *bw = gui_window_get_browser_window(g->top_level); - if (GTK_WIDGET_HAS_FOCUS(gw->url_bar)) { + if (GTK_WIDGET_HAS_FOCUS(g->url_bar)) { LOG(("Selecting all URL bar text")); - gtk_editable_select_region(GTK_EDITABLE(gw->url_bar), 0, -1); + gtk_editable_select_region(GTK_EDITABLE(g->url_bar), 0, -1); } else { LOG(("Selecting all document text")); selection_select_all(bw->sel); @@ -833,145 +871,213 @@ MENUHANDLER(select_all) return TRUE; } -MENUHANDLER(preferences) +MULTIHANDLER(find) +{ + nsgtk_scaffolding_toggle_search_bar_visibility(g); + return TRUE; +} + +MULTIHANDLER(preferences) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - if (gw->preferences_dialog == NULL) - gw->preferences_dialog = nsgtk_options_init(bw, gw->window); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + if (g->preferences_dialog == NULL) + g->preferences_dialog = nsgtk_options_init(bw, g->window); else - gtk_widget_show (GTK_WIDGET(gw->preferences_dialog)); + gtk_widget_show(GTK_WIDGET(g->preferences_dialog)); return TRUE; } -MENUHANDLER(zoom_in) +MULTIHANDLER(zoomplus) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - float old_scale = nsgtk_get_scale_for_gui(gw->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + float old_scale = nsgtk_get_scale_for_gui(g->top_level); browser_window_set_scale(bw, old_scale + 0.05, true); return TRUE; } -MENUHANDLER(normal_size) +MULTIHANDLER(zoomnormal) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); browser_window_set_scale(bw, 1.0, true); return TRUE; } -MENUHANDLER(zoom_out) +MULTIHANDLER(zoomminus) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - struct browser_window *bw = nsgtk_get_browser_for_gui(gw->top_level); - float old_scale = nsgtk_get_scale_for_gui(gw->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); + float old_scale = nsgtk_get_scale_for_gui(g->top_level); browser_window_set_scale(bw, old_scale - 0.05, true); return TRUE; } -MENUHANDLER(full_screen) +MULTIHANDLER(fullscreen) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - - if (gw->fullscreen) { - gtk_window_unfullscreen(gw->window); + if (g->fullscreen) { + gtk_window_unfullscreen(g->window); } else { - gtk_window_fullscreen(gw->window); + gtk_window_fullscreen(g->window); } - gw->fullscreen = !gw->fullscreen; + g->fullscreen = !g->fullscreen; return TRUE; } -MENUHANDLER(view_source) +MULTIHANDLER(viewsource) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - nsgtk_source_dialog_init(gw->window, - nsgtk_get_browser_for_gui(gw->top_level)); + nsgtk_source_dialog_init(g->window, + gui_window_get_browser_window(g->top_level)); return TRUE; } -MENUHANDLER(menu_bar) +MENUHANDLER(menubar) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - + GtkWidget *w; + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - gtk_widget_show(GTK_WIDGET(gw->menu_bar)); + /* need to synchronise menus as gtk grumbles when one menu + * is attached to both headers */ + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->menubar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->menubar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); - gtk_widget_show_all(GTK_WIDGET(gw->popup_menu)); - - GList *widgets = glade_xml_get_widget_prefix(gw->popup_xml, + gtk_widget_show(GTK_WIDGET(g->menu_bar)); + + gtk_widget_show_all(GTK_WIDGET(g->popup_menu)); + + GList *widgets = glade_xml_get_widget_prefix(g->popup_xml, "menupopup"); for (; widgets != NULL; widgets = widgets->next) gtk_widget_hide(GTK_WIDGET(widgets->data)); + } else { - gtk_widget_hide(GTK_WIDGET(gw->menu_bar)); + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->menubar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->menubar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); - gtk_widget_hide_all(GTK_WIDGET(gw->popup_menu)); - gtk_widget_show(GTK_WIDGET(gw->popup_menu)); + gtk_widget_hide(GTK_WIDGET(g->menu_bar)); - GList *widgets = glade_xml_get_widget_prefix(gw->popup_xml, + GList *widgets = glade_xml_get_widget_prefix(g->popup_xml, "menupopup"); for (; widgets != NULL; widgets = widgets->next) gtk_widget_show_all(GTK_WIDGET(widgets->data)); - } + } return TRUE; } -MENUHANDLER(tool_bar) +MENUHANDLER(toolbar) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - + GtkWidget *w; + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - gtk_widget_show(GTK_WIDGET(gw->tool_bar)); + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->toolbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->toolbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); + gtk_widget_show(GTK_WIDGET(g->tool_bar)); } else { - gtk_widget_hide(GTK_WIDGET(gw->tool_bar)); + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->toolbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->toolbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); + gtk_widget_hide(GTK_WIDGET(g->tool_bar)); } return TRUE; } -MENUHANDLER(status_bar) +MENUHANDLER(statusbar) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - + GtkWidget *w; + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - gtk_widget_show(GTK_WIDGET(gw->status_bar)); + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->statusbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->statusbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) + == FALSE) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + TRUE); + gtk_widget_show(GTK_WIDGET(g->status_bar)); } else { - gtk_widget_hide(GTK_WIDGET(gw->status_bar)); + w = GTK_WIDGET(g->rclick_view_menu-> + toolbars_submenu->statusbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); + w = GTK_WIDGET(g->view_menu-> + toolbars_submenu->statusbar_menuitem); + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + FALSE); + gtk_widget_hide(GTK_WIDGET(g->status_bar)); } return TRUE; } -MENUHANDLER(downloads) +MULTIHANDLER(downloads) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - nsgtk_download_show(gw->window); + nsgtk_download_show(g->window); return TRUE; } -MENUHANDLER(save_window_size) +MULTIHANDLER(savewindowsize) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - - option_toolbar_status_width = gtk_paned_get_position(gw->status_pane); - gtk_window_get_position(gw->window, &option_window_x, + if (GTK_IS_PANED(g->status_pane)) + option_toolbar_status_width = + gtk_paned_get_position(g->status_pane); + gtk_window_get_position(g->window, &option_window_x, &option_window_y); - gtk_window_get_size(gw->window, &option_window_width, + gtk_window_get_size(g->window, &option_window_width, &option_window_height); @@ -980,19 +1086,18 @@ MENUHANDLER(save_window_size) return TRUE; } -MENUHANDLER(toggle_debug_rendering) +MULTIHANDLER(toggledebugging) { html_redraw_debug = !html_redraw_debug; nsgtk_reflow_all_windows(); return TRUE; } -MENUHANDLER(save_box_tree) +MULTIHANDLER(saveboxtree) { GtkWidget *save_dialog; - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - save_dialog = gtk_file_chooser_dialog_new("Save File", gw->window, + save_dialog = gtk_file_chooser_dialog_new("Save File", g->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, @@ -1017,7 +1122,7 @@ MENUHANDLER(save_box_tree) "Unable to open file for writing."); } else { struct browser_window *bw; - bw = nsgtk_get_browser_window(gw->top_level); + bw = gui_window_get_browser_window(g->top_level); if (bw->current_content && bw->current_content->type == @@ -1038,12 +1143,11 @@ MENUHANDLER(save_box_tree) return TRUE; } -MENUHANDLER(save_dom_tree) +MULTIHANDLER(savedomtree) { GtkWidget *save_dialog; - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - save_dialog = gtk_file_chooser_dialog_new("Save File", gw->window, + save_dialog = gtk_file_chooser_dialog_new("Save File", g->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, @@ -1067,7 +1171,7 @@ MENUHANDLER(save_dom_tree) "Unable to open file for writing."); } else { struct browser_window *bw; - bw = nsgtk_get_browser_window(gw->top_level); + bw = gui_window_get_browser_window(g->top_level); if (bw->current_content && bw->current_content->type == @@ -1089,37 +1193,119 @@ MENUHANDLER(save_dom_tree) } -MENUHANDLER(stop) +MULTIHANDLER(stop) { - return nsgtk_window_stop_button_clicked(GTK_WIDGET(widget), g); + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + browser_window_stop(bw); + + return TRUE; } -MENUHANDLER(reload) +MULTIHANDLER(reload) { - return nsgtk_window_reload_button_clicked(GTK_WIDGET(widget), g); + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + /* clear potential search effects */ + + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); + + browser_window_reload(bw, true); + + return TRUE; } -MENUHANDLER(back) +MULTIHANDLER(back) { - return nsgtk_window_back_button_clicked(GTK_WIDGET(widget), g); + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + if (!history_back_available(bw->history)) + return TRUE; + + /* clear potential search effects */ + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); + + history_back(bw, bw->history); + nsgtk_window_update_back_forward(g); + + return TRUE; } -MENUHANDLER(forward) +MULTIHANDLER(forward) { - return nsgtk_window_forward_button_clicked(GTK_WIDGET(widget), g); + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + if (!history_forward_available(bw->history)) + return TRUE; + + /* clear potential search effects */ + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); + + history_forward(bw, bw->history); + nsgtk_window_update_back_forward(g); + + return TRUE; } -MENUHANDLER(home) +MULTIHANDLER(home) { - return nsgtk_window_home_button_clicked(GTK_WIDGET(widget), g); + static const char *addr = NETSURF_HOMEPAGE; + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + if (option_homepage_url != NULL && option_homepage_url[0] != '\0') + addr = option_homepage_url; + + browser_window_go(bw, addr, 0, true); + + return TRUE; } -MENUHANDLER(local_history) +MULTIHANDLER(localhistory) { - return nsgtk_window_history_button_clicked(GTK_WIDGET(widget), g); + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + + int x,y, width, height, mainwidth, mainheight, margin = 20; + /* if entries of the same url but different frag_ids have been added + * the history needs redrawing (what throbber code normally does) + */ + history_size(bw->history, &width, &height); + nsgtk_window_update_back_forward(g); + gtk_window_get_position(g->window, &x, &y); + gtk_window_get_size(g->window, &mainwidth, &mainheight); + width = (width + g->historybase + margin > mainwidth) ? + mainwidth - g->historybase : width + margin; + height = (height + g->toolbarbase + margin > mainheight) ? + mainheight - g->toolbarbase : height + margin; + gtk_window_set_default_size(g->history_window->window, width, height); + gtk_widget_set_size_request(GTK_WIDGET(g->history_window->window), + -1, -1); + gtk_window_resize(g->history_window->window, width, height); + gtk_window_set_transient_for(g->history_window->window, g->window); + gtk_window_set_opacity(g->history_window->window, 0.9); + gtk_widget_show(GTK_WIDGET(g->history_window->window)); + gtk_window_move(g->history_window->window, x + g->historybase, y + + g->toolbarbase); + gdk_window_raise(GTK_WIDGET(g->history_window->window)->window); + + return TRUE; } -MENUHANDLER(global_history) +MULTIHANDLER(globalhistory) { gtk_widget_show(GTK_WIDGET(wndHistory)); gdk_window_raise(GTK_WIDGET(wndHistory)->window); @@ -1127,49 +1313,89 @@ MENUHANDLER(global_history) return TRUE; } -MENUHANDLER(next_tab) +MULTIHANDLER(addbookmarks) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + return TRUE; +} - gtk_notebook_next_page(gw->notebook); - +MULTIHANDLER(showbookmarks) +{ return TRUE; } -MENUHANDLER(prev_tab) +MULTIHANDLER(openlocation) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + gtk_widget_grab_focus(GTK_WIDGET(g->url_bar)); + return TRUE; +} - gtk_notebook_prev_page(gw->notebook); +MULTIHANDLER(nexttab) +{ + gtk_notebook_next_page(g->notebook); return TRUE; } -MENUHANDLER(close_tab) +MULTIHANDLER(prevtab) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + gtk_notebook_prev_page(g->notebook); - nsgtk_tab_close_current(gw->notebook); + return TRUE; +} + +MULTIHANDLER(closetab) +{ + nsgtk_tab_close_current(g->notebook); return TRUE; } -MENUHANDLER(about) +MULTIHANDLER(contents) { - struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; - nsgtk_about_dialog_init(gw->window, - nsgtk_get_browser_for_gui(gw->top_level), + return TRUE; +} + +MULTIHANDLER(guide) +{ + return TRUE; +} + +MULTIHANDLER(info) +{ + return TRUE; +} + +MULTIHANDLER(about) +{ + nsgtk_about_dialog_init(g->window, + gui_window_get_browser_window(g->top_level), netsurf_version); return TRUE; } +BUTTONHANDLER(history) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + return nsgtk_on_localhistory_activate(g); +} + +gboolean nsgtk_filter_directory(const GtkFileFilterInfo *info, + gpointer data) +{ + DIR *d = opendir(info->filename); + if (d == NULL) + return FALSE; + closedir(d); + return TRUE; +} + /* signal handler functions for the local history window */ gboolean nsgtk_history_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer g) { struct gtk_history_window *hw = (struct gtk_history_window *)g; struct browser_window *bw = - nsgtk_get_browser_for_gui(hw->g->top_level); + gui_window_get_browser_window(hw->g->top_level); current_widget = widget; current_drawable = widget->window; @@ -1190,12 +1416,16 @@ gboolean nsgtk_history_expose_event(GtkWidget *widget, return FALSE; } +#undef MULTIHANDLER +#undef CHECKHANDLER +#undef BUTTONHANDLER + gboolean nsgtk_history_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer g) { struct gtk_history_window *hw = (struct gtk_history_window *)g; struct browser_window *bw = - nsgtk_get_browser_for_gui(hw->g->top_level); + gui_window_get_browser_window(hw->g->top_level); LOG(("X=%g, Y=%g", event->x, event->y)); @@ -1209,8 +1439,10 @@ gboolean nsgtk_history_button_press_event(GtkWidget *widget, nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) { - struct gtk_scaffolding *g = malloc(sizeof(*g)); - + struct gtk_scaffolding *g = malloc(sizeof(*g)); + char *searchname; + int i; + LOG(("Constructing a scaffold of %p for gui_window %p", g, toplevel)); g->top_level = toplevel; @@ -1220,29 +1452,78 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) /* load the window template from the glade xml file, and extract * widget references from it for later use. */ - g->xml = glade_xml_new(glade_file_location, "wndBrowser", NULL); + g->xml = glade_xml_new(glade_netsurf_file_location, + "wndBrowser", NULL); glade_xml_signal_autoconnect(g->xml); g->window = GTK_WINDOW(GET_WIDGET("wndBrowser")); g->notebook = GTK_NOTEBOOK(GET_WIDGET("notebook")); - g->url_bar = GTK_ENTRY(GET_WIDGET("URLBar")); g->menu_bar = GTK_MENU_BAR(GET_WIDGET("menubar")); g->status_bar = GTK_STATUSBAR(GET_WIDGET("statusbar")); - g->edit_menu = GTK_MENU_ITEM(GET_WIDGET("menuitem_edit")); - g->tabs_menu = GTK_MENU_ITEM(GET_WIDGET("menuitem_tabs")); g->tool_bar = GTK_TOOLBAR(GET_WIDGET("toolbar")); - g->back_button = GTK_TOOL_BUTTON(GET_WIDGET("toolBack")); - g->forward_button = GTK_TOOL_BUTTON(GET_WIDGET("toolForward")); - g->stop_button = GTK_TOOL_BUTTON(GET_WIDGET("toolStop")); - g->reload_button = GTK_TOOL_BUTTON(GET_WIDGET("toolReload")); - g->back_menu = GTK_MENU_ITEM(GET_WIDGET("back")); - g->history_button = GTK_TOOL_BUTTON(GET_WIDGET("toolHistory")); - g->forward_menu = GTK_MENU_ITEM(GET_WIDGET("forward")); - g->stop_menu = GTK_MENU_ITEM(GET_WIDGET("stop")); - g->reload_menu = GTK_MENU_ITEM(GET_WIDGET("reload")); - g->throbber = GTK_IMAGE(GET_WIDGET("throbber")); + + g->search = malloc(sizeof(struct gtk_search)); + if (g->search == NULL) { + warn_user("NoMemory", 0); + return NULL; + } + + g->search->bar = GTK_TOOLBAR(GET_WIDGET("searchbar")); + g->search->entry = GTK_ENTRY(GET_WIDGET("searchEntry")); + + g->search->buttons[0] = GTK_TOOL_BUTTON(GET_WIDGET("searchBackButton")); + g->search->buttons[1] = GTK_TOOL_BUTTON(GET_WIDGET( + "searchForwardButton")); + g->search->buttons[2] = GTK_TOOL_BUTTON(GET_WIDGET( + "closeSearchButton")); + g->search->checkAll = GTK_CHECK_BUTTON(GET_WIDGET("checkAllSearch")); + g->search->caseSens = GTK_CHECK_BUTTON(GET_WIDGET("caseSensButton")); + + GtkAccelGroup *group = gtk_accel_group_new(); + gtk_window_add_accel_group(g->window, group); + + + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + g->buttons[i] = malloc(sizeof(struct nsgtk_button_connect)); + if (g->buttons[i] == NULL) { + warn_user("NoMemory", 0); + return NULL; + } + g->buttons[i]->button = NULL; + g->buttons[i]->location = -1; + g->buttons[i]->sensitivity = true; + g->buttons[i]->main = NULL; + g->buttons[i]->rclick = NULL; + g->buttons[i]->popup = NULL; + g->buttons[i]->mhandler = NULL; + g->buttons[i]->bhandler = NULL; + g->buttons[i]->dataplus = NULL; + g->buttons[i]->dataminus = NULL; + } + /* here custom toolbutton adding code */ + g->offset = 0; + g->toolbarmem = 0; + g->toolbarbase = 0; + g->historybase = 0; + nsgtk_toolbar_customization_load(g); + nsgtk_toolbar_set_physical(g); +#define MAKE_MENUS(q)\ + g->q##_menu = nsgtk_menu_##q##_menu(group);\ + g->rclick_##q##_menu = nsgtk_menu_##q##_menu(group);\ + gtk_menu_item_set_submenu(GTK_MENU_ITEM(GET_WIDGET("menuitem_" #q)),\ + GTK_WIDGET(g->q##_menu->q##_menu));\ + gtk_menu_set_accel_group(g->q##_menu->q##_menu, group) + MAKE_MENUS(file); + MAKE_MENUS(edit); + MAKE_MENUS(view); + MAKE_MENUS(nav); + MAKE_MENUS(tabs); + MAKE_MENUS(help); +#undef MAKE_MENUS + g->edit_menu_item = GTK_MENU_ITEM(GET_WIDGET("menuitem_edit")); + g->tabs_menu_item = GTK_MENU_ITEM(GET_WIDGET("menuitem_tabs")); g->preferences_dialog = NULL; - + nscss_screen_dpi = FLTTOFIX(gdk_screen_get_resolution( gtk_widget_get_screen(GTK_WIDGET(g->window)))); LOG(("Set CSS DPI to %f", FIXTOFLT(nscss_screen_dpi))); @@ -1276,16 +1557,18 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) break; case GTK_TOOLBAR_BOTH: case GTK_TOOLBAR_BOTH_HORIZ: - option_button_type = 3; - break; + /* no labels in default configuration */ default: /* No system default, so use large icons */ option_button_type = 2; break; } } - + switch (option_button_type) { + /* case 0 is 'unset' [from fresh install / clearing options] + * see above */ + case 1: /* Small icons */ gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar), GTK_TOOLBAR_ICONS); @@ -1311,26 +1594,19 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) break; } + gtk_toolbar_set_show_arrow(g->tool_bar, TRUE); + gtk_widget_show_all(GTK_WIDGET(g->tool_bar)); nsgtk_tab_init(GTK_WIDGET(g->notebook)); - /* set the URL entry box to expand, as we can't do this from within - * glade because of the way it emulates toolbars. - */ - gtk_tool_item_set_expand(GTK_TOOL_ITEM(GET_WIDGET("toolURLBar")), - TRUE); - - /* disable toolbar buttons that make no sense initially. */ - gtk_widget_set_sensitive(GTK_WIDGET(g->back_button), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g->forward_button), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g->stop_button), FALSE); - + gtk_widget_set_size_request(GTK_WIDGET( + g->buttons[HISTORY_BUTTON]->button), 20, -1); + /* create the local history window to be associated with this browser */ g->history_window = malloc(sizeof(struct gtk_history_window)); g->history_window->g = g; g->history_window->window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); gtk_window_set_transient_for(g->history_window->window, g->window); - gtk_window_set_default_size(g->history_window->window, 400, 400); gtk_window_set_title(g->history_window->window, "NetSurf History"); gtk_window_set_type_hint(g->history_window->window, GDK_WINDOW_TYPE_HINT_UTILITY); @@ -1356,7 +1632,6 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) /* set up URL bar completion */ g->url_bar_completion = gtk_entry_completion_new(); - gtk_entry_set_completion(g->url_bar, g->url_bar_completion); gtk_entry_completion_set_match_func(g->url_bar_completion, nsgtk_completion_match, NULL, NULL); gtk_entry_completion_set_model(g->url_bar_completion, @@ -1370,8 +1645,8 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) NULL); /* set up the throbber. */ - gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[0]); g->throb_frame = 0; + #define CONNECT(obj, sig, callback, ptr) \ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) @@ -1379,8 +1654,8 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) /* connect history window signals to their handlers */ CONNECT(g->history_window->drawing_area, "expose_event", nsgtk_history_expose_event, g->history_window); -// CONNECT(g->history_window->drawing_area, "motion_notify_event", -// nsgtk_history_motion_notify_event, g->history_window); + /*CONNECT(g->history_window->drawing_area, "motion_notify_event", + nsgtk_history_motion_notify_event, g->history_window);*/ CONNECT(g->history_window->drawing_area, "button_press_event", nsgtk_history_button_press_event, g->history_window); CONNECT(g->history_window->window, "delete_event", @@ -1393,35 +1668,67 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) /* connect signals to handlers. */ CONNECT(g->window, "delete-event", nsgtk_window_delete_event, g); - CONNECT(g->window, "destroy", nsgtk_window_destroy_event, g); - /* toolbar, URL bar, and menu bar signal handlers */ - CONNECT(g->edit_menu, "show", nsgtk_window_edit_menu_clicked, g); - CONNECT(g->edit_menu, "hide", nsgtk_window_edit_menu_hidden, g); - CONNECT(g->back_button, "clicked", nsgtk_window_back_button_clicked, + /* toolbar URL bar menu bar search bar signal handlers */ + CONNECT(g->edit_menu_item, "show", nsgtk_window_edit_menu_clicked, g); + CONNECT(g->edit_menu_item, "hide", nsgtk_window_edit_menu_hidden, g); + CONNECT(g->search->buttons[1], "clicked", + nsgtk_search_forward_button_clicked, g); + CONNECT(g->search->buttons[0], "clicked", + nsgtk_search_back_button_clicked, g); + CONNECT(g->search->entry, "changed", nsgtk_search_entry_changed, g); + CONNECT(g->search->entry, "activate", nsgtk_search_entry_activate, g); + CONNECT(g->search->entry, "key-press-event", nsgtk_search_entry_key, g); + CONNECT(g->search->buttons[2], "clicked", + nsgtk_search_close_button_clicked, g); + CONNECT(g->search->caseSens, "toggled", nsgtk_search_entry_changed, g); - CONNECT(g->forward_button, "clicked", - nsgtk_window_forward_button_clicked, g); - CONNECT(g->history_button, "clicked", - nsgtk_window_history_button_clicked, g); - CONNECT(g->stop_button, "clicked", nsgtk_window_stop_button_clicked, - g); - CONNECT(g->reload_button, "clicked", - nsgtk_window_reload_button_clicked, g); - CONNECT(GET_WIDGET("toolHome"), "clicked", - nsgtk_window_home_button_clicked, g); - CONNECT(g->url_bar, "activate", nsgtk_window_url_activate_event, g); - CONNECT(g->url_bar, "changed", nsgtk_window_url_changed, g); + + CONNECT(g->tool_bar, "popup-context-menu", + nsgtk_window_tool_bar_clicked, g); + g->popup_xml = glade_xml_new(glade_netsurf_file_location, "menuPopup", NULL); /* set up the menu signal handlers */ - nsgtk_attach_menu_handlers(g->xml, g); + nsgtk_scaffolding_toolbar_init(g); + nsgtk_toolbar_connect_all(g); + nsgtk_attach_menu_handlers(g); + + /* prepare to set the web search ico */ + + /* init web search prefs from file */ + search_web_provider_details(option_search_provider); + + /* potentially retrieve ico */ + if (search_web_ico() == NULL) + search_web_retrieve_ico(false); + + /* set entry */ + searchname = search_web_provider_name(); + if (searchname != NULL) { + char searchcontent[strlen(searchname) + SLEN("Search ") + 1]; + sprintf(searchcontent, "Search %s", searchname); + nsgtk_scaffolding_set_websearch(g, searchcontent); + free(searchname); + } +#define POPUP_ATTACH(q) gtk_menu_item_set_submenu( \ + GTK_MENU_ITEM(glade_xml_get_widget(g->popup_xml,\ + "menupopup_" #q)), GTK_WIDGET(g->rclick_##q##_menu->q##_menu));\ + + POPUP_ATTACH(file); + POPUP_ATTACH(edit); + POPUP_ATTACH(view); + POPUP_ATTACH(nav); + POPUP_ATTACH(tabs); + POPUP_ATTACH(help); +#undef POPUP_ATTACH + nsgtk_scaffolding_initial_sensitivity(g); + g->being_destroyed = 0; g->fullscreen = false; /* create the popup version of the menu */ - g->popup_xml = glade_xml_new(glade_file_location, "menuPopup", NULL); g->popup_menu = GTK_MENU(glade_xml_get_widget(g->popup_xml, "menuPopup")); @@ -1430,54 +1737,50 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) * gtk_menu_shell_append (GTK_MENU_SHELL(g->popup_menu), * GTK_WIDGET(glade_xml_get_widget(g->xml, "back"))); */ CONNECT(g->popup_menu, "hide", nsgtk_window_popup_menu_hidden, g); - CONNECT(glade_xml_get_widget(g->popup_xml, "popupBack"), "activate", - nsgtk_window_back_button_clicked, g); - CONNECT(glade_xml_get_widget(g->popup_xml, "popupForward"),"activate", - nsgtk_window_forward_button_clicked, g); - CONNECT(glade_xml_get_widget(g->popup_xml, "popupReload"), "activate", - nsgtk_window_reload_button_clicked, g); + CONNECT(glade_xml_get_widget(g->popup_xml, "save_link_popup"), - "activate", nsgtk_on_save_link_activate, g); + "activate", nsgtk_on_savelink_activate, g); CONNECT(glade_xml_get_widget(g->popup_xml, - "open_link_in_focused_tab_popup"), - "activate", - nsgtk_on_open_link_in_focused_tab_activate, g); + "open_link_in_focused_tab_popup"), "activate", + nsgtk_on_linkfocused_activate, g); CONNECT(glade_xml_get_widget(g->popup_xml, - "open_link_in_background_tab_popup"), - "activate", - nsgtk_on_open_link_in_background_tab_activate, g); + "open_link_in_background_tab_popup"), "activate", + nsgtk_on_linkbackground_activate, g); CONNECT(glade_xml_get_widget(g->popup_xml, "cut_popup"), "activate", nsgtk_on_cut_activate, g); CONNECT(glade_xml_get_widget(g->popup_xml, "copy_popup"), "activate", nsgtk_on_copy_activate, g); - CONNECT(glade_xml_get_widget(g->popup_xml, "paste_popup"),"activate", - nsgtk_on_paste_activate, g); - -#define POPUP_ATTACH(x, y) gtk_menu_item_set_submenu( \ - GTK_MENU_ITEM(glade_xml_get_widget(g->popup_xml, x)),\ - GTK_WIDGET(glade_xml_get_widget(g->xml, y))) - - POPUP_ATTACH("menupopup_file", "menumain_file"); - POPUP_ATTACH("menupopup_edit", "menumain_edit"); - POPUP_ATTACH("menupopup_view", "menumain_view"); - POPUP_ATTACH("menupopup_navigate", "menumain_navigate"); - POPUP_ATTACH("menupopup_help", "menumain_help"); - -#undef POPUP_ATTACH + CONNECT(glade_xml_get_widget(g->popup_xml, "paste_popup"), "activate", + nsgtk_on_paste_activate, g); + CONNECT(glade_xml_get_widget(g->popup_xml, "customize_popup"), + "activate", nsgtk_on_customize_activate, g); /* hides redundant popup menu items */ GList *widgets = glade_xml_get_widget_prefix(g->popup_xml, "menupopup"); for (; widgets != NULL; widgets = widgets->next) gtk_widget_hide(GTK_WIDGET(widgets->data)); + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "customize_popup")); + + /* attach to the list */ + if (scaf_list) + scaf_list->prev = g; + g->next = scaf_list; + g->prev = NULL; + scaf_list = g; + + /* call functions that need access from the list */ + nsgtk_theme_init(); + nsgtk_theme_implement(g); - /* disable PDF-requiring menu items */ -#ifndef WITH_PDF_EXPORT - gtk_widget_set_sensitive(GET_WIDGET("export_pdf"), FALSE); -#endif - + /* set web search ico */ + if (search_web_ico() != NULL) + gui_window_set_search_ico(search_web_ico()); + /* finally, show the window. */ gtk_widget_show(GTK_WIDGET(g->window)); + LOG(("creation complete")); + return g; } @@ -1516,17 +1819,16 @@ void gui_window_set_url(struct gui_window *_g, const char *url) { struct gtk_scaffolding *g = nsgtk_get_scaffold(_g); if (g->top_level != _g) return; - gtk_entry_set_text(g->url_bar, url); - gtk_editable_set_position(GTK_EDITABLE(g->url_bar), -1); + gtk_entry_set_text(GTK_ENTRY(g->url_bar), url); + gtk_editable_set_position(GTK_EDITABLE(g->url_bar), -1); } void gui_window_start_throbber(struct gui_window* _g) { struct gtk_scaffolding *g = nsgtk_get_scaffold(_g); - gtk_widget_set_sensitive(GTK_WIDGET(g->stop_button), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(g->reload_button), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g->stop_menu), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(g->reload_menu), FALSE); + g->buttons[STOP_BUTTON]->sensitivity = true; + g->buttons[RELOAD_BUTTON]->sensitivity = false; + nsgtk_scaffolding_set_sensitivity(g); nsgtk_window_update_back_forward(g); @@ -1536,88 +1838,428 @@ void gui_window_start_throbber(struct gui_window* _g) void gui_window_stop_throbber(struct gui_window* _g) { struct gtk_scaffolding *g = nsgtk_get_scaffold(_g); - gtk_widget_set_sensitive(GTK_WIDGET(g->stop_button), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g->reload_button), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(g->stop_menu), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(g->reload_menu), TRUE); - + g->buttons[STOP_BUTTON]->sensitivity = false; + g->buttons[RELOAD_BUTTON]->sensitivity = true; nsgtk_window_update_back_forward(g); - schedule_remove(nsgtk_throb, g); + if ((g == NULL) || (g->throbber == NULL) || (nsgtk_throbber == NULL) || + (nsgtk_throbber->framedata == NULL) || + (nsgtk_throbber->framedata[0] == NULL)) + return; gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[0]); } -gboolean nsgtk_scaffolding_is_busy(struct gtk_scaffolding *scaffold) +/** + * set favicon + */ +void gui_window_set_icon(struct gui_window *_g, struct content *icon) +{ + struct gtk_scaffolding *g = nsgtk_get_scaffold(_g); + GtkImage *iconImage = NULL; + if (g->icoFav != NULL) + g_object_unref(g->icoFav); + if ((icon != NULL) && (icon->type == CONTENT_ICO)) { + nsico_set_bitmap_from_size(icon, 16, 16); + } + if ((icon != NULL) && (icon->bitmap != NULL)) { + GdkPixbuf *pb = gtk_bitmap_get_primary(icon->bitmap); + if ((pb != NULL) && (gdk_pixbuf_get_width(pb) > 0) && + (gdk_pixbuf_get_height(pb) > 0)) { + pb = gdk_pixbuf_scale_simple(pb, 16, 16, + GDK_INTERP_HYPER); + iconImage = GTK_IMAGE( + gtk_image_new_from_pixbuf(pb)); + } else { + iconImage = NULL; + } + } + if (iconImage == NULL) { + char imagepath[strlen(res_dir_location) + SLEN("html.png") + + 1]; + sprintf(imagepath, "%shtml.png", res_dir_location); + iconImage = GTK_IMAGE(gtk_image_new_from_file(imagepath)); + } + g->icoFav = iconImage; + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(g->url_bar), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(g->icoFav)); + gtk_widget_show_all(GTK_WIDGET(g->buttons[URL_BAR_ITEM]->button)); +} + +void gui_window_set_search_ico(struct content *ico) +{ + GdkPixbuf *pbico = NULL; + GtkImage *searchico = NULL; + nsgtk_scaffolding *current; + if (ico == NULL) + ico = search_web_ico(); + + if ((ico != NULL) && (ico->type == CONTENT_ICO)) { + nsico_set_bitmap_from_size(ico, 20, 20); + } + if ((ico != NULL) && (ico->bitmap != NULL)) { + pbico = gtk_bitmap_get_primary(ico->bitmap); + if ((pbico != NULL) && (gdk_pixbuf_get_width(pbico) > 0) && + (gdk_pixbuf_get_height(pbico) > 0)) { + pbico = gdk_pixbuf_scale_simple(pbico, 20, 20, + GDK_INTERP_HYPER); + current = scaf_list; + searchico = GTK_IMAGE( + gtk_image_new_from_pixbuf(pbico)); + } else { + searchico = NULL; + } + } + /* add ico to toolbar */ + current = scaf_list; + while (current) { + if (searchico != NULL) { + current->webSearchIco = searchico; + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY( + current->webSearchEntry), + SEXY_ICON_ENTRY_PRIMARY, + current->webSearchIco); + } + searchico = GTK_IMAGE(gtk_image_new_from_pixbuf(pbico)); + current = current->next; + } +} + +bool nsgtk_scaffolding_is_busy(nsgtk_scaffolding *g) { /* We are considered "busy" if the stop button is sensitive */ - return GTK_WIDGET_SENSITIVE((GTK_WIDGET(scaffold->stop_button))); + return g->buttons[STOP_BUTTON]->sensitivity; +} + +GtkWindow* nsgtk_scaffolding_window(nsgtk_scaffolding *g) +{ + return g->window; +} + +GtkNotebook* nsgtk_scaffolding_notebook(nsgtk_scaffolding *g) +{ + return g->notebook; +} + +GtkWidget *nsgtk_scaffolding_urlbar(nsgtk_scaffolding *g) +{ + return g->url_bar; +} + +GtkWidget *nsgtk_scaffolding_websearch(nsgtk_scaffolding *g) +{ + return g->webSearchEntry; +} + + +GtkToolbar *nsgtk_scaffolding_toolbar(nsgtk_scaffolding *g) +{ + return g->tool_bar; +} + +struct nsgtk_button_connect *nsgtk_scaffolding_button(nsgtk_scaffolding *g, + int i) +{ + return g->buttons[i]; +} + +struct gtk_search *nsgtk_scaffolding_search(nsgtk_scaffolding *g) +{ + return g->search; +} + +GtkMenuBar *nsgtk_scaffolding_menu_bar(nsgtk_scaffolding *g) +{ + return g->menu_bar; } -GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g) +struct gtk_history_window *nsgtk_scaffolding_history_window(nsgtk_scaffolding + *g) { - return g->scaffold->window; + return g->history_window; } -GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g) +nsgtk_scaffolding *nsgtk_scaffolding_iterate(nsgtk_scaffolding *g) { - return g->scaffold->notebook; + return g->next; +} + +void nsgtk_scaffolding_reset_offset(nsgtk_scaffolding *g) +{ + g->offset = 0; +} + +void nsgtk_scaffolding_update_url_bar_ref(nsgtk_scaffolding *g) +{ + g->url_bar = GTK_WIDGET(gtk_bin_get_child(GTK_BIN( + nsgtk_scaffolding_button(g, URL_BAR_ITEM)->button))); + g->icoFav = sexy_icon_entry_get_icon(SEXY_ICON_ENTRY(g->url_bar), + SEXY_ICON_ENTRY_PRIMARY); + + gtk_entry_set_completion(GTK_ENTRY(g->url_bar), + g->url_bar_completion); +} +void nsgtk_scaffolding_update_throbber_ref(nsgtk_scaffolding *g) +{ + g->throbber = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(gtk_bin_get_child( + GTK_BIN(g->buttons[THROBBER_ITEM]->button))))); +} + +void nsgtk_scaffolding_update_websearch_ref(nsgtk_scaffolding *g) +{ + g->webSearchEntry = gtk_bin_get_child(GTK_BIN( + g->buttons[WEBSEARCH_ITEM]->button)); + g->webSearchIco = sexy_icon_entry_get_icon(SEXY_ICON_ENTRY( + g->webSearchEntry), SEXY_ICON_ENTRY_PRIMARY); +} + +void nsgtk_scaffolding_set_websearch(nsgtk_scaffolding *g, const char *content) +{ + /* this code appears technically correct, though currently has no + * effect at all - tinkering encouraged */ + PangoLayout *lo = gtk_entry_get_layout(GTK_ENTRY(g->webSearchEntry)); + if (lo != NULL) { + pango_layout_set_font_description(lo, NULL); + PangoFontDescription *desc = pango_font_description_new(); + if (desc != NULL) { + pango_font_description_set_style(desc, + PANGO_STYLE_ITALIC); + pango_font_description_set_family(desc, "Arial"); + pango_font_description_set_weight(desc, + PANGO_WEIGHT_ULTRALIGHT); + pango_font_description_set_size(desc, + 10 * PANGO_SCALE); + pango_layout_set_font_description(lo, desc); + } + + PangoAttrList *list = pango_attr_list_new(); + if (list != NULL) { + PangoAttribute *italic = pango_attr_style_new( + PANGO_STYLE_ITALIC); + if (italic != NULL) { + italic->start_index = 0; + italic->end_index = strlen(content); + } + PangoAttribute *grey = pango_attr_foreground_new( + 0x7777, 0x7777, 0x7777); + if (grey != NULL) { + grey->start_index = 0; + grey->end_index = strlen(content); + } + pango_attr_list_insert(list, italic); + pango_attr_list_insert(list, grey); + pango_layout_set_attributes(lo, list); + pango_attr_list_unref(list); + } + pango_layout_set_text(lo, content, -1); + } +/* an alternative method */ +/* char *parse = malloc(strlen(content) + 1); + PangoAttrList *list = pango_layout_get_attributes(lo); + char *markup = g_strconcat("<span foreground='#777777'><i>", content, + "</i></span>", NULL); + pango_parse_markup(markup, -1, 0, &list, &parse, NULL, NULL); + gtk_widget_show_all(g->webSearchEntry); +*/ + gtk_entry_set_visibility(GTK_ENTRY(g->webSearchEntry), TRUE); + gtk_entry_set_text(GTK_ENTRY(g->webSearchEntry), content); +} + +void nsgtk_scaffolding_toggle_search_bar_visibility(nsgtk_scaffolding *g) +{ + gboolean vis; + struct browser_window *bw = + gui_window_get_browser_window(g->top_level); + g_object_get(G_OBJECT(g->search->bar), "visible", &vis, NULL); + if (vis) { + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); + gtk_widget_hide(GTK_WIDGET(g->search->bar)); + } else { + gtk_widget_show(GTK_WIDGET(g->search->bar)); + gtk_widget_grab_focus(GTK_WIDGET(g->search->entry)); + } +} + + +struct gui_window *nsgtk_scaffolding_top_level(nsgtk_scaffolding *g) +{ + return g->top_level; } void nsgtk_scaffolding_set_top_level (struct gui_window *gw) { - gw->scaffold->top_level = gw; + nsgtk_get_scaffold(gw)->top_level = gw; + struct browser_window *bw = gui_window_get_browser_window(gw); /* Synchronise the history (will also update the URL bar) */ - nsgtk_window_update_back_forward(gw->scaffold); - - /* Ensure the window's title bar is updated */ - if (gw->bw != NULL && gw->bw->current_content != NULL) { - if (gw->bw->current_content->title != NULL) { + nsgtk_window_update_back_forward(nsgtk_get_scaffold(gw)); + /* clear effects of potential searches */ + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); + + /* Ensure the window's title bar as well as favicon are updated */ + if (gui_window_get_browser_window(gw) != NULL && + gui_window_get_browser_window(gw)->current_content + != NULL) { + if (gui_window_get_browser_window(gw)->current_content->title + != NULL) { gui_window_set_title(gw, - gw->bw->current_content->title); + gui_window_get_browser_window(gw)-> + current_content->title); } else { - gui_window_set_title(gw, gw->bw->current_content->url); + gui_window_set_title(gw, + gui_window_get_browser_window(gw)-> + current_content->url); } + if (gui_window_get_browser_window(gw)->current_content->type + == CONTENT_HTML) + gui_window_set_icon(gw, + gui_window_get_browser_window(gw)-> + current_content->data.html.favicon); } } +void nsgtk_scaffolding_set_sensitivity(struct gtk_scaffolding *g) +{ +#define SENSITIVITY(q)\ + i = q##_BUTTON;\ + if (g->buttons[i]->main != NULL)\ + gtk_widget_set_sensitive(GTK_WIDGET(\ + g->buttons[i]->main),\ + g->buttons[i]->sensitivity);\ + if (g->buttons[i]->rclick != NULL)\ + gtk_widget_set_sensitive(GTK_WIDGET(\ + g->buttons[i]->rclick),\ + g->buttons[i]->sensitivity);\ + if ((g->buttons[i]->location != -1) && \ + (g->buttons[i]->button != NULL))\ + gtk_widget_set_sensitive(GTK_WIDGET(\ + g->buttons[i]->button),\ + g->buttons[i]->sensitivity);\ + if (g->buttons[i]->popup != NULL)\ + gtk_widget_set_sensitive(GTK_WIDGET(\ + g->buttons[i]->popup),\ + g->buttons[i]->sensitivity); + + int i; + SENSITIVITY(STOP) + SENSITIVITY(RELOAD) + SENSITIVITY(CUT) + SENSITIVITY(COPY) + SENSITIVITY(PASTE) + SENSITIVITY(BACK) + SENSITIVITY(FORWARD) + SENSITIVITY(NEXTTAB) + SENSITIVITY(PREVTAB) + SENSITIVITY(CLOSETAB) +#undef SENSITIVITY +} + +void nsgtk_scaffolding_initial_sensitivity(struct gtk_scaffolding *g) +{ + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + if (g->buttons[i]->main != NULL) + gtk_widget_set_sensitive(GTK_WIDGET( + g->buttons[i]->main), + g->buttons[i]->sensitivity); + if (g->buttons[i]->rclick != NULL) + gtk_widget_set_sensitive(GTK_WIDGET( + g->buttons[i]->rclick), + g->buttons[i]->sensitivity); + if ((g->buttons[i]->location != -1) && + (g->buttons[i]->button != NULL)) + gtk_widget_set_sensitive(GTK_WIDGET( + g->buttons[i]->button), + g->buttons[i]->sensitivity); + if (g->buttons[i]->popup != NULL) + gtk_widget_set_sensitive(GTK_WIDGET( + g->buttons[i]->popup), + g->buttons[i]->sensitivity); + } + gtk_widget_set_sensitive(GTK_WIDGET(g->view_menu->images_menuitem), + FALSE); +} + void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x, gdouble y) { guint available_menu_options = 0; GtkWidget *widget = NULL; + available_menu_options |= nsgtk_scaffolding_update_link_operations_sensitivity(g, - g->popup_xml, x, y, TRUE); + g->popup_xml, x, y, true); available_menu_options |= nsgtk_scaffolding_update_edit_actions_sensitivity(g, - g->popup_xml, TRUE); + g->popup_xml, true); /* Hide the separator as well */ if (!available_menu_options) { - widget = glade_xml_get_widget(g->popup_xml, "separator1"); + widget = glade_xml_get_widget(g->popup_xml, "sep2"); gtk_widget_hide(widget); } + /* hide customize */ + gtk_widget_hide(glade_xml_get_widget(g->popup_xml, "customize_popup")); + gtk_menu_popup(g->popup_menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); } +/** + * reallocate width for history button, reallocate buttons right of history; + * memorise base of history button / toolbar + */ +void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget, + GtkAllocation *alloc, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + int i = nsgtk_toolbar_get_id_from_widget(widget, g); + if ((g->toolbarmem == alloc->x) || + (g->buttons[i]->location < + g->buttons[HISTORY_BUTTON]->location)) + /* no reallocation after first adjustment, no reallocation for buttons + * left of history button */ + return; + if (widget == GTK_WIDGET(g->buttons[HISTORY_BUTTON]->button)) { + if (alloc->width == 20) + return; + + g->toolbarbase = alloc->y + alloc->height; + g->historybase = alloc->x + 20; + if (g->offset == 0) + g->offset = alloc->width - 20; + alloc->width = 20; + } else if (g->buttons[i]->location <= + g->buttons[URL_BAR_ITEM]->location) { + alloc->x -= g->offset; + if (i == URL_BAR_ITEM) + alloc->width += g->offset; + } + g->toolbarmem = alloc->x; + gtk_widget_size_allocate(widget, alloc); +} + static guint nsgtk_scaffolding_update_link_operations_sensitivity( struct gtk_scaffolding *g, GladeXML *xml, gdouble x, gdouble y, gboolean hide) { gboolean is_sensitive; - GtkWidget *widget1, *widget2, *widget3; + GtkWidget *widget[3]; + int i; - widget1 = glade_xml_get_widget_prefix(xml, "save_link")->data; - widget2 = glade_xml_get_widget_prefix(xml, + widget[0] = glade_xml_get_widget_prefix(xml, "save_link")->data; + widget[1] = glade_xml_get_widget_prefix(xml, "open_link_in_focused_tab")->data; - widget3 = glade_xml_get_widget_prefix(xml, + widget[2] = glade_xml_get_widget_prefix(xml, "open_link_in_background_tab")->data; - struct browser_window *bw = nsgtk_get_browser_for_gui(g->top_level); + struct browser_window *bw = gui_window_get_browser_window(g->top_level); current_menu_link_box = NULL; if (bw->current_content && bw->current_content->type == CONTENT_HTML) { @@ -1626,107 +2268,228 @@ static guint nsgtk_scaffolding_update_link_operations_sensitivity( } is_sensitive = (current_menu_link_box != NULL) ? TRUE : FALSE; - gtk_widget_set_sensitive(widget1, is_sensitive); - gtk_widget_set_sensitive(widget2, is_sensitive); - gtk_widget_set_sensitive(widget3, is_sensitive); - - if (hide == TRUE && current_menu_link_box == NULL) { - gtk_widget_hide(widget1); - gtk_widget_hide(widget2); - gtk_widget_hide(widget3); + for (i = 0; i < 3; i++) { + gtk_widget_set_sensitive(widget[i], is_sensitive); + + if (hide == true && current_menu_link_box == NULL) { + gtk_widget_hide(widget[i]); + } } return is_sensitive; } static guint nsgtk_scaffolding_update_edit_actions_sensitivity( - struct gtk_scaffolding *g, GladeXML *xml, gboolean hide) + struct gtk_scaffolding *g, GladeXML *xml, bool hide) { GtkWidget *widget = gtk_window_get_focus(g->window); - gboolean can_copy, can_cut, can_paste; gboolean has_selection; - if (GTK_IS_EDITABLE (widget)) { - has_selection = gtk_editable_get_selection_bounds - (GTK_EDITABLE (widget), NULL, NULL); + if (GTK_IS_EDITABLE(widget)) { + has_selection = gtk_editable_get_selection_bounds( + GTK_EDITABLE (widget), NULL, NULL); - can_copy = has_selection; - can_cut = has_selection; - can_paste = TRUE; + g->buttons[COPY_BUTTON]->sensitivity = has_selection; + g->buttons[CUT_BUTTON]->sensitivity = has_selection; + g->buttons[PASTE_BUTTON]->sensitivity = true; } else { struct browser_window *bw = - nsgtk_get_browser_for_gui(g->top_level); + gui_window_get_browser_window(g->top_level); has_selection = bw->sel->defined; - can_copy = has_selection; - can_cut = (has_selection && bw->caret_callback != 0); - can_paste = (bw->paste_callback != 0); + g->buttons[COPY_BUTTON]->sensitivity = has_selection; + g->buttons[CUT_BUTTON]->sensitivity = (has_selection && + bw->caret_callback != 0); + g->buttons[PASTE_BUTTON]->sensitivity = + (bw->paste_callback != 0); } widget = glade_xml_get_widget_prefix(xml, "copy")->data; - gtk_widget_set_sensitive (widget, can_copy); - if (hide && !can_copy) + if (hide && !(g->buttons[COPY_BUTTON]->sensitivity)) gtk_widget_hide(widget); widget = glade_xml_get_widget_prefix(xml, "cut")->data; - gtk_widget_set_sensitive (widget, can_cut); - if (hide && !can_cut) + if (hide && !(g->buttons[CUT_BUTTON]->sensitivity)) gtk_widget_hide(widget); widget = glade_xml_get_widget_prefix(xml, "paste")->data; - gtk_widget_set_sensitive (widget, can_paste); - if (hide && !can_paste) + if (hide && !(g->buttons[PASTE_BUTTON]->sensitivity)) gtk_widget_hide(widget); - - return (can_paste | can_cut | can_copy); + nsgtk_scaffolding_set_sensitivity(g); + return ((g->buttons[COPY_BUTTON]->sensitivity) | + (g->buttons[CUT_BUTTON]->sensitivity) | + (g->buttons[PASTE_BUTTON]->sensitivity)); } static void nsgtk_scaffolding_enable_link_operations_sensitivity( struct gtk_scaffolding *g, GladeXML *xml) { - GtkWidget *widget1; - GtkWidget *widget2; - GtkWidget *widget3; + int i; + GtkWidget *widget[3]; - widget1 = glade_xml_get_widget_prefix(xml, "save_link")->data; - widget2 = glade_xml_get_widget_prefix(xml, + widget[0] = glade_xml_get_widget_prefix(xml, "save_link")->data; + widget[1] = glade_xml_get_widget_prefix(xml, "open_link_in_focused_tab")->data; - widget3 = glade_xml_get_widget_prefix(xml, + widget[2] = glade_xml_get_widget_prefix(xml, "open_link_in_background_tab")->data; - gtk_widget_set_sensitive(widget1, TRUE); - gtk_widget_show(widget1); - gtk_widget_set_sensitive(widget2, TRUE); - gtk_widget_show(widget2); - gtk_widget_set_sensitive(widget3, TRUE); - gtk_widget_show(widget3); - - + for (i = 0; i < 3; i++) { + gtk_widget_set_sensitive(widget[i], TRUE); + gtk_widget_show(widget[i]); + } } static void nsgtk_scaffolding_enable_edit_actions_sensitivity( struct gtk_scaffolding *g, GladeXML *xml) { - GtkWidget *widget1; - GtkWidget *widget2; - GtkWidget *widget3; - GtkWidget *widget4; - GtkWidget *widget5; - - widget1 = glade_xml_get_widget(xml, "separator"); - widget2 = glade_xml_get_widget(xml, "separator1"); - widget3 = glade_xml_get_widget_prefix(xml, "copy")->data; - widget4 = glade_xml_get_widget_prefix(xml, "cut")->data; - widget5 = glade_xml_get_widget_prefix(xml, "paste")->data; - - gtk_widget_set_sensitive(widget3, TRUE); - gtk_widget_set_sensitive(widget4, TRUE); - gtk_widget_set_sensitive(widget5, TRUE); - - gtk_widget_show(widget1); - gtk_widget_show(widget2); - gtk_widget_show(widget3); - gtk_widget_show(widget4); - gtk_widget_show(widget5); + int i; + GtkWidget *widget[5]; + + widget[0] = glade_xml_get_widget(xml, "sep"); + widget[1] = glade_xml_get_widget(xml, "sep2"); + widget[2] = glade_xml_get_widget_prefix(xml, "copy")->data; + widget[3] = glade_xml_get_widget_prefix(xml, "cut")->data; + widget[4] = glade_xml_get_widget_prefix(xml, "paste")->data; + g->buttons[PASTE_BUTTON]->sensitivity = true; + g->buttons[COPY_BUTTON]->sensitivity = true; + g->buttons[CUT_BUTTON]->sensitivity = true; + nsgtk_scaffolding_set_sensitivity(g); + + for (i = 0; i < 5; i++) + gtk_widget_show(widget[i]); + +} + +/** + * init the array g->buttons[] + */ +void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g) +{ +#define ITEM_MAIN(p, q, r)\ + g->buttons[p##_BUTTON]->main =\ + g->q##_menu->r##_menuitem;\ + g->buttons[p##_BUTTON]->rclick =\ + g->rclick_##q##_menu->r##_menuitem;\ + g->buttons[p##_BUTTON]->mhandler =\ + nsgtk_on_##r##_activate_menu;\ + g->buttons[p##_BUTTON]->bhandler =\ + nsgtk_on_##r##_activate_button;\ + g->buttons[p##_BUTTON]->dataplus =\ + nsgtk_toolbar_##r##_button_data;\ + g->buttons[p##_BUTTON]->dataminus =\ + nsgtk_toolbar_##r##_toolbar_button_data +#define ITEM_SUB(p, q, r, s)\ + g->buttons[p##_BUTTON]->main =\ + g->q##_menu->\ + r##_submenu->s##_menuitem;\ + g->buttons[p##_BUTTON]->rclick =\ + g->rclick_##q##_menu->\ + r##_submenu->s##_menuitem;\ + g->buttons[p##_BUTTON]->mhandler =\ + nsgtk_on_##s##_activate_menu;\ + g->buttons[p##_BUTTON]->bhandler =\ + nsgtk_on_##s##_activate_button;\ + g->buttons[p##_BUTTON]->dataplus =\ + nsgtk_toolbar_##s##_button_data;\ + g->buttons[p##_BUTTON]->dataminus =\ + nsgtk_toolbar_##s##_toolbar_button_data +#define ITEM_BUTTON(p, q)\ + g->buttons[p##_BUTTON]->bhandler =\ + nsgtk_on_##q##_activate;\ + g->buttons[p##_BUTTON]->dataplus =\ + nsgtk_toolbar_##q##_button_data;\ + g->buttons[p##_BUTTON]->dataminus =\ + nsgtk_toolbar_##q##_toolbar_button_data +#define ITEM_POP(p, q)\ + g->buttons[p##_BUTTON]->popup = GTK_IMAGE_MENU_ITEM(\ + glade_xml_get_widget(g->popup_xml, #q "_popup")) +#define SENSITIVITY(q)\ + g->buttons[q##_BUTTON]->sensitivity = false +#define ITEM_ITEM(p, q)\ + g->buttons[p##_ITEM]->dataplus =\ + nsgtk_toolbar_##q##_button_data;\ + g->buttons[p##_ITEM]->dataminus =\ + nsgtk_toolbar_##q##_toolbar_button_data + ITEM_ITEM(WEBSEARCH, websearch); + ITEM_ITEM(THROBBER, throbber); + ITEM_MAIN(NEWWINDOW, file, newwindow); + ITEM_MAIN(NEWTAB, file, newtab); + ITEM_MAIN(OPENFILE, file, openfile); + ITEM_MAIN(PRINT, file, print); + ITEM_MAIN(CLOSEWINDOW, file, closewindow); + ITEM_MAIN(SAVEPAGE, file, savepage); + ITEM_MAIN(PRINTPREVIEW, file, printpreview); + ITEM_MAIN(PRINT, file, print); + ITEM_MAIN(QUIT, file, quit); + ITEM_MAIN(CUT, edit, cut); + ITEM_MAIN(COPY, edit, copy); + ITEM_MAIN(PASTE, edit, paste); + ITEM_MAIN(DELETE, edit, delete); + ITEM_MAIN(SELECTALL, edit, selectall); + ITEM_MAIN(FIND, edit, find); + ITEM_MAIN(PREFERENCES, edit, preferences); + ITEM_MAIN(STOP, view, stop); + ITEM_POP(STOP, stop); + ITEM_MAIN(RELOAD, view, reload); + ITEM_POP(RELOAD, reload); + ITEM_MAIN(FULLSCREEN, view, fullscreen); + ITEM_MAIN(VIEWSOURCE, view, viewsource); + ITEM_MAIN(DOWNLOADS, view, downloads); + ITEM_MAIN(SAVEWINDOWSIZE, view, savewindowsize); + ITEM_MAIN(BACK, nav, back); + ITEM_POP(BACK, back); + ITEM_MAIN(FORWARD, nav, forward); + ITEM_POP(FORWARD, forward); + ITEM_MAIN(HOME, nav, home); + ITEM_MAIN(LOCALHISTORY, nav, localhistory); + ITEM_MAIN(GLOBALHISTORY, nav, globalhistory); + ITEM_MAIN(ADDBOOKMARKS, nav, addbookmarks); + ITEM_MAIN(SHOWBOOKMARKS, nav, showbookmarks); + ITEM_MAIN(OPENLOCATION, nav, openlocation); + ITEM_MAIN(NEXTTAB, tabs, nexttab); + ITEM_MAIN(PREVTAB, tabs, prevtab); + ITEM_MAIN(CLOSETAB, tabs, closetab); + ITEM_MAIN(CONTENTS, help, contents); + ITEM_MAIN(INFO, help, info); + ITEM_MAIN(GUIDE, help, guide); + ITEM_MAIN(ABOUT, help, about); + ITEM_SUB(PLAINTEXT, file, export, plaintext); + ITEM_SUB(PDF, file, export, pdf); + ITEM_SUB(DRAWFILE, file, export, drawfile); + ITEM_SUB(POSTSCRIPT, file, export, postscript); + ITEM_SUB(ZOOMPLUS, view, scaleview, zoomplus); + ITEM_SUB(ZOOMMINUS, view, scaleview, zoomminus); + ITEM_SUB(ZOOMNORMAL, view, scaleview, zoomnormal); + ITEM_SUB(TOGGLEDEBUGGING, view, debugging, toggledebugging); + ITEM_SUB(SAVEBOXTREE, view, debugging, saveboxtree); + ITEM_SUB(SAVEDOMTREE, view, debugging, savedomtree); + ITEM_BUTTON(HISTORY, history); + /* disable items that make no sense initially, as well as + * as-yet-unimplemented items */ + SENSITIVITY(BACK); + SENSITIVITY(FORWARD); + SENSITIVITY(STOP); + SENSITIVITY(PRINTPREVIEW); + SENSITIVITY(DELETE); + SENSITIVITY(CONTENTS); + SENSITIVITY(DRAWFILE); + SENSITIVITY(POSTSCRIPT); + SENSITIVITY(ADDBOOKMARKS); + SENSITIVITY(SHOWBOOKMARKS); + SENSITIVITY(NEXTTAB); + SENSITIVITY(PREVTAB); + SENSITIVITY(CLOSETAB); + SENSITIVITY(GUIDE); + SENSITIVITY(INFO); +#ifndef WITH_PDF_EXPORT + SENSITIVITY(PDF); +#endif + +#undef ITEM_MAIN +#undef ITEM_SUB +#undef ITEM_BUTTON +#undef ITEM_POP +#undef SENSITIVITY + } diff --git a/gtk/gtk_scaffolding.h b/gtk/gtk_scaffolding.h index f4b6bffd5..07886690b 100644 --- a/gtk/gtk_scaffolding.h +++ b/gtk/gtk_scaffolding.h @@ -21,63 +21,219 @@ #include <gtk/gtk.h> #include <glade/glade.h> +#include <glib.h> #include "desktop/gui.h" #include "desktop/plotters.h" +#include "gtk/gtk_menu.h" +#include "gtk/sexy_icon_entry.h" typedef struct gtk_scaffolding nsgtk_scaffolding; -struct gtk_scaffolding { +typedef enum { + BACK_BUTTON = 0, + HISTORY_BUTTON, + FORWARD_BUTTON, + STOP_BUTTON, + RELOAD_BUTTON, + HOME_BUTTON, + URL_BAR_ITEM, + WEBSEARCH_ITEM, + THROBBER_ITEM, + NEWWINDOW_BUTTON, + NEWTAB_BUTTON, + OPENFILE_BUTTON, + CLOSETAB_BUTTON, + CLOSEWINDOW_BUTTON, + SAVEPAGE_BUTTON, + PDF_BUTTON, + PLAINTEXT_BUTTON, + DRAWFILE_BUTTON, + POSTSCRIPT_BUTTON, + PRINTPREVIEW_BUTTON, + PRINT_BUTTON, + QUIT_BUTTON, + CUT_BUTTON, + COPY_BUTTON, + PASTE_BUTTON, + DELETE_BUTTON, + SELECTALL_BUTTON, + FIND_BUTTON, + PREFERENCES_BUTTON, + ZOOMPLUS_BUTTON, + ZOOMMINUS_BUTTON, + ZOOMNORMAL_BUTTON, + FULLSCREEN_BUTTON, + VIEWSOURCE_BUTTON, + DOWNLOADS_BUTTON, + SAVEWINDOWSIZE_BUTTON, + TOGGLEDEBUGGING_BUTTON, + SAVEBOXTREE_BUTTON, + SAVEDOMTREE_BUTTON, + LOCALHISTORY_BUTTON, + GLOBALHISTORY_BUTTON, + ADDBOOKMARKS_BUTTON, + SHOWBOOKMARKS_BUTTON, + OPENLOCATION_BUTTON, + NEXTTAB_BUTTON, + PREVTAB_BUTTON, + CONTENTS_BUTTON, + GUIDE_BUTTON, + INFO_BUTTON, + ABOUT_BUTTON, + PLACEHOLDER_BUTTON /* size indicator; array maximum indices */ +} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */ + +struct gtk_history_window { + struct gtk_scaffolding *g; GtkWindow *window; - GtkNotebook *notebook; - GtkEntry *url_bar; - GtkEntryCompletion *url_bar_completion; - GtkStatusbar *status_bar; - GtkMenuItem *edit_menu; - GtkMenuItem *tabs_menu; - GtkToolbar *tool_bar; - GtkToolButton *back_button; - GtkToolButton *history_button; - GtkToolButton *forward_button; - GtkToolButton *stop_button; - GtkToolButton *reload_button; - GtkMenuBar *menu_bar; - GtkMenuItem *back_menu; - GtkMenuItem *forward_menu; - GtkMenuItem *stop_menu; - GtkMenuItem *reload_menu; - GtkImage *throbber; - GtkPaned *status_pane; - - GladeXML *xml; - - GladeXML *popup_xml; - GtkMenu *popup_menu; - - struct gtk_history_window *history_window; - GtkDialog *preferences_dialog; - - int throb_frame; - struct gui_window *top_level; - int being_destroyed; - - bool fullscreen; + GtkScrolledWindow *scrolled; + GtkDrawingArea *drawing_area; }; -GtkWindow *nsgtk_get_window_for_scaffold(struct gtk_scaffolding *g); - -nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel); - -gboolean nsgtk_scaffolding_is_busy(nsgtk_scaffolding *scaffold); - -GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g); +struct gtk_search { + GtkToolbar *bar; + GtkEntry *entry; + GtkToolButton *buttons[3]; /* back, forward, */ + GtkCheckButton *checkAll; /* close */ + GtkCheckButton *caseSens; +}; -GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g); +struct nsgtk_button_connect { + GtkToolItem *button; + int location; /* in toolbar */ + bool sensitivity; + GtkImageMenuItem *main; + GtkImageMenuItem *rclick; + GtkImageMenuItem *popup; + void *mhandler; /* menu item clicked */ + void *bhandler; /* button clicked */ + void *dataplus; /* customization -> toolbar */ + void *dataminus; /* customization -> store */ +}; -void nsgtk_scaffolding_set_top_level (struct gui_window *gw); +extern nsgtk_scaffolding *scaf_list; -void nsgtk_scaffolding_destroy(nsgtk_scaffolding *scaffold); +nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel); +bool nsgtk_scaffolding_is_busy(nsgtk_scaffolding *g); + +GtkWindow *nsgtk_scaffolding_window(nsgtk_scaffolding *g); +GtkNotebook *nsgtk_scaffolding_notebook(nsgtk_scaffolding *g); +GtkWidget *nsgtk_scaffolding_urlbar(nsgtk_scaffolding *g); +GtkWidget *nsgtk_scaffolding_websearch(nsgtk_scaffolding *g); +GtkToolbar *nsgtk_scaffolding_toolbar(nsgtk_scaffolding *g); +struct nsgtk_button_connect *nsgtk_scaffolding_button(nsgtk_scaffolding *g, + int i); +struct gtk_search *nsgtk_scaffolding_search(nsgtk_scaffolding *g); +GtkMenuBar *nsgtk_scaffolding_menu_bar(nsgtk_scaffolding *g); +struct gtk_history_window *nsgtk_scaffolding_history_window(nsgtk_scaffolding + *g); +struct gui_window *nsgtk_scaffolding_top_level(nsgtk_scaffolding *g); +void nsgtk_scaffolding_reset_offset(nsgtk_scaffolding *g); +nsgtk_scaffolding *nsgtk_scaffolding_iterate(nsgtk_scaffolding *g); +void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g); +void nsgtk_scaffolding_update_url_bar_ref(nsgtk_scaffolding *g); +void nsgtk_scaffolding_update_throbber_ref(nsgtk_scaffolding *g); +void nsgtk_scaffolding_update_websearch_ref(nsgtk_scaffolding *g); +void nsgtk_scaffolding_set_websearch(nsgtk_scaffolding *g, const char + *content); +void nsgtk_scaffolding_toggle_search_bar_visibility(nsgtk_scaffolding *g); +void nsgtk_scaffolding_set_top_level(struct gui_window *g); + +void nsgtk_scaffolding_destroy(nsgtk_scaffolding *g); + +void nsgtk_scaffolding_set_sensitivity(struct gtk_scaffolding *g); +void nsgtk_scaffolding_initial_sensitivity(struct gtk_scaffolding *g); void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x, gdouble y); +void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget, + GtkAllocation *alloc, gpointer data); + +gboolean nsgtk_window_url_activate_event(GtkWidget *, gpointer); +gboolean nsgtk_window_url_changed(GtkWidget *, GdkEventKey *, gpointer); + +#define MULTIPROTO(q)\ +gboolean nsgtk_on_##q##_activate(struct gtk_scaffolding *);\ +gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *, gpointer);\ +gboolean nsgtk_on_##q##_activate_button(GtkButton *, gpointer) +#define MENUPROTO(q)\ +gboolean nsgtk_on_##q##_activate(GtkMenuItem *, gpointer) +#define BUTTONPROTO(q)\ +gboolean nsgtk_on_##q##_activate(GtkButton *, gpointer) +/* prototypes for handlers */ +/* file menu */ +MULTIPROTO(newwindow); +MULTIPROTO(newtab); +MULTIPROTO(open_location); +MULTIPROTO(openfile); +MULTIPROTO(savepage); +MULTIPROTO(pdf); +MULTIPROTO(plaintext); +MULTIPROTO(drawfile); +MULTIPROTO(postscript); +MULTIPROTO(printpreview); +MULTIPROTO(print); +MULTIPROTO(closewindow); +MULTIPROTO(quit); + +/* edit menu */ +MULTIPROTO(cut); +MULTIPROTO(copy); +MULTIPROTO(paste); +MULTIPROTO(delete); +MULTIPROTO(selectall); +MULTIPROTO(find); +MULTIPROTO(preferences); + +/* view menu */ +MULTIPROTO(stop); +MULTIPROTO(reload); +MULTIPROTO(zoomplus); +MULTIPROTO(zoomnormal); +MULTIPROTO(zoomminus); +MULTIPROTO(fullscreen); +MULTIPROTO(viewsource); +MENUPROTO(menubar); +MENUPROTO(toolbar); +MENUPROTO(statusbar); +MULTIPROTO(downloads); +MULTIPROTO(savewindowsize); +MULTIPROTO(toggledebugging); +MULTIPROTO(saveboxtree); +MULTIPROTO(savedomtree); + +/* navigate menu */ +MULTIPROTO(back); +MULTIPROTO(forward); +MULTIPROTO(home); +MULTIPROTO(localhistory); +MULTIPROTO(globalhistory); +MULTIPROTO(addbookmarks); +MULTIPROTO(showbookmarks); +MULTIPROTO(openlocation); + +/* tabs menu */ +MULTIPROTO(nexttab); +MULTIPROTO(prevtab); +MULTIPROTO(closetab); + +/* help menu */ +MULTIPROTO(contents); +MULTIPROTO(guide); +MULTIPROTO(info); +MULTIPROTO(about); + +/* popup menu */ +MENUPROTO(customize); +MENUPROTO(savelink); +MENUPROTO(linkfocused); +MENUPROTO(linkbackground); + +/* non-menu */ +BUTTONPROTO(history); + +#undef MULTIPROTO +#undef MENUPROTO +#undef BUTTONPROTO #endif /* NETSURF_GTK_SCAFFOLDING_H */ diff --git a/gtk/gtk_search.c b/gtk/gtk_search.c new file mode 100644 index 000000000..bb5d0138c --- /dev/null +++ b/gtk/gtk_search.c @@ -0,0 +1,263 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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 + * Free text search (front component) + */ +#include <ctype.h> +#include <string.h> +#include <gdk/gdkkeysyms.h> +#include "gtk/gtk_search.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_window.h" +#include "utils/config.h" +#include "content/content.h" +#include "desktop/browser.h" +#include "desktop/gui.h" +#include "desktop/search.h" +#include "desktop/searchweb.h" +#include "desktop/selection.h" +#include "render/box.h" +#include "render/html.h" +#include "utils/config.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" + +static void nsgtk_search_init(struct gtk_scaffolding *g); +static void nsgtk_search_set_status(bool found, void *p); +static void nsgtk_search_set_hourglass(bool active, void *p); +static void nsgtk_search_add_recent(const char *string, void *p); + +static struct search_callbacks nsgtk_search_callbacks = { + nsgtk_search_set_forward_state, + nsgtk_search_set_back_state, + nsgtk_search_set_status, + nsgtk_search_set_hourglass, + nsgtk_search_add_recent +}; + +/** connected to the search forward button */ + +gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + struct browser_window *bw = gui_window_get_browser_window( + nsgtk_scaffolding_top_level(g)); + nsgtk_search_init(g); + search_flags_t flags = SEARCH_FLAG_FORWARDS | + (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->caseSens)) ? + SEARCH_FLAG_CASE_SENSITIVE : 0) | + (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->checkAll)) ? + SEARCH_FLAG_SHOWALL : 0); + if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw)) + search_step(bw->search_context, flags, gtk_entry_get_text( + nsgtk_scaffolding_search(g)->entry)); + return TRUE; +} + +/** connected to the search back button */ + +gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + struct browser_window *bw = gui_window_get_browser_window( + nsgtk_scaffolding_top_level(g)); + nsgtk_search_init(g); + search_flags_t flags = 0 |(gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->caseSens)) ? + SEARCH_FLAG_CASE_SENSITIVE : 0) | + (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->checkAll)) ? + SEARCH_FLAG_SHOWALL : 0); + if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw)) + search_step(bw->search_context, flags, gtk_entry_get_text( + nsgtk_scaffolding_search(g)->entry)); + return TRUE; +} + +/** preparatory code when the search bar is made visible initially */ + +void nsgtk_search_init(struct gtk_scaffolding *g) +{ + struct content *c; + + assert(gui_window_get_browser_window(nsgtk_scaffolding_top_level(g)) + != NULL); + + c = gui_window_get_browser_window(nsgtk_scaffolding_top_level(g))-> + current_content; + + if ((!c) || (c->type != CONTENT_HTML && c->type != CONTENT_TEXTPLAIN)) + return; + +} + +/** connected to the search close button */ + +gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + nsgtk_scaffolding_toggle_search_bar_visibility(g); + return TRUE; +} + +/** connected to the search entry [typing] */ + +gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + struct browser_window *bw = gui_window_get_browser_window( + nsgtk_scaffolding_top_level(g)); + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, (void *)bw); + nsgtk_search_set_back_state(true, (void *)bw); + return TRUE; +} + +/** connected to the search entry [return key] */ + +gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + struct browser_window *bw = gui_window_get_browser_window( + nsgtk_scaffolding_top_level(g)); + nsgtk_search_init(g); + search_flags_t flags = SEARCH_FLAG_FORWARDS | + (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->caseSens)) ? + SEARCH_FLAG_CASE_SENSITIVE : 0) | + (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + nsgtk_scaffolding_search(g)->checkAll)) ? + SEARCH_FLAG_SHOWALL : 0); + if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw)) + search_step(bw->search_context, flags, gtk_entry_get_text( + nsgtk_scaffolding_search(g)->entry)); + return FALSE; +} + +/** allows escape key to close search bar too */ + +gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, + gpointer data) +{ + if (event->keyval == GDK_Escape) { + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + nsgtk_scaffolding_toggle_search_bar_visibility(g); + } + return FALSE; +} + +/** connected to the websearch entry [return key] */ + +gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + temp_open_background = 0; + search_web_new_window(gui_window_get_browser_window( + nsgtk_scaffolding_top_level(g)), + (char *)gtk_entry_get_text(GTK_ENTRY( + nsgtk_scaffolding_websearch(g)))); + temp_open_background = -1; + return TRUE; +} + +/** + * allows a click in the websearch entry field to clear the name of the + * provider + */ + +gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f, + gpointer data) +{ + struct gtk_scaffolding *g = (struct gtk_scaffolding *)data; + gtk_editable_select_region(GTK_EDITABLE( + nsgtk_scaffolding_websearch(g)), 0, -1); + gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_websearch(g))); + return TRUE; +} + +/** +* Change the displayed search status. +* \param found search pattern matched in text +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void nsgtk_search_set_status(bool found, void *p) +{ +} + +/** +* display hourglass while searching +* \param active start/stop indicator +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void nsgtk_search_set_hourglass(bool active, void *p) +{ +} + +/** +* add search string to recent searches list +* front is at liberty how to implement the bare notification +* should normally store a strdup() of the string; +* core gives no guarantee of the integrity of the const char * +* \param string search pattern +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void nsgtk_search_add_recent(const char *string, void *p) +{ +} + +/** +* activate search forwards button in gui +* \param active activate/inactivate +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void nsgtk_search_set_forward_state(bool active, void *p) +{ + struct browser_window *bw = (struct browser_window *)p; + if ((bw != NULL) && (bw->window != NULL)) { + struct gtk_scaffolding *g = nsgtk_get_scaffold(bw->window); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search( + g)->buttons[1]), active); + } +} + +/** +* activate search back button in gui +* \param active activate/inactivate +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void nsgtk_search_set_back_state(bool active, void *p) +{ + struct browser_window *bw = (struct browser_window *)p; + if ((bw != NULL) && (bw->window != NULL)) { + struct gtk_scaffolding *g = nsgtk_get_scaffold(bw->window); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search( + g)->buttons[0]), active); + } +} diff --git a/gtk/gtk_search.h b/gtk/gtk_search.h new file mode 100644 index 000000000..981ea5bfd --- /dev/null +++ b/gtk/gtk_search.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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_SEARCH_H_ +#define _NETSURF_GTK_SEARCH_H_ + +#include <gtk/gtk.h> +#include "gtk/gtk_scaffolding.h" + +void nsgtk_search_bar_toggle_visibility(struct gtk_scaffolding * g); +gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data); +gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data); +gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, + gpointer data); +gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data); +gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data); +gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data); +gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data); +gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f, + gpointer data); +void nsgtk_search_set_forward_state(bool active, void *p); +void nsgtk_search_set_back_state(bool active, void *p); + +#endif diff --git a/gtk/gtk_selection.c b/gtk/gtk_selection.c index cf9e1decd..41869d753 100644 --- a/gtk/gtk_selection.c +++ b/gtk/gtk_selection.c @@ -79,7 +79,7 @@ void gui_start_selection(struct gui_window *g) else g_string_set_size(current_selection, 0); - gtk_widget_grab_focus(GTK_WIDGET(g->drawing_area)); + gtk_widget_grab_focus(GTK_WIDGET(nsgtk_window_get_drawing_area(g))); } void gui_paste_from_clipboard(struct gui_window *g, int x, int y) @@ -89,7 +89,8 @@ void gui_paste_from_clipboard(struct gui_window *g, int x, int y) text = gtk_clipboard_wait_for_text (clipboard); /* clipboard_wait... converts the string to utf8 for us */ if (text != NULL) - browser_window_paste_text(g->bw, text, strlen(text), true); + browser_window_paste_text(gui_window_get_browser_window(g), + text, strlen(text), true); g_free(text); } diff --git a/gtk/gtk_tabs.c b/gtk/gtk_tabs.c index b54f3cfb9..f0e87bb79 100644 --- a/gtk/gtk_tabs.c +++ b/gtk/gtk_tabs.c @@ -23,12 +23,14 @@ #include "desktop/browser.h" #include "content/content.h" #include "desktop/options.h" +#include "desktop/search.h" #include "utils/utils.h" #include "gtk/options.h" +#include "gtk/gtk_search.h" #include "gtk/gtk_tabs.h" #define TAB_WIDTH_N_CHARS 15 -#define GET_WIDGET(x) glade_xml_get_widget(gladeWindows, (x)) +#define GET_WIDGET(x) glade_xml_get_widget(gladeNetsurf, (x)) static GtkWidget *nsgtk_tab_label_setup(struct gui_window *window); static void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, @@ -58,15 +60,19 @@ void nsgtk_tab_init(GtkWidget *tabs) void nsgtk_tab_add(struct gui_window *window, bool background) { - GtkWidget *tabs = GTK_WIDGET(nsgtk_scaffolding_get_notebook(window)); + GtkWidget *tabs = GTK_WIDGET(nsgtk_scaffolding_notebook( + nsgtk_get_scaffold(window))); GtkWidget *tabBox = nsgtk_tab_label_setup(window); gint remember = gtk_notebook_get_current_page(GTK_NOTEBOOK(tabs)); gtk_notebook_append_page(GTK_NOTEBOOK(tabs), - GTK_WIDGET(window->scrolledwindow), tabBox); - /*causes gtk errors can't set a parent + GTK_WIDGET(nsgtk_window_get_scrolledwindow(window)), + tabBox); + /*causes gtk errors can't set a parent */ gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(tabs), - GTK_WIDGET(window->scrolledwindow), true); */ - gtk_widget_show_all(GTK_WIDGET(window->scrolledwindow)); + GTK_WIDGET(nsgtk_window_get_scrolledwindow(window)), + true); + gtk_widget_show_all(GTK_WIDGET(nsgtk_window_get_scrolledwindow( + window))); gtk_notebook_set_current_page(GTK_NOTEBOOK(tabs), gtk_notebook_get_n_pages(GTK_NOTEBOOK(tabs)) - 1); if (option_new_blank) { @@ -75,13 +81,15 @@ void nsgtk_tab_add(struct gui_window *window, bool background) blankpage = g_strconcat("file:///", res_dir_location, "blankpage", NULL); */ /* segfaults - struct browser_window *bw = nsgtk_get_browser_for_gui(window); + struct browser_window *bw = + gui_window_get_browser_window(window); browser_window_go(bw, blankpage, 0, true); */ /* free(blankpage); */ } if (background) gtk_notebook_set_current_page(GTK_NOTEBOOK(tabs), remember); - gtk_widget_grab_focus(GTK_WIDGET(window->scaffold->url_bar)); + gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_urlbar( + nsgtk_get_scaffold(window)))); } void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, @@ -97,12 +105,14 @@ void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, void nsgtk_tab_set_title(struct gui_window *g, const char *title) { GtkWidget *label; - gboolean is_top_level = (g->tab != NULL); + GtkWidget *tab; + tab = nsgtk_window_get_tab(g); + gboolean is_top_level = (tab != NULL); if (is_top_level) { - label = g_object_get_data(G_OBJECT(g->tab), "label"); + label = g_object_get_data(G_OBJECT(tab), "label"); gtk_label_set_text(GTK_LABEL(label), title); - gtk_widget_set_tooltip_text(g->tab, title); + gtk_widget_set_tooltip_text(tab, title); } } @@ -147,7 +157,7 @@ GtkWidget *nsgtk_tab_label_setup(struct gui_window *window) g_object_set_data(G_OBJECT(hbox), "label", label); g_object_set_data(G_OBJECT(hbox), "close-button", button); - window->tab = hbox; + nsgtk_window_set_tab(window, hbox); gtk_widget_show_all(hbox); return hbox; @@ -183,6 +193,11 @@ void nsgtk_tab_page_changed(GtkNotebook *notebook, GtkNotebookPage *page, GtkWidget *window = gtk_notebook_get_nth_page(notebook, page_num); struct gui_window *gw = g_object_get_data(G_OBJECT(window), "gui_window"); + struct browser_window *bw = gui_window_get_browser_window(gw); + if ((bw != NULL) && (bw->search_context != NULL)) + search_destroy_context(bw->search_context); + nsgtk_search_set_forward_state(true, bw); + nsgtk_search_set_back_state(true, bw); if (gw) nsgtk_scaffolding_set_top_level(gw); } diff --git a/gtk/gtk_theme.c b/gtk/gtk_theme.c new file mode 100644 index 000000000..f215cbeea --- /dev/null +++ b/gtk/gtk_theme.c @@ -0,0 +1,773 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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/>. + */ + +#include <gtk/gtk.h> +#include <stdio.h> +#include <sys/stat.h> +#include "content/content.h" +#include "content/content_type.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_menu.h" +#include "gtk/gtk_theme.h" +#include "gtk/gtk_window.h" +#include "gtk/options.h" +#include "gtk/dialogs/gtk_options.h" +#include "utils/container.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" + +enum image_sets { + IMAGE_SET_MAIN_MENU = 0, + IMAGE_SET_RCLICK_MENU, + IMAGE_SET_POPUP_MENU, + IMAGE_SET_BUTTONS, + IMAGE_SET_COUNT +}; + +struct nsgtk_theme_cache { + GdkPixbuf *image[PLACEHOLDER_BUTTON]; + GdkPixbuf *searchimage[SEARCH_BUTTONS_COUNT]; + /* apng throbber image */ +}; + +static char *current_theme_name = NULL; +static struct nsgtk_theme_cache *theme_cache_menu = NULL; +static struct nsgtk_theme_cache *theme_cache_toolbar = NULL; + +static struct nsgtk_theme *nsgtk_theme_default(GtkIconSize s); +static GtkImage *nsgtk_theme_image_default(nsgtk_toolbar_button i, + GtkIconSize s); +static bool nsgtk_theme_verify(const char *themename); +static void nsgtk_theme_cache_image(nsgtk_toolbar_button i, + const char *filename, const char *path); +static void nsgtk_theme_cache_searchimage(nsgtk_search_buttons i, + const char *filename, const char *path); + +#ifdef WITH_THEME_INSTALL +static struct content *theme_install_content = NULL; + +static void theme_install_callback(content_msg msg, struct content *c, + intptr_t p1, intptr_t p2, union content_msg_data data); +static bool theme_install_read(const char *data, unsigned long len); +#endif + +/** + * called during gui init phase to retrieve theme name from file then + * implement + */ + +void nsgtk_theme_init(void) +{ + size_t len; + if (option_current_theme == 0) + return; + len = SLEN("themelist") + strlen(res_dir_location) + 1; + char themefile[len]; + snprintf(themefile, len, "%s%s", res_dir_location, "themelist"); + nsgtk_scaffolding *list = scaf_list; + nsgtk_theme_verify(NULL); + FILE *fp = fopen(themefile, "r"); + if (fp == NULL) + return; + char buf[50]; + int row_count = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (buf[0] == '\0') + continue; + + if (row_count++ == option_current_theme) { + if (current_theme_name != NULL) + free(current_theme_name); + /* clear the '\n' ["\n\0"->"\0\0"] */ + buf[strlen(buf) - 1] = '\0'; + current_theme_name = strdup(buf); + break; + } + } + fclose(fp); + + while (list != NULL) { + nsgtk_theme_implement(list); + list = nsgtk_scaffolding_iterate(list); + } +} + +/** + * return reference to static global current_theme_name; caller then has + * responsibility for global reference + */ + +char *nsgtk_theme_name(void) +{ + return current_theme_name; +} + +/** + * set static global current_theme_name from param; caller is responsible + * for the integrity of the global reference + */ + +void nsgtk_theme_set_name(char *name) +{ + current_theme_name = name; +} + +/** + * adds a theme name to the list of themes + */ + +void nsgtk_theme_add(const char *themename) +{ + size_t len; + GtkWidget *notification, *label; + len = SLEN("themelist") + strlen(res_dir_location) + 1; + char themefile[len]; + snprintf(themefile, len, "%s%s", res_dir_location, "themelist"); + /* conduct verification here; no adding duplicates to list */ + if (nsgtk_theme_verify(themename) == false) { + warn_user(messages_get("gtkThemeDup"), 0); + return; + } + FILE *fp = fopen(themefile, "a"); + if (fp == NULL) { + warn_user(messages_get("gtkFileError"), themefile); + return; + } + fprintf(fp, "%s\n", themename); + fclose(fp); + + /* notification that theme was added successfully */ + notification = gtk_dialog_new_with_buttons(messages_get("gtkThemeAdd"), + NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, + GTK_RESPONSE_NONE, NULL); + if (notification == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + len = SLEN("\t\t\t\t\t\t") + strlen(messages_get("gtkThemeAdd")) + 1; + char labelcontent[len]; + snprintf(labelcontent, len, "\t\t\t%s\t\t\t", + messages_get("gtkThemeAdd")); + label = gtk_label_new(labelcontent); + if (label == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + g_signal_connect_swapped(notification, "response", + G_CALLBACK(gtk_widget_destroy), notification); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(notification)->vbox), label); + gtk_widget_show_all(notification); + + /* update combo */ + if (wndPreferences == NULL) + return; + nsgtk_options_combo_theme_add(themename); + +} + +/** + * \param themename contains a name of theme to check whether it may + * properly be added to the list; alternatively NULL to check the integrity + * of the list + * \return true for themename may be added / every item in the list is + * a valid directory + */ + +bool nsgtk_theme_verify(const char *themename) +{ + long filelength; + FILE *fp; + size_t val = SLEN("themelist") + strlen(res_dir_location) + 1; + char buf[50]; + char themefile[val]; + snprintf(themefile, val, "%s%s", res_dir_location, "themelist"); + if (themename == NULL) { + char *filecontent, *testfile; + struct stat sta; + fp = fopen(themefile, "r+"); + if (fp == NULL) { + warn_user(messages_get("gtkFileError"), themefile); + return true; + } + fseek(fp, 0L, SEEK_END); + filelength = ftell(fp); + filecontent = malloc(filelength + + SLEN("gtk default theme\n") + SLEN("\n") + + 1); + if (filecontent == NULL) { + warn_user(messages_get("NoMemory"), 0); + return true; + } + strcpy(filecontent, "gtk default theme\n"); + fseek(fp, 0L, SEEK_SET); + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* iterate list */ + buf[strlen(buf) - 1] = '\0'; + /* "\n\0" -> "\0\0" */ + testfile = malloc(strlen(res_dir_location) + + SLEN("themes/") + strlen(buf) + 1); + if (testfile == NULL) { + warn_user(messages_get("NoMemory"), 0); + free(filecontent); + return false; + } + sprintf(testfile, "%sthemes/%s", res_dir_location, + buf); + /* check every directory */ + if (access(testfile, R_OK) == 0) { + stat(testfile, &sta); + if (S_ISDIR(sta.st_mode)) { + buf[strlen(buf)] = '\n'; + /* "\0\0" -> "\n\0" */ + strcat(filecontent, buf); + } + } + free(testfile); + } + fclose(fp); + fp = fopen(themefile, "w"); + if (fp == NULL) { + warn_user(messages_get("gtkFileError"), themefile); + free(filecontent); + return true; + } + val = fwrite(filecontent, strlen(filecontent), 1, fp); + if (val == 0) + LOG(("empty write themelist")); + fclose(fp); + free(filecontent); + return true; + } else { + fp = fopen(themefile, "r"); + if (fp == NULL) { + warn_user(messages_get("gtkFileError"), themefile); + return false; + } + while (fgets(buf, sizeof(buf), fp) != NULL) { + buf[strlen(buf) - 1] = '\0'; + /* "\n\0" -> "\0\0" */ + if (strcmp(buf, themename) == 0) { + fclose(fp); + return false; + } + } + fclose(fp); + return true; + } + +} + +/** + * sets the images for a particular scaffolding according to the current theme + */ + +void nsgtk_theme_implement(struct gtk_scaffolding *g) +{ + struct nsgtk_theme *theme[IMAGE_SET_COUNT]; + int i; + struct nsgtk_button_connect *button; + struct gtk_search *search; + + for (i = 0; i <= IMAGE_SET_POPUP_MENU; i++) + theme[i] = nsgtk_theme_load(GTK_ICON_SIZE_MENU); + + theme[IMAGE_SET_BUTTONS] = + nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR); + + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + if ((i == URL_BAR_ITEM) || (i == THROBBER_ITEM) || + (i == WEBSEARCH_ITEM)) + continue; + button = nsgtk_scaffolding_button(g, i); + if (button == NULL) + continue; + /* gtk_image_menu_item_set_image accepts NULL image */ + if ((button->main != NULL) && + (theme[IMAGE_SET_MAIN_MENU] != NULL)) { + gtk_image_menu_item_set_image(button->main, + GTK_WIDGET( + theme[IMAGE_SET_MAIN_MENU]-> + image[i])); + gtk_widget_show_all(GTK_WIDGET(button->main)); + } + if ((button->rclick != NULL) && + (theme[IMAGE_SET_RCLICK_MENU] != NULL)) { + gtk_image_menu_item_set_image(button->rclick, + GTK_WIDGET( + theme[IMAGE_SET_RCLICK_MENU]-> + image[i])); + gtk_widget_show_all(GTK_WIDGET(button->rclick)); + } + if ((button->popup != NULL) && + (theme[IMAGE_SET_POPUP_MENU] != NULL)) { + gtk_image_menu_item_set_image(button->popup, + GTK_WIDGET( + theme[IMAGE_SET_POPUP_MENU]-> + image[i])); + gtk_widget_show_all(GTK_WIDGET(button->popup)); + } + if ((button->location != -1) && (button->button != NULL) && + (theme[IMAGE_SET_BUTTONS] != NULL)) { + gtk_tool_button_set_icon_widget( + GTK_TOOL_BUTTON(button->button), + GTK_WIDGET( + theme[IMAGE_SET_BUTTONS]-> + image[i])); + gtk_widget_show_all(GTK_WIDGET(button->button)); + } + } + + /* set search bar images */ + search = nsgtk_scaffolding_search(g); + if ((search != NULL) && (theme[IMAGE_SET_MAIN_MENU] != NULL)) { + /* gtk_tool_button_set_icon_widget accepts NULL image */ + if (search->buttons[SEARCH_BACK_BUTTON] != NULL) { + gtk_tool_button_set_icon_widget( + search->buttons[SEARCH_BACK_BUTTON], + GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]-> + searchimage[SEARCH_BACK_BUTTON])); + gtk_widget_show_all(GTK_WIDGET( + search->buttons[SEARCH_BACK_BUTTON])); + } + if (search->buttons[SEARCH_FORWARD_BUTTON] != NULL) { + gtk_tool_button_set_icon_widget( + search->buttons[SEARCH_FORWARD_BUTTON], + GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]-> + searchimage[SEARCH_FORWARD_BUTTON])); + gtk_widget_show_all(GTK_WIDGET( + search->buttons[ + SEARCH_FORWARD_BUTTON])); + } + if (search->buttons[SEARCH_CLOSE_BUTTON] != NULL) { + gtk_tool_button_set_icon_widget( + search->buttons[SEARCH_CLOSE_BUTTON], + GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]-> + searchimage[SEARCH_CLOSE_BUTTON])); + gtk_widget_show_all(GTK_WIDGET( + search->buttons[SEARCH_CLOSE_BUTTON])); + } + } + for (i = 0; i < IMAGE_SET_COUNT; i++) + if (theme[i] != NULL) + free(theme[i]); +} + +/** + * creates a set of images to add to buttons / menus + * loads images from cache, calling an update to the cache when necessary + * \return a struct nsgtk_theme is an array of images + */ + +struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s) +{ + if (current_theme_name == NULL) + return nsgtk_theme_default(s); + + struct nsgtk_theme *theme = malloc(sizeof(struct nsgtk_theme)); + if (theme == NULL) + return theme; + + if ((theme_cache_menu == NULL) || (theme_cache_toolbar == NULL)) + nsgtk_theme_prepare(); + + /* load theme from cache */ + struct nsgtk_theme_cache *cachetheme = (s == GTK_ICON_SIZE_MENU) ? + theme_cache_menu : theme_cache_toolbar; + if (cachetheme == NULL) + return NULL; + +#define SET_BUTTON_IMAGE(p, q, r)\ + if (p->image[q##_BUTTON] != NULL)\ + r->image[q##_BUTTON] = GTK_IMAGE(gtk_image_new_from_pixbuf(\ + p->image[q##_BUTTON]));\ + else\ + r->image[q##_BUTTON] = nsgtk_theme_image_default(\ + q##_BUTTON, s); + + SET_BUTTON_IMAGE(cachetheme, BACK, theme) + SET_BUTTON_IMAGE(cachetheme, HISTORY, theme) + SET_BUTTON_IMAGE(cachetheme, FORWARD, theme) + SET_BUTTON_IMAGE(cachetheme, STOP, theme) + SET_BUTTON_IMAGE(cachetheme, RELOAD, theme) + SET_BUTTON_IMAGE(cachetheme, HOME, theme) + SET_BUTTON_IMAGE(cachetheme, NEWWINDOW, theme) + SET_BUTTON_IMAGE(cachetheme, NEWTAB, theme) + SET_BUTTON_IMAGE(cachetheme, OPENFILE, theme) + SET_BUTTON_IMAGE(cachetheme, CLOSETAB, theme) + SET_BUTTON_IMAGE(cachetheme, CLOSEWINDOW, theme) + SET_BUTTON_IMAGE(cachetheme, SAVEPAGE, theme) + SET_BUTTON_IMAGE(cachetheme, PRINTPREVIEW, theme) + SET_BUTTON_IMAGE(cachetheme, PRINT, theme) + SET_BUTTON_IMAGE(cachetheme, QUIT, theme) + SET_BUTTON_IMAGE(cachetheme, CUT, theme) + SET_BUTTON_IMAGE(cachetheme, COPY, theme) + SET_BUTTON_IMAGE(cachetheme, PASTE, theme) + SET_BUTTON_IMAGE(cachetheme, DELETE, theme) + SET_BUTTON_IMAGE(cachetheme, SELECTALL, theme) + SET_BUTTON_IMAGE(cachetheme, PREFERENCES, theme) + SET_BUTTON_IMAGE(cachetheme, ZOOMPLUS, theme) + SET_BUTTON_IMAGE(cachetheme, ZOOMMINUS, theme) + SET_BUTTON_IMAGE(cachetheme, ZOOMNORMAL, theme) + SET_BUTTON_IMAGE(cachetheme, FULLSCREEN, theme) + SET_BUTTON_IMAGE(cachetheme, VIEWSOURCE, theme) + SET_BUTTON_IMAGE(cachetheme, CONTENTS, theme) + SET_BUTTON_IMAGE(cachetheme, ABOUT, theme) + SET_BUTTON_IMAGE(cachetheme, PDF, theme) + SET_BUTTON_IMAGE(cachetheme, PLAINTEXT, theme) + SET_BUTTON_IMAGE(cachetheme, DRAWFILE, theme) + SET_BUTTON_IMAGE(cachetheme, POSTSCRIPT, theme) + SET_BUTTON_IMAGE(cachetheme, FIND, theme) + SET_BUTTON_IMAGE(cachetheme, DOWNLOADS, theme) + SET_BUTTON_IMAGE(cachetheme, SAVEWINDOWSIZE, theme) + SET_BUTTON_IMAGE(cachetheme, TOGGLEDEBUGGING, theme) + SET_BUTTON_IMAGE(cachetheme, SAVEBOXTREE, theme) + SET_BUTTON_IMAGE(cachetheme, SAVEDOMTREE, theme) + SET_BUTTON_IMAGE(cachetheme, LOCALHISTORY, theme) + SET_BUTTON_IMAGE(cachetheme, GLOBALHISTORY, theme) + SET_BUTTON_IMAGE(cachetheme, ADDBOOKMARKS, theme) + SET_BUTTON_IMAGE(cachetheme, SHOWBOOKMARKS, theme) + SET_BUTTON_IMAGE(cachetheme, OPENLOCATION, theme) + SET_BUTTON_IMAGE(cachetheme, NEXTTAB, theme) + SET_BUTTON_IMAGE(cachetheme, PREVTAB, theme) + SET_BUTTON_IMAGE(cachetheme, GUIDE, theme) + SET_BUTTON_IMAGE(cachetheme, INFO, theme) +#undef SET_BUTTON_IMAGE +#define SET_BUTTON_IMAGE(p, q, qq, r)\ + if (qq->searchimage[SEARCH_##p##_BUTTON] != NULL)\ + r->searchimage[SEARCH_##p##_BUTTON] =\ + GTK_IMAGE(gtk_image_new_from_pixbuf(\ + qq->searchimage[\ + SEARCH_##p##_BUTTON]));\ + else if (qq->image[q##_BUTTON] != NULL)\ + r->searchimage[SEARCH_##p##_BUTTON] =\ + GTK_IMAGE(gtk_image_new_from_pixbuf(\ + qq->image[q##_BUTTON]));\ + else\ + r->searchimage[SEARCH_##p##_BUTTON] =\ + nsgtk_theme_image_default(\ + PLACEHOLDER_BUTTON + SEARCH_##p##_BUTTON, s); + + SET_BUTTON_IMAGE(BACK, BACK, cachetheme, theme) + SET_BUTTON_IMAGE(FORWARD, FORWARD, cachetheme, theme) + SET_BUTTON_IMAGE(CLOSE, CLOSEWINDOW, cachetheme, theme) +#undef SET_BUTTON_IMAGE + return theme; +} + +/** + * caches individual theme images from file + * \param i the toolbar button reference + * \param filename the image file name + * \param path the path to the theme folder + */ +void nsgtk_theme_cache_image(nsgtk_toolbar_button i, const char *filename, + const char *path) +{ + char fullpath[strlen(filename) + strlen(path) + 1]; + sprintf(fullpath, "%s%s", path, filename); + if (theme_cache_toolbar != NULL) + theme_cache_toolbar->image[i] = + gdk_pixbuf_new_from_file_at_size(fullpath, + 24, 24, NULL); + if (theme_cache_menu != NULL) + theme_cache_menu->image[i] = gdk_pixbuf_new_from_file_at_size( + fullpath, 16, 16, NULL); +} + +void nsgtk_theme_cache_searchimage(nsgtk_search_buttons i, + const char *filename, const char *path) +{ + char fullpath[strlen(filename) + strlen(path) + 1]; + sprintf(fullpath, "%s%s", path, filename); + if (theme_cache_toolbar != NULL) + theme_cache_toolbar->searchimage[i] = + gdk_pixbuf_new_from_file_at_size(fullpath, + 24, 24, NULL); + if (theme_cache_menu != NULL) + theme_cache_menu->searchimage[i] = + gdk_pixbuf_new_from_file_at_size(fullpath, + 16, 16, NULL); +} + +/** + * caches theme images from file as pixbufs + */ +void nsgtk_theme_prepare(void) +{ + if (current_theme_name == NULL) + return; + if (theme_cache_menu == NULL) + theme_cache_menu = malloc(sizeof(struct nsgtk_theme_cache)); + if (theme_cache_toolbar == NULL) + theme_cache_toolbar = malloc(sizeof(struct nsgtk_theme_cache)); + size_t len = strlen(res_dir_location) + SLEN("/themes/") + + strlen(current_theme_name) + 1; + char path[len]; + snprintf(path, len, "%sthemes/%s/", res_dir_location, + current_theme_name); +#define CACHE_IMAGE(p, q, r)\ + nsgtk_theme_cache_image(p##_BUTTON, #q ".png", r) + + CACHE_IMAGE(BACK, back, path); + CACHE_IMAGE(HISTORY, history, path); + CACHE_IMAGE(FORWARD, forward, path); + CACHE_IMAGE(STOP, stop, path); + CACHE_IMAGE(RELOAD, reload, path); + CACHE_IMAGE(HOME, home, path); + CACHE_IMAGE(NEWWINDOW, newwindow, path); + CACHE_IMAGE(NEWTAB, newtab, path); + CACHE_IMAGE(OPENFILE, openfile, path); + CACHE_IMAGE(CLOSETAB, closetab, path); + CACHE_IMAGE(CLOSEWINDOW, closewindow, path); + CACHE_IMAGE(SAVEPAGE, savepage, path); + CACHE_IMAGE(PRINTPREVIEW, printpreview, path); + CACHE_IMAGE(PRINT, print, path); + CACHE_IMAGE(QUIT, quit, path); + CACHE_IMAGE(CUT, cut, path); + CACHE_IMAGE(COPY, copy, path); + CACHE_IMAGE(PASTE, paste, path); + CACHE_IMAGE(DELETE, delete, path); + CACHE_IMAGE(SELECTALL, selectall, path); + CACHE_IMAGE(PREFERENCES, preferences, path); + CACHE_IMAGE(ZOOMPLUS, zoomplus, path); + CACHE_IMAGE(ZOOMMINUS, zoomminus, path); + CACHE_IMAGE(ZOOMNORMAL, zoomnormal, path); + CACHE_IMAGE(FULLSCREEN, fullscreen, path); + CACHE_IMAGE(VIEWSOURCE, viewsource, path); + CACHE_IMAGE(CONTENTS, helpcontents, path); + CACHE_IMAGE(ABOUT, helpabout, path); + CACHE_IMAGE(PDF, pdf, path); + CACHE_IMAGE(PLAINTEXT, plaintext, path); + CACHE_IMAGE(DRAWFILE, drawfile, path); + CACHE_IMAGE(POSTSCRIPT, postscript, path); + CACHE_IMAGE(FIND, find, path); + CACHE_IMAGE(DOWNLOADS, downloads, path); + CACHE_IMAGE(SAVEWINDOWSIZE, savewindowsize, path); + CACHE_IMAGE(TOGGLEDEBUGGING, toggledebugging, path); + CACHE_IMAGE(SAVEBOXTREE, boxtree, path); + CACHE_IMAGE(SAVEDOMTREE, domtree, path); + CACHE_IMAGE(LOCALHISTORY, localhistory, path); + CACHE_IMAGE(GLOBALHISTORY, globalhistory, path); + CACHE_IMAGE(ADDBOOKMARKS, addbookmarks, path); + CACHE_IMAGE(SHOWBOOKMARKS, showbookmarks, path); + CACHE_IMAGE(OPENLOCATION, openlocation, path); + CACHE_IMAGE(NEXTTAB, nexttab, path); + CACHE_IMAGE(PREVTAB, prevtab, path); + CACHE_IMAGE(GUIDE, helpguide, path); + CACHE_IMAGE(INFO, helpinfo, path); +#undef CACHE_IMAGE +#define CACHE_IMAGE(p, q, r)\ + nsgtk_theme_cache_searchimage(p, #q ".png", r); + + CACHE_IMAGE(SEARCH_BACK_BUTTON, searchback, path); + CACHE_IMAGE(SEARCH_FORWARD_BUTTON, searchforward, path); + CACHE_IMAGE(SEARCH_CLOSE_BUTTON, searchclose, path); +#undef CACHE_IMAGE +} + +/** + * returns default image for buttons / menu items from gtk stock items + * \param i button reference + */ + +GtkImage *nsgtk_theme_image_default(nsgtk_toolbar_button i, GtkIconSize s) +{ + char *imagefile; + GtkImage *image; + switch(i) { +#define BUTTON_IMAGE(p, q)\ + case p##_BUTTON:\ + return GTK_IMAGE(gtk_image_new_from_stock(#q, s)) + + BUTTON_IMAGE(BACK, gtk-go-back); + case HISTORY_BUTTON: { + size_t len = SLEN("arrow_down_8x32.png") + + strlen(res_dir_location) + 1; + imagefile = malloc(len); + if (imagefile == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + snprintf(imagefile, len, "%sarrow_down_8x32.png", + res_dir_location); + image = GTK_IMAGE(gtk_image_new_from_file(imagefile)); + free(imagefile); + return image; + } + BUTTON_IMAGE(FORWARD, gtk-go-forward); + BUTTON_IMAGE(STOP, gtk-stop); + BUTTON_IMAGE(RELOAD, gtk-refresh); + BUTTON_IMAGE(HOME, gtk-home); + BUTTON_IMAGE(NEWWINDOW, gtk-new); + BUTTON_IMAGE(NEWTAB, gtk-new); + BUTTON_IMAGE(OPENFILE, gtk-open); + BUTTON_IMAGE(CLOSETAB, gtk-close); + BUTTON_IMAGE(CLOSEWINDOW, gtk-close); + BUTTON_IMAGE(SAVEPAGE, gtk-save-as); + BUTTON_IMAGE(PRINTPREVIEW, gtk-print-preview); + BUTTON_IMAGE(PRINT, gtk-print); + BUTTON_IMAGE(QUIT, gtk-quit); + BUTTON_IMAGE(CUT, gtk-cut); + BUTTON_IMAGE(COPY, gtk-copy); + BUTTON_IMAGE(PASTE, gtk-paste); + BUTTON_IMAGE(DELETE, gtk-delete); + BUTTON_IMAGE(SELECTALL, gtk-select-all); + BUTTON_IMAGE(FIND, gtk-find); + BUTTON_IMAGE(PREFERENCES, gtk-preferences); + BUTTON_IMAGE(ZOOMPLUS, gtk-zoom-in); + BUTTON_IMAGE(ZOOMMINUS, gtk-zoom-out); + BUTTON_IMAGE(ZOOMNORMAL, gtk-zoom-100); + BUTTON_IMAGE(FULLSCREEN, gtk-fullscreen); + BUTTON_IMAGE(VIEWSOURCE, gtk-index); + BUTTON_IMAGE(CONTENTS, gtk-help); + BUTTON_IMAGE(ABOUT, gtk-about); +#undef BUTTON_IMAGE + case (PLACEHOLDER_BUTTON + SEARCH_BACK_BUTTON): + return GTK_IMAGE(gtk_image_new_from_stock("gtk-go-back", s)); + case (PLACEHOLDER_BUTTON + SEARCH_FORWARD_BUTTON): + return GTK_IMAGE(gtk_image_new_from_stock("gtk-go-forward", + s)); + case (PLACEHOLDER_BUTTON + SEARCH_CLOSE_BUTTON): + return GTK_IMAGE(gtk_image_new_from_stock("gtk-close", s)); + default: { + size_t len = SLEN("themes/Alpha.png") + + strlen(res_dir_location) + 1; + imagefile = malloc(len); + if (imagefile == NULL) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + snprintf(imagefile, len, "%sthemes/Alpha.png", + res_dir_location); + image = GTK_IMAGE( + gtk_image_new_from_file(imagefile)); + free(imagefile); + return image; + } + } +} + + +#ifdef WITH_THEME_INSTALL +/** + * when CONTENT_THEME needs handling call this function + */ +void theme_install_start(struct content *c) +{ + assert(c); + assert(c->type == CONTENT_THEME); + + /* stop theme sitting in memory cache */ + c->fresh = false; + if (!content_add_user(c, theme_install_callback, 0, 0)) { + warn_user("NoMemory", 0); + return; + } +} + + +/** + * Callback for fetchcache() for theme install fetches. + */ + +void theme_install_callback(content_msg msg, struct content *c, + intptr_t p1, intptr_t p2, union content_msg_data data) +{ + switch (msg) { + case CONTENT_MSG_READY: + break; + + case CONTENT_MSG_DONE: + theme_install_content = c; + if (!theme_install_read(c->source_data, c->source_size)) + warn_user("ThemeInvalid", 0); + break; + + case CONTENT_MSG_ERROR: + warn_user(data.error, 0); + break; + + case CONTENT_MSG_STATUS: + break; + + case CONTENT_MSG_LOADING: + case CONTENT_MSG_REFORMAT: + case CONTENT_MSG_REDRAW: + case CONTENT_MSG_NEWPTR: + case CONTENT_MSG_LAUNCH: + case CONTENT_MSG_AUTH: + default: + assert(0); + break; + } +} + +/** + * handler saves theme data content as a local theme + */ + +bool theme_install_read(const char *data, unsigned long len) +{ + char *filename, *newfilename; + size_t namelen; + int handle = g_file_open_tmp("nsgtkthemeXXXXXX", &filename, NULL); + if (handle == -1) { + warn_user(messages_get("gtkFileError"), + "temporary theme file"); + } + ssize_t written = write(handle, data, len); + close(handle); + if ((unsigned)written != len) + return false; + + /* get name of theme; set as dirname */ + namelen = SLEN("themes/") + strlen(res_dir_location) + 1; + char dirname[namelen]; + snprintf(dirname, namelen, "%sthemes/", res_dir_location); + + /* save individual files in theme */ + newfilename = container_extract_theme(filename, dirname); + g_free(filename); + if (newfilename == NULL) + return false; + nsgtk_theme_add(newfilename); + free(newfilename); + + return true; +} +#endif + +/** + * loads the set of default images for the toolbar / menus + */ + +struct nsgtk_theme *nsgtk_theme_default(GtkIconSize s) +{ + struct nsgtk_theme *theme = malloc(sizeof(struct nsgtk_theme)); + if (theme == NULL) { + warn_user("NoMemory", 0); + return NULL; + } + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON + + SEARCH_BUTTONS_COUNT; i++) + theme->image[i] = nsgtk_theme_image_default(i, s); + return theme; +} + diff --git a/gtk/gtk_theme.h b/gtk/gtk_theme.h new file mode 100644 index 000000000..833379d36 --- /dev/null +++ b/gtk/gtk_theme.h @@ -0,0 +1,46 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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_THEME_H_ +#define _NETSURF_GTK_THEME_H_ + +#include <gtk/gtk.h> +#include "gtk/gtk_scaffolding.h" + +typedef enum search_buttons { + SEARCH_BACK_BUTTON = 0, + SEARCH_FORWARD_BUTTON, + SEARCH_CLOSE_BUTTON, + SEARCH_BUTTONS_COUNT +} nsgtk_search_buttons; + +struct nsgtk_theme { + GtkImage *image[PLACEHOLDER_BUTTON]; + GtkImage *searchimage[SEARCH_BUTTONS_COUNT]; + /* apng throbber element */ +}; + +struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s); +void nsgtk_theme_add(const char *themename); +void nsgtk_theme_init(void); +void nsgtk_theme_prepare(void); +void nsgtk_theme_implement(struct gtk_scaffolding *g); +char *nsgtk_theme_name(void); +void nsgtk_theme_set_name(char *name); + +#endif diff --git a/gtk/gtk_toolbar.c b/gtk/gtk_toolbar.c new file mode 100644 index 000000000..20cfbd812 --- /dev/null +++ b/gtk/gtk_toolbar.c @@ -0,0 +1,1102 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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/>. + */ + +#include <gtk/gtk.h> +#include "desktop/searchweb.h" +#include "gtk/gtk_toolbar.h" +#include "gtk/gtk_gui.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/gtk_search.h" +#include "gtk/gtk_theme.h" +#include "gtk/gtk_throbber.h" +#include "gtk/gtk_window.h" +#include "gtk/sexy_icon_entry.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" + +static GtkTargetEntry entry = {(char *)"nsgtk_button_data", + GTK_TARGET_SAME_APP, 0}; + +static bool edit_mode = false; + +struct nsgtk_toolbar_custom_store { + GtkWidget *window; + GtkWidget *store_buttons[PLACEHOLDER_BUTTON]; + GtkWidget *widgetvbox; + GtkWidget *currentbar; + char numberh; /* current horizontal location while adding */ + GladeXML *glade; /* button widgets to store */ + int buttonlocations[PLACEHOLDER_BUTTON]; + int currentbutton; + bool fromstore; +}; +/* the number of buttons that fit in the width of the store window */ +#define NSGTK_STORE_WIDTH 6 + +/* the 'standard' width of a button that makes sufficient of its label +visible */ +#define NSGTK_BUTTON_WIDTH 111 + +/* the 'standard' height of a button that fits as many toolbars as +possible into the store */ +#define NSGTK_BUTTON_HEIGHT 70 + +/* the 'normal' width of the websearch bar */ +#define NSGTK_WEBSEARCH_WIDTH 150 + +static struct nsgtk_toolbar_custom_store store; +static struct nsgtk_toolbar_custom_store *window = &store; + +static void nsgtk_toolbar_close(nsgtk_scaffolding *g); +static void nsgtk_toolbar_window_open(nsgtk_scaffolding *g); +static void nsgtk_toolbar_customization_save(nsgtk_scaffolding *g); +static void nsgtk_toolbar_add_item_to_toolbar(nsgtk_scaffolding *g, int i, + struct nsgtk_theme *theme); +static bool nsgtk_toolbar_add_store_widget(GtkWidget *widget); +static gboolean nsgtk_toolbar_data(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint time, gpointer data); +static gboolean nsgtk_toolbar_store_return(GtkWidget *widget, GdkDragContext *gdc, gint x, gint y, guint time, gpointer data); +static gboolean nsgtk_toolbar_action(GtkWidget *widget, GdkDragContext + *drag_context, gint x, gint y, guint time, gpointer data); +gboolean nsgtk_toolbar_store_action(GtkWidget *widget, GdkDragContext *gdc, + gint x, gint y, guint time, gpointer data); +static gboolean nsgtk_toolbar_move_complete(GtkWidget *widget, GdkDragContext + *gdc, gint x, gint y, GtkSelectionData *selection, guint info, + guint time, gpointer data); +static void nsgtk_toolbar_clear(GtkWidget *widget, GdkDragContext *gdc, guint + time, gpointer data); +static gboolean nsgtk_toolbar_delete(GtkWidget *widget, GdkEvent *event, + gpointer data); +static gboolean nsgtk_toolbar_cancel_clicked(GtkWidget *widget, gpointer data); +static gboolean nsgtk_toolbar_reset(GtkWidget *widget, gpointer data); +static gboolean nsgtk_toolbar_persist(GtkWidget *widget, gpointer data); +static void nsgtk_toolbar_cast(nsgtk_scaffolding *g); +static GtkWidget *nsgtk_toolbar_make_widget(nsgtk_scaffolding *g, + nsgtk_toolbar_button i, struct nsgtk_theme *theme); +static void nsgtk_toolbar_set_handler(nsgtk_scaffolding *g, + nsgtk_toolbar_button i); +static void nsgtk_toolbar_temp_connect(nsgtk_scaffolding *g, + nsgtk_toolbar_button i); +static void nsgtk_toolbar_clear_toolbar(GtkWidget *widget, gpointer data); +static nsgtk_toolbar_button nsgtk_toolbar_get_id_at_location( + nsgtk_scaffolding *g, int i); + +/** + * change behaviour of scaffoldings while editing toolbar; all buttons as + * well as window clicks are desensitized; then buttons in the front window + * are changed to movable buttons + */ +void nsgtk_toolbar_customization_init(nsgtk_scaffolding *g) +{ + int i; + nsgtk_scaffolding *list = scaf_list; + edit_mode = true; + + while (list) { + g_signal_handler_block(GTK_WIDGET( + nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + nsgtk_window_get_signalhandler( + nsgtk_scaffolding_top_level(list), + NSGTK_WINDOW_SIGNAL_CLICK)); + g_signal_handler_block(GTK_WIDGET( + nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + nsgtk_window_get_signalhandler( + nsgtk_scaffolding_top_level(list), + NSGTK_WINDOW_SIGNAL_REDRAW)); + gtk_widget_modify_bg(GTK_WIDGET(nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + GTK_STATE_NORMAL, &((GdkColor) + {0, 0xEEEE, 0xEEEE, 0xEEEE})); + + if (list == g) { + list = nsgtk_scaffolding_iterate(list); + continue; + } + /* set sensitive for all gui_windows save g */ + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_window( + list)), FALSE); + list = nsgtk_scaffolding_iterate(list); + } + /* set sensitive for all of g save toolbar */ + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)), + FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)), + FALSE); + + /* set editable aspect for toolbar */ + gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)), + nsgtk_toolbar_clear_toolbar, g); + nsgtk_toolbar_set_physical(g); + /* memorize button locations, set editable */ + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + window->buttonlocations[i] = nsgtk_scaffolding_button(g, i) + ->location; + if ((window->buttonlocations[i] == -1) || (i == URL_BAR_ITEM)) + continue; + gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM( + nsgtk_scaffolding_button(g, i)->button), TRUE); + gtk_drag_source_set(GTK_WIDGET(nsgtk_scaffolding_button( + g, i)->button), GDK_BUTTON1_MASK, &entry, 1, + GDK_ACTION_COPY); + nsgtk_toolbar_temp_connect(g, i); + } + + /* add move button listeners */ + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)), + "drag-drop", G_CALLBACK(nsgtk_toolbar_data), g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)), + "drag-data-received", G_CALLBACK( + nsgtk_toolbar_move_complete), g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)), + "drag-motion", G_CALLBACK(nsgtk_toolbar_action), g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)), + "drag-leave", G_CALLBACK( + nsgtk_toolbar_clear), g); + + /* set data types */ + gtk_drag_dest_set(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)), + GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, + &entry, 1, GDK_ACTION_COPY); + + /* open toolbar window */ + nsgtk_toolbar_window_open(g); +} + +/** + * create store window + */ +void nsgtk_toolbar_window_open(nsgtk_scaffolding *g) +{ + int x = 0, y = 0; + struct nsgtk_theme *theme = + nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR); + if (theme == NULL) { + warn_user(messages_get("NoMemory"), 0); + nsgtk_toolbar_cancel_clicked(NULL, g); + return; + } + window->glade = glade_xml_new(glade_toolbar_file_location, + "toolbarwindow", NULL); + if (window->glade == NULL) { + warn_user(messages_get("NoMemory"), 0); + nsgtk_toolbar_cancel_clicked(NULL, g); + } + glade_xml_signal_autoconnect(window->glade); + +#define GET_TOOLWIDGET(p, q, r, s) r->p = glade_xml_get_widget(r->s, #q);\ + if (r->p == NULL) {\ + warn_user(messages_get("NoMemory"), 0);\ + nsgtk_toolbar_cancel_clicked(NULL, g);\ + return;\ + } + + GET_TOOLWIDGET(window, toolbarwindow, window, glade) + GET_TOOLWIDGET(widgetvbox, widgetvbox, window, glade) +#undef GET_TOOLWIDGET + + window->numberh = NSGTK_STORE_WIDTH; /* preset to width [in buttons] of */ + /* store to cause creation of a new toolbar */ + window->currentbutton = -1; + /* load toolbuttons */ + /* add toolbuttons to window */ + /* set event handlers */ + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + if (i == URL_BAR_ITEM) + continue; + window->store_buttons[i] = + nsgtk_toolbar_make_widget(g, i, theme); + if (window->store_buttons[i] == NULL) { + warn_user(messages_get("NoMemory"), 0); + continue; + } + nsgtk_toolbar_add_store_widget(window->store_buttons[i]); + g_signal_connect(window->store_buttons[i], "drag-data-get", + G_CALLBACK( + nsgtk_scaffolding_button(g, i)->dataplus), g); + } + free(theme); + gtk_window_set_transient_for(GTK_WINDOW(window->window), + nsgtk_scaffolding_window(g)); + gtk_window_set_title(GTK_WINDOW(window->window), messages_get( + "gtkToolBarTitle")); + gtk_window_set_accept_focus(GTK_WINDOW(window->window), FALSE); + gtk_drag_dest_set(GTK_WIDGET(window->window), GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_DROP, &entry, 1, GDK_ACTION_COPY); + gtk_widget_show_all(window->window); + gtk_window_set_position(GTK_WINDOW(window->window), + GTK_WIN_POS_CENTER_ON_PARENT); + gtk_window_get_position(nsgtk_scaffolding_window(g), &x, &y); + gtk_window_move(GTK_WINDOW(window->window), x, y + 100); + g_signal_connect(glade_xml_get_widget(window->glade, "cancelbutton"), + "clicked", G_CALLBACK( + nsgtk_toolbar_cancel_clicked), g); + g_signal_connect(glade_xml_get_widget(window->glade, "okbutton"), + "clicked", G_CALLBACK(nsgtk_toolbar_persist), g); + g_signal_connect(glade_xml_get_widget(window->glade, "resetbutton"), + "clicked", G_CALLBACK(nsgtk_toolbar_reset), g); + g_signal_connect(window->window, "delete-event", + G_CALLBACK(nsgtk_toolbar_delete), g); + g_signal_connect(window->window, "drag-drop", + G_CALLBACK(nsgtk_toolbar_store_return), g); + g_signal_connect(window->window, "drag-motion", + G_CALLBACK(nsgtk_toolbar_store_action), g); +} + +/** + * when titlebar / alt-F4 window close event happens + */ +gboolean nsgtk_toolbar_delete(GtkWidget *widget, GdkEvent *event, + gpointer data) +{ + edit_mode = false; + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + /* reset g->buttons->location */ + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + nsgtk_scaffolding_button(g, i)->location = + window->buttonlocations[i]; + } + nsgtk_toolbar_set_physical(g); + nsgtk_toolbar_connect_all(g); + nsgtk_toolbar_close(g); + nsgtk_scaffolding_set_sensitivity(g); + gtk_widget_destroy(window->window); + return TRUE; +} + +/** + * when cancel button is clicked + */ +gboolean nsgtk_toolbar_cancel_clicked(GtkWidget *widget, gpointer data) +{ + edit_mode = false; + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + /* reset g->buttons->location */ + for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + nsgtk_scaffolding_button(g, i)->location = + window->buttonlocations[i]; + } + nsgtk_toolbar_set_physical(g); + nsgtk_toolbar_connect_all(g); + nsgtk_toolbar_close(g); + nsgtk_scaffolding_set_sensitivity(g); + gtk_widget_destroy(window->window); + return TRUE; +} + +/** + * when 'save settings' button is clicked + */ +gboolean nsgtk_toolbar_persist(GtkWidget *widget, gpointer data) +{ + edit_mode = false; + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + /* save state to file, update toolbars for all windows */ + nsgtk_toolbar_customization_save(g); + nsgtk_toolbar_cast(g); + nsgtk_toolbar_set_physical(g); + nsgtk_toolbar_close(g); + gtk_widget_destroy(window->window); + return TRUE; +} + +/** + * when 'reload defaults' button is clicked + */ +gboolean nsgtk_toolbar_reset(GtkWidget *widget, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + int i; + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) + nsgtk_scaffolding_button(g, i)->location = + (i <= THROBBER_ITEM) ? i : -1; + nsgtk_toolbar_set_physical(g); + for (i = BACK_BUTTON; i <= THROBBER_ITEM; i++) { + if (i == URL_BAR_ITEM) + continue; + gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM( + nsgtk_scaffolding_button(g, i)->button), TRUE); + gtk_drag_source_set(GTK_WIDGET( + nsgtk_scaffolding_button(g, i)->button), + GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_COPY); + nsgtk_toolbar_temp_connect(g, i); + } + return TRUE; +} + +/** + * set toolbar logical -> physical; physically visible toolbar buttons are made + * to correspond to the logically stored schema in terms of location + * visibility etc + */ +void nsgtk_toolbar_set_physical(nsgtk_scaffolding *g) +{ + int i; + struct nsgtk_theme *theme = + nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR); + if (theme == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + /* simplest is to clear the toolbar then reload it from memory */ + gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)), + nsgtk_toolbar_clear_toolbar, g); + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) + nsgtk_toolbar_add_item_to_toolbar(g, i, theme); + gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar(g))); + free(theme); +} + +/** + * cleanup code physical update of all toolbars; resensitize + * \param g the 'front' scaffolding that called customize + */ +void nsgtk_toolbar_close(nsgtk_scaffolding *g) +{ + int i; + nsgtk_scaffolding *list = scaf_list; + while (list) { + struct nsgtk_theme *theme = + nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR); + if (theme == NULL) { + warn_user(messages_get("NoMemory"), 0); + continue; + } + /* clear toolbar */ + gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar( + list)), nsgtk_toolbar_clear_toolbar, list); + /* then add items */ + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + nsgtk_toolbar_add_item_to_toolbar(list, i, theme); + } + nsgtk_toolbar_connect_all(list); + gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar( + list))); + nsgtk_scaffolding_set_sensitivity(list); + gtk_widget_modify_bg(GTK_WIDGET(nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + GTK_STATE_NORMAL, &((GdkColor) + {0, 0xFFFF, 0xFFFF, 0xFFFF})); + g_signal_handler_unblock(GTK_WIDGET( + nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + nsgtk_window_get_signalhandler( + nsgtk_scaffolding_top_level(list), + NSGTK_WINDOW_SIGNAL_CLICK)); + g_signal_handler_unblock(GTK_WIDGET( + nsgtk_window_get_drawing_area( + nsgtk_scaffolding_top_level(list))), + nsgtk_window_get_signalhandler( + nsgtk_scaffolding_top_level(list), + NSGTK_WINDOW_SIGNAL_REDRAW)); + if ((gui_window_get_browser_window(nsgtk_scaffolding_top_level( + list))->current_content != NULL) && + (gui_window_get_browser_window( + nsgtk_scaffolding_top_level(list))-> + current_content->url != NULL)) + browser_window_refresh_url_bar( + gui_window_get_browser_window( + nsgtk_scaffolding_top_level(list)), + gui_window_get_browser_window( + nsgtk_scaffolding_top_level(list))-> + current_content->url, + gui_window_get_browser_window( + nsgtk_scaffolding_top_level(list))-> + frag_id); + + if (list != g) + gtk_widget_set_sensitive(GTK_WIDGET( + nsgtk_scaffolding_window(list)), TRUE); + free(theme); + list = nsgtk_scaffolding_iterate(list); + } + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)), + TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)), + TRUE); + /* update favicon etc */ + nsgtk_scaffolding_set_top_level(nsgtk_scaffolding_top_level(g)); + if (search_web_ico()) + gui_window_set_search_ico(search_web_ico()); +} + +/** + * callback function to iterate toolbar's widgets + */ +void nsgtk_toolbar_clear_toolbar(GtkWidget *widget, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + gtk_container_remove(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)), widget); +} + +/** + * add item to toolbar + * \param g the scaffolding whose toolbar an item is added to + * \param i the location in the toolbar + * the function should be called, when multiple items are being added, + * in ascending order + */ +void nsgtk_toolbar_add_item_to_toolbar(nsgtk_scaffolding *g, int i, + struct nsgtk_theme *theme) +{ + int q; + for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++) + if (nsgtk_scaffolding_button(g, q)->location == i) { + nsgtk_scaffolding_button(g, q)->button = GTK_TOOL_ITEM( + nsgtk_toolbar_make_widget(g, q, + theme)); + gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g), + nsgtk_scaffolding_button(g, q)->button, + i); + break; + } +} + +/** + * physically add widgets to store window + */ +bool nsgtk_toolbar_add_store_widget(GtkWidget *widget) +{ + if (window->numberh >= NSGTK_STORE_WIDTH) { + window->currentbar = gtk_toolbar_new(); + if (window->currentbar == NULL) { + warn_user("NoMemory", 0); + return false; + } + gtk_toolbar_set_style(GTK_TOOLBAR(window->currentbar), + GTK_TOOLBAR_BOTH); + gtk_toolbar_set_icon_size(GTK_TOOLBAR(window->currentbar), + GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_box_pack_start(GTK_BOX(window->widgetvbox), + window->currentbar, FALSE, FALSE, 0); + window->numberh = 0; + } + gtk_widget_set_size_request(widget, NSGTK_BUTTON_WIDTH, + NSGTK_BUTTON_HEIGHT); + gtk_toolbar_insert(GTK_TOOLBAR(window->currentbar), GTK_TOOL_ITEM( + widget), window->numberh++); + gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(widget), TRUE); + gtk_drag_source_set(widget, GDK_BUTTON1_MASK, &entry, 1, + GDK_ACTION_COPY); + gtk_widget_show_all(window->window); + return true; +} + +/** + * called when a widget is dropped onto the toolbar + */ +gboolean nsgtk_toolbar_data(GtkWidget *widget, GdkDragContext *gdc, gint x, + gint y, guint time, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + int ind = gtk_toolbar_get_drop_index(nsgtk_scaffolding_toolbar(g), + x, y); + int q, i; + if (window->currentbutton == -1) + return TRUE; + struct nsgtk_theme *theme = + nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR); + if (theme == NULL) { + warn_user(messages_get("NoMemory"), 0); + return TRUE; + } + if (nsgtk_scaffolding_button(g, window->currentbutton)->location + != -1) { + /* widget was already in the toolbar; so replace */ + if (nsgtk_scaffolding_button(g, window->currentbutton)-> + location < ind) + ind--; + gtk_container_remove(GTK_CONTAINER( + nsgtk_scaffolding_toolbar(g)), GTK_WIDGET( + nsgtk_scaffolding_button(g, + window->currentbutton)->button)); + /* 'move' all widgets further right than the original location, + * one place to the left in logical schema */ + for (i = nsgtk_scaffolding_button(g, window->currentbutton)-> + location + 1; i < PLACEHOLDER_BUTTON; i++) { + q = nsgtk_toolbar_get_id_at_location(g, i); + if (q == -1) + continue; + nsgtk_scaffolding_button(g, q)->location--; + } + nsgtk_scaffolding_button(g, window->currentbutton)-> + location = -1; + } + nsgtk_scaffolding_button(g, window->currentbutton)->button = + GTK_TOOL_ITEM(nsgtk_toolbar_make_widget(g, + window->currentbutton, theme)); + free(theme); + if (nsgtk_scaffolding_button(g, window->currentbutton)->button + == NULL) { + warn_user("NoMemory", 0); + return TRUE; + } + /* update logical schema */ + nsgtk_scaffolding_reset_offset(g); + /* 'move' all widgets further right than the new location, one place to + * the right in logical schema */ + for (i = PLACEHOLDER_BUTTON - 1; i >= ind; i--) { + q = nsgtk_toolbar_get_id_at_location(g, i); + if (q == -1) + continue; + nsgtk_scaffolding_button(g, q)->location++; + } + nsgtk_scaffolding_button(g, window->currentbutton)->location = ind; + + /* complete action */ + gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g), + nsgtk_scaffolding_button(g, + window->currentbutton)->button, ind); + gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM( + nsgtk_scaffolding_button(g, + window->currentbutton)->button), TRUE); + gtk_drag_source_set(GTK_WIDGET( + nsgtk_scaffolding_button(g, + window->currentbutton)->button), + GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_COPY); + nsgtk_toolbar_temp_connect(g, window->currentbutton); + gtk_widget_show_all(GTK_WIDGET( + nsgtk_scaffolding_button(g, + window->currentbutton)->button)); + window->currentbutton = -1; + return TRUE; +} + +/** + * connected to toolbutton drop; perhaps one day it'll work properly so it may + * replace the global current_button + */ + +gboolean nsgtk_toolbar_move_complete(GtkWidget *widget, GdkDragContext *gdc, + gint x, gint y, GtkSelectionData *selection, guint info, + guint time, gpointer data) +{ + return FALSE; +} + +/** + * called when a widget is dropped onto the store window + */ +gboolean nsgtk_toolbar_store_return(GtkWidget *widget, GdkDragContext *gdc, + gint x, gint y, guint time, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + int q, i; + + if ((window->fromstore) || (window->currentbutton == -1)) { + window->currentbutton = -1; + return FALSE; + } + if (nsgtk_scaffolding_button(g, window->currentbutton)->location + != -1) { + /* 'move' all widgets further right, one place to the left + * in logical schema */ + for (i = nsgtk_scaffolding_button(g, window->currentbutton)-> + location + 1; i < PLACEHOLDER_BUTTON; i++) { + q = nsgtk_toolbar_get_id_at_location(g, i); + if (q == -1) + continue; + nsgtk_scaffolding_button(g, q)->location--; + } + gtk_container_remove(GTK_CONTAINER( + nsgtk_scaffolding_toolbar(g)), GTK_WIDGET( + nsgtk_scaffolding_button(g, + window->currentbutton)->button)); + nsgtk_scaffolding_button(g, window->currentbutton)->location + = -1; + } + window->currentbutton = -1; + gtk_drag_finish(gdc, TRUE, TRUE, time); + return FALSE; +} +/** + * called when hovering an item above the toolbar + */ +gboolean nsgtk_toolbar_action(GtkWidget *widget, GdkDragContext *gdc, gint x, + gint y, guint time, gpointer data) +{ + nsgtk_scaffolding *g = (nsgtk_scaffolding *)data; + GtkToolItem *item = gtk_tool_button_new(NULL, NULL); + if (item != NULL) + gtk_toolbar_set_drop_highlight_item( + nsgtk_scaffolding_toolbar(g), + GTK_TOOL_ITEM(item), + gtk_toolbar_get_drop_index( + nsgtk_scaffolding_toolbar(g), x, y)); + return FALSE; +} + +/** + * called when hovering above the store + */ +gboolean nsgtk_toolbar_store_action(GtkWidget *widget, GdkDragContext *gdc, + gint x, gint y, guint time, gpointer data) +{ + return FALSE; +} +/** + * called when hovering stops + */ +void nsgtk_toolbar_clear(GtkWidget *widget, GdkDragContext *gdc, guint time, + gpointer data) +{ + gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(widget), NULL, 0); +} + +/** + * widget factory for creation of toolbar item widgets + * \param g the reference scaffolding + * \param i the id of the widget + * \param theme the theme to make the widgets from + */ +GtkWidget *nsgtk_toolbar_make_widget(nsgtk_scaffolding *g, + nsgtk_toolbar_button i, struct nsgtk_theme *theme) +{ + switch(i) { + +/* gtk_tool_button_new() accepts NULL args */ +#define MAKE_STOCKBUTTON(p, q) case p##_BUTTON: {\ + GtkStockItem item;\ + char *label = NULL;\ + gtk_stock_lookup(#q, &item);\ + if (item.label != NULL)\ + label = remove_underscores(item.label, false);\ + GtkWidget *w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(\ + theme->image[p##_BUTTON]), label));\ + if (label != NULL) {\ + free(label);\ + label = NULL;\ + }\ + return w;\ + } + + MAKE_STOCKBUTTON(HOME, gtk-home) + MAKE_STOCKBUTTON(BACK, gtk-go-back) + MAKE_STOCKBUTTON(FORWARD, gtk-go-forward) + MAKE_STOCKBUTTON(STOP, gtk-stop) + MAKE_STOCKBUTTON(RELOAD, gtk-refresh) +#undef MAKE_STOCKBUTTON + case HISTORY_BUTTON: + return GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( + theme->image[HISTORY_BUTTON]), NULL)); + case URL_BAR_ITEM: { + char imagefile[strlen(res_dir_location) + SLEN("html.png") + + 1]; + sprintf(imagefile, "%shtml.png", res_dir_location); + GtkWidget *image = GTK_WIDGET(gtk_image_new_from_file( + imagefile)); + GtkWidget *entry = GTK_WIDGET(sexy_icon_entry_new()); + GtkWidget *w = GTK_WIDGET(gtk_tool_item_new()); + if ((entry == NULL) || (w == NULL)) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + + if (image != NULL) + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry), + SEXY_ICON_ENTRY_PRIMARY, + GTK_IMAGE(image)); + gtk_container_add(GTK_CONTAINER(w), entry); + gtk_tool_item_set_expand(GTK_TOOL_ITEM(w), TRUE); + return w; + } + case THROBBER_ITEM: { + if (edit_mode) + return GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( + gtk_image_new_from_pixbuf( + nsgtk_throbber->framedata[0])), + "[throbber]")); + if ((nsgtk_throbber == NULL) || (nsgtk_throbber->framedata == + NULL) || (nsgtk_throbber->framedata[0] == + NULL)) + return NULL; + GtkWidget *image = GTK_WIDGET(gtk_image_new_from_pixbuf( + nsgtk_throbber->framedata[0])); + GtkWidget *w = GTK_WIDGET(gtk_tool_item_new()); + GtkWidget *al = GTK_WIDGET(gtk_alignment_new(0.1,0.1,0.8,0.8)); + if ((w == NULL) || (al == NULL)) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + gtk_alignment_set_padding(GTK_ALIGNMENT(al), 0, 0, 6, 0); + if (image != NULL) + gtk_container_add(GTK_CONTAINER(al), image); + gtk_container_add(GTK_CONTAINER(w), al); + return w; + } + case WEBSEARCH_ITEM: { + if (edit_mode) + return GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( + gtk_image_new_from_stock("gtk-find", + GTK_ICON_SIZE_LARGE_TOOLBAR)), + "[websearch]")); + GtkWidget *image = GTK_WIDGET(gtk_image_new_from_stock( + "gtk-info", GTK_ICON_SIZE_LARGE_TOOLBAR)); + GtkWidget *entry = GTK_WIDGET(sexy_icon_entry_new()); + GtkWidget *w = GTK_WIDGET(gtk_tool_item_new()); + if ((entry == NULL) || (w == NULL)) { + warn_user(messages_get("NoMemory"), 0); + return NULL; + } + + gtk_widget_set_size_request(entry, NSGTK_WEBSEARCH_WIDTH, + -1); + if (image != NULL) + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry), + SEXY_ICON_ENTRY_PRIMARY, + GTK_IMAGE(image)); + gtk_container_add(GTK_CONTAINER(w), entry); + return w; + } + +/* gtk_tool_button_new accepts NULL args */ +#define MAKE_MENUBUTTON(p, q) case p##_BUTTON: {\ + char *label = NULL;\ + label = remove_underscores(messages_get(#q), false);\ + GtkWidget *w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(\ + theme->image[p##_BUTTON]), label));\ + if (label != NULL)\ + free(label);\ + return w;\ + } + + MAKE_MENUBUTTON(NEWWINDOW, gtkNewWindow) + MAKE_MENUBUTTON(NEWTAB, gtkNewTab) + MAKE_MENUBUTTON(OPENFILE, gtkOpenFile) + MAKE_MENUBUTTON(CLOSETAB, gtkCloseTab) + MAKE_MENUBUTTON(CLOSEWINDOW, gtkCloseWindow) + MAKE_MENUBUTTON(SAVEPAGE, gtkSavePage) + MAKE_MENUBUTTON(PRINTPREVIEW, gtkPrintPreview) + MAKE_MENUBUTTON(PRINT, gtkPrint) + MAKE_MENUBUTTON(QUIT, gtkQuitMenu) + MAKE_MENUBUTTON(CUT, gtkCut) + MAKE_MENUBUTTON(COPY, gtkCopy) + MAKE_MENUBUTTON(PASTE, gtkPaste) + MAKE_MENUBUTTON(DELETE, gtkDelete) + MAKE_MENUBUTTON(SELECTALL, gtkSelectAll) + MAKE_MENUBUTTON(PREFERENCES, gtkPreferences) + MAKE_MENUBUTTON(ZOOMPLUS, gtkZoomPlus) + MAKE_MENUBUTTON(ZOOMMINUS, gtkZoomMinus) + MAKE_MENUBUTTON(ZOOMNORMAL, gtkZoomNormal) + MAKE_MENUBUTTON(FULLSCREEN, gtkFullScreen) + MAKE_MENUBUTTON(VIEWSOURCE, gtkViewSource) + MAKE_MENUBUTTON(CONTENTS, gtkContents) + MAKE_MENUBUTTON(ABOUT, gtkAbout) + MAKE_MENUBUTTON(PDF, gtkPDF) + MAKE_MENUBUTTON(PLAINTEXT, gtkPlainText) + MAKE_MENUBUTTON(DRAWFILE, gtkDrawFile) + MAKE_MENUBUTTON(POSTSCRIPT, gtkPostScript) + MAKE_MENUBUTTON(FIND, gtkFind) + MAKE_MENUBUTTON(DOWNLOADS, gtkDownloads) + MAKE_MENUBUTTON(SAVEWINDOWSIZE, gtkSaveWindowSize) + MAKE_MENUBUTTON(TOGGLEDEBUGGING, gtkToggleDebugging) + MAKE_MENUBUTTON(SAVEBOXTREE, gtkSaveBoxTree) + MAKE_MENUBUTTON(SAVEDOMTREE, gtkSaveDomTree) + MAKE_MENUBUTTON(LOCALHISTORY, gtkLocalHistory) + MAKE_MENUBUTTON(GLOBALHISTORY, gtkGlobalHistory) + MAKE_MENUBUTTON(ADDBOOKMARKS, gtkAddBookMarks) + MAKE_MENUBUTTON(SHOWBOOKMARKS, gtkShowBookMarks) + MAKE_MENUBUTTON(OPENLOCATION, gtkOpenLocation) + MAKE_MENUBUTTON(NEXTTAB, gtkNextTab) + MAKE_MENUBUTTON(PREVTAB, gtkPrevTab) + MAKE_MENUBUTTON(GUIDE, gtkGuide) + MAKE_MENUBUTTON(INFO, gtkUserInformation) + default: + return NULL; +#undef MAKE_MENUBUTTON + } +} + +/** + * \return toolbar item id when a widget is an element of the scaffolding + * else -1 + */ +int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget, nsgtk_scaffolding *g) +{ + int i; + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + if ((nsgtk_scaffolding_button(g, i)->location != -1) + && (widget == GTK_WIDGET( + nsgtk_scaffolding_button(g, i)->button))) { + return i; + } + } + return -1; +} + +/** + * \return toolbar item id from location when there is an item at that logical + * location; else -1 + */ +nsgtk_toolbar_button nsgtk_toolbar_get_id_at_location(nsgtk_scaffolding *g, + int i) +{ + int q; + for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++) + if (nsgtk_scaffolding_button(g, q)->location == i) + return q; + return -1; +} + +/** + * connect 'normal' handlers to toolbar buttons + */ + +void nsgtk_toolbar_connect_all(nsgtk_scaffolding *g) +{ + int q, i; + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + q = nsgtk_toolbar_get_id_at_location(g, i); + if (q == -1) + continue; + if (nsgtk_scaffolding_button(g, q)->button != NULL) + g_signal_connect( + nsgtk_scaffolding_button(g, q)->button, + "size-allocate", G_CALLBACK( + nsgtk_scaffolding_toolbar_size_allocate + ), g); + nsgtk_toolbar_set_handler(g, q); + } +} + +/** + * add handlers to factory widgets + * \param g the scaffolding to attach handlers to + * \param i the toolbar item id + */ +void nsgtk_toolbar_set_handler(nsgtk_scaffolding *g, nsgtk_toolbar_button i) +{ + switch(i){ + case URL_BAR_ITEM: + nsgtk_scaffolding_update_url_bar_ref(g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)), + "activate", G_CALLBACK( + nsgtk_window_url_activate_event), g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)), + "changed", G_CALLBACK( + nsgtk_window_url_changed), g); + break; + case THROBBER_ITEM: + nsgtk_scaffolding_update_throbber_ref(g); + break; + case WEBSEARCH_ITEM: + nsgtk_scaffolding_update_websearch_ref(g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)), + "activate", G_CALLBACK( + nsgtk_websearch_activate), g); + g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)), + "button-press-event", G_CALLBACK( + nsgtk_websearch_clear), g); + break; + default: + if ((nsgtk_scaffolding_button(g, i)->bhandler != NULL) && + (nsgtk_scaffolding_button(g, i)->button + != NULL)) + g_signal_connect(nsgtk_scaffolding_button(g, i)-> + button, "clicked", + G_CALLBACK(nsgtk_scaffolding_button(g, + i)->bhandler), g); + break; + } +} + +#define DATAHANDLER(p, q, r)\ +gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\ + *cont, GtkSelectionData *selection, guint info, guint time,\ + gpointer data)\ +{\ + r->currentbutton = q##_BUTTON;\ + r->fromstore = true;\ + return TRUE;\ +}\ +gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\ + GdkDragContext *cont, GtkSelectionData *selection, guint info,\ + guint time, gpointer data)\ +{\ + r->currentbutton = q##_BUTTON;\ + r->fromstore = false;\ + return TRUE;\ +} + +DATAHANDLER(home, HOME, window) +DATAHANDLER(forward, FORWARD, window) +DATAHANDLER(back, BACK, window) +DATAHANDLER(stop, STOP, window) +DATAHANDLER(reload, RELOAD, window) +DATAHANDLER(history, HISTORY, window) +DATAHANDLER(newwindow, NEWWINDOW, window) +DATAHANDLER(newtab, NEWTAB, window) +DATAHANDLER(openfile, OPENFILE, window) +DATAHANDLER(closetab, CLOSETAB, window) +DATAHANDLER(closewindow, CLOSEWINDOW, window) +DATAHANDLER(savepage, SAVEPAGE, window) +DATAHANDLER(printpreview, PRINTPREVIEW, window) +DATAHANDLER(print, PRINT, window) +DATAHANDLER(quit, QUIT, window) +DATAHANDLER(cut, CUT, window) +DATAHANDLER(copy, COPY, window) +DATAHANDLER(paste, PASTE, window) +DATAHANDLER(delete, DELETE, window) +DATAHANDLER(selectall, SELECTALL, window) +DATAHANDLER(preferences, PREFERENCES, window) +DATAHANDLER(zoomplus, ZOOMPLUS, window) +DATAHANDLER(zoomminus, ZOOMMINUS, window) +DATAHANDLER(zoomnormal, ZOOMNORMAL, window) +DATAHANDLER(fullscreen, FULLSCREEN, window) +DATAHANDLER(viewsource, VIEWSOURCE, window) +DATAHANDLER(contents, CONTENTS, window) +DATAHANDLER(about, ABOUT, window) +DATAHANDLER(pdf, PDF, window) +DATAHANDLER(plaintext, PLAINTEXT, window) +DATAHANDLER(drawfile, DRAWFILE, window) +DATAHANDLER(postscript, POSTSCRIPT, window) +DATAHANDLER(find, FIND, window) +DATAHANDLER(downloads, DOWNLOADS, window) +DATAHANDLER(savewindowsize, SAVEWINDOWSIZE, window) +DATAHANDLER(toggledebugging, TOGGLEDEBUGGING, window) +DATAHANDLER(saveboxtree, SAVEBOXTREE, window) +DATAHANDLER(savedomtree, SAVEDOMTREE, window) +DATAHANDLER(localhistory, LOCALHISTORY, window) +DATAHANDLER(globalhistory, GLOBALHISTORY, window) +DATAHANDLER(addbookmarks, ADDBOOKMARKS, window) +DATAHANDLER(showbookmarks, SHOWBOOKMARKS, window) +DATAHANDLER(openlocation, OPENLOCATION, window) +DATAHANDLER(nexttab, NEXTTAB, window) +DATAHANDLER(prevtab, PREVTAB, window) +DATAHANDLER(guide, GUIDE, window) +DATAHANDLER(info, INFO, window) +#undef DATAHANDLER +#define DATAHANDLER(p, q, r)\ +gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\ + *cont, GtkSelectionData *selection, guint info, guint time,\ + gpointer data)\ +{\ + r->currentbutton = q##_ITEM;\ + r->fromstore = true;\ + return TRUE;\ +}\ +gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\ + GdkDragContext *cont, GtkSelectionData *selection, guint info,\ + guint time, gpointer data)\ +{\ + r->currentbutton = q##_ITEM;\ + r->fromstore = false;\ + return TRUE;\ +} + +DATAHANDLER(throbber, THROBBER, window) +DATAHANDLER(websearch, WEBSEARCH, window) +#undef DATAHANDLER + +/** + * connect temporary handler for toolbar edit events + */ +void nsgtk_toolbar_temp_connect(nsgtk_scaffolding *g, nsgtk_toolbar_button i) +{ + if ((i == URL_BAR_ITEM) || + (nsgtk_scaffolding_button(g, i)->button == NULL) || + (nsgtk_scaffolding_button(g, i)->dataminus == NULL)) + return; + g_signal_connect(nsgtk_scaffolding_button(g, i)->button, + "drag-data-get", G_CALLBACK(nsgtk_scaffolding_button( + g, i)->dataminus), g); +} + +/** + * load toolbar settings from file; file is a set of fields arranged as + * <itemreference>;<itemlocation>|<itemreference>;<itemlocation>| etc + */ +void nsgtk_toolbar_customization_load(nsgtk_scaffolding *g) +{ + int i, ii; + char *val; + char buffer[SLEN("11;|") * 2 * PLACEHOLDER_BUTTON]; /* numbers 0-99 */ + buffer[0] = '\0'; + char *buffer1, *subbuffer, *ptr = NULL, *pter = NULL; + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) + nsgtk_scaffolding_button(g, i)->location = + (i <= THROBBER_ITEM) ? i : -1; + FILE *f = fopen(toolbar_indices_file_location, "r"); + if (f == NULL) { + warn_user(messages_get("gtkFileError"), + toolbar_indices_file_location); + return; + } + val = fgets(buffer, sizeof buffer, f); + if (val == NULL) + LOG(("empty read toolbar settings")); + fclose(f); + i = BACK_BUTTON; + ii = BACK_BUTTON; + buffer1 = strtok_r(buffer, "|", &ptr); + while (buffer1 != NULL) { + subbuffer = strtok_r(buffer1, ";", &pter); + i = atoi(subbuffer); + subbuffer = strtok_r(NULL, ";", &pter); + ii = atoi(subbuffer); + if ((i >= BACK_BUTTON) && (i < PLACEHOLDER_BUTTON) && + (ii >= -1) && (ii < PLACEHOLDER_BUTTON)) { + nsgtk_scaffolding_button(g, i)->location = ii; + } + buffer1 = strtok_r(NULL, "|", &ptr); + } +} + +/** + * cast toolbar settings to all scaffoldings referenced from the global linked + * list of gui_windows + */ +void nsgtk_toolbar_cast(nsgtk_scaffolding *g) +{ + int i; + nsgtk_scaffolding *list = scaf_list; + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) + window->buttonlocations[i] = + ((nsgtk_scaffolding_button(g, i)->location + >= -1) && + (nsgtk_scaffolding_button(g, i)->location + < PLACEHOLDER_BUTTON)) ? + nsgtk_scaffolding_button(g, i)->location : -1; + while (list) { + if (list != g) + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) + nsgtk_scaffolding_button(list, i)->location = + window->buttonlocations[i]; + list = nsgtk_scaffolding_iterate(list); + } +} + +/** + * save toolbar settings to file + */ +void nsgtk_toolbar_customization_save(nsgtk_scaffolding *g) +{ + int i; + FILE *f = fopen(toolbar_indices_file_location, "w"); + if (f == NULL){ + warn_user("gtkFileError", toolbar_indices_file_location); + return; + } + for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) { + fprintf(f, "%d;%d|", i, nsgtk_scaffolding_button(g, i)->location); + } + fclose(f); +} + diff --git a/gtk/gtk_toolbar.h b/gtk/gtk_toolbar.h new file mode 100644 index 000000000..a470a4480 --- /dev/null +++ b/gtk/gtk_toolbar.h @@ -0,0 +1,90 @@ +/* + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * 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_TOOLBAR_H_ +#define _NETSURF_GTK_TOOLBAR_H_ + +#include <gtk/gtk.h> +#include "gtk/gtk_scaffolding.h" + +void nsgtk_toolbar_customization_init(nsgtk_scaffolding *g); +void nsgtk_toolbar_init(nsgtk_scaffolding *g); +void nsgtk_toolbar_customization_load(nsgtk_scaffolding *g); +void nsgtk_toolbar_set_physical(nsgtk_scaffolding *g); +void nsgtk_toolbar_connect_all(nsgtk_scaffolding *g); +int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget, nsgtk_scaffolding + *g); + +#define TOOLPROTO(q) gboolean nsgtk_toolbar_##q##_button_data(\ + GtkWidget *widget, GdkDragContext *cont, GtkSelectionData\ + *selection, guint info, guint time, gpointer data);\ +gboolean nsgtk_toolbar_##q##_toolbar_button_data(GtkWidget *widget,\ + GdkDragContext *cont, GtkSelectionData *selection, guint info,\ + guint time, gpointer data) +TOOLPROTO(home); +TOOLPROTO(back); +TOOLPROTO(forward); +TOOLPROTO(reload); +TOOLPROTO(stop); +TOOLPROTO(throbber); +TOOLPROTO(websearch); +TOOLPROTO(history); +TOOLPROTO(newwindow); +TOOLPROTO(newtab); +TOOLPROTO(openfile); +TOOLPROTO(closetab); +TOOLPROTO(closewindow); +TOOLPROTO(savepage); +TOOLPROTO(pdf); +TOOLPROTO(plaintext); +TOOLPROTO(drawfile); +TOOLPROTO(postscript); +TOOLPROTO(printpreview); +TOOLPROTO(print); +TOOLPROTO(quit); +TOOLPROTO(cut); +TOOLPROTO(copy); +TOOLPROTO(paste); +TOOLPROTO(delete); +TOOLPROTO(selectall); +TOOLPROTO(find); +TOOLPROTO(preferences); +TOOLPROTO(zoomplus); +TOOLPROTO(zoomminus); +TOOLPROTO(zoomnormal); +TOOLPROTO(fullscreen); +TOOLPROTO(viewsource); +TOOLPROTO(downloads); +TOOLPROTO(localhistory); +TOOLPROTO(globalhistory); +TOOLPROTO(addbookmarks); +TOOLPROTO(showbookmarks); +TOOLPROTO(openlocation); +TOOLPROTO(nexttab); +TOOLPROTO(prevtab); +TOOLPROTO(savewindowsize); +TOOLPROTO(toggledebugging); +TOOLPROTO(saveboxtree); +TOOLPROTO(savedomtree); +TOOLPROTO(contents); +TOOLPROTO(guide); +TOOLPROTO(info); +TOOLPROTO(about); +#undef TOOLPROTO + +#endif diff --git a/gtk/gtk_window.c b/gtk/gtk_window.c index aa0ccaae6..54e9c16a1 100644 --- a/gtk/gtk_window.c +++ b/gtk/gtk_window.c @@ -22,6 +22,7 @@ #include "gtk/gtk_window.h" #include "desktop/browser.h" #include "desktop/options.h" +#include "desktop/searchweb.h" #include "desktop/textinput.h" #include "desktop/selection.h" #include "gtk/gtk_gui.h" @@ -35,7 +36,36 @@ #include <gdk/gdkkeysyms.h> #include <assert.h> -struct gui_window *window_list = 0; /**< first entry in win list*/ +struct gui_window { + /* All gui_window objects have an ultimate scaffold */ + nsgtk_scaffolding *scaffold; + /**< the gtk object containing menu, buttons, url bar, [tabs], + * drawing area, etc that may contain 1 -> several gui_windows */ + struct browser_window *bw; + /**< the 'content' window that is rendered in the gui_window*/ + struct browser_mouse *mouse; /**< contains mouse state / events */ + + int caretx, carety, careth; + /**< storage caret dimension / location for rendering */ + gui_pointer_shape current_pointer; + /**< storage caret shape for rendering */ + int last_x, last_y; + /**< storage caret location for rendering */ + + GtkScrolledWindow *scrolledwindow; + /**< optional; for frames that need it; top level of gtk structure of + * gui_window */ + GtkViewport *viewport; + /**< contained in a scrolled window */ + GtkFixed *fixed; /**< contained in a viewport */ + GtkDrawingArea *drawing_area; /**< contained in a gtkfixed */ + GtkWidget *tab; /** the visible tab */ + gulong signalhandler[NSGTK_WINDOW_SIGNAL_COUNT]; + /**< to allow disactivation / resume of normal window behaviour */ + struct gui_window *next, *prev; /**< list for eventual cleanup */ +}; + +struct gui_window *window_list = NULL; /**< first entry in win list*/ int temp_open_background = -1; @@ -60,19 +90,45 @@ static void nsgtk_redraw_caret(struct gui_window *g); static GdkCursor *nsgtk_create_menu_cursor(void); -struct browser_window *nsgtk_get_browser_window(struct gui_window *g) +nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g) +{ + return g->scaffold; +} + +struct browser_window *gui_window_get_browser_window(struct gui_window *g) { return g->bw; } -nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g) +unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i) { - return g->scaffold; + return g->signalhandler[i]; } -struct browser_window *nsgtk_get_browser_for_gui(struct gui_window *g) +GtkDrawingArea *nsgtk_window_get_drawing_area(struct gui_window *g) { - return g->bw; + return g->drawing_area; +} + +GtkScrolledWindow *nsgtk_window_get_scrolledwindow(struct gui_window *g) +{ + return g->scrolledwindow; +} + +GtkWidget *nsgtk_window_get_tab(struct gui_window *g) +{ + return g->tab; +} + +void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w) +{ + g->tab = w; +} + + +struct gui_window *nsgtk_window_iterate(struct gui_window *g) +{ + return g->next; } float nsgtk_get_scale_for_gui(struct gui_window *g) @@ -111,13 +167,6 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, g->careth = 0; - /* Attach ourselves to the list (push_top) */ - if (window_list) - window_list->prev = g; - g->next = window_list; - g->prev = NULL; - window_list = g; - if (bw->parent != NULL) /* Find our parent's scaffolding */ g->scaffold = bw->parent->window->scaffold; @@ -127,9 +176,20 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, else /* Now construct and attach a scaffold */ g->scaffold = nsgtk_new_scaffolding(g); + if (g->scaffold == NULL) { + free(g); + return NULL; + } - /* Construct our primary elements */ - g->fixed = GTK_FIXED(gtk_fixed_new()); + /* Attach ourselves to the list (push_top) */ + if (window_list) + window_list->prev = g; + g->next = window_list; + g->prev = NULL; + window_list = g; + + /* Construct our primary elements */ + g->fixed = GTK_FIXED(gtk_fixed_new()); g->drawing_area = GTK_DRAWING_AREA(gtk_drawing_area_new()); gtk_fixed_put(g->fixed, GTK_WIDGET(g->drawing_area), 0, 0); gtk_container_set_border_width(GTK_CONTAINER(g->fixed), 0); @@ -219,6 +279,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); GTK_WIDGET_SET_FLAGS(GTK_WIDGET(g->drawing_area), GTK_CAN_FOCUS); @@ -229,17 +290,20 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, #define CONNECT(obj, sig, callback, ptr) \ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) - CONNECT(g->drawing_area, "expose_event", nsgtk_window_expose_event, g); + g->signalhandler[NSGTK_WINDOW_SIGNAL_REDRAW] = + CONNECT(g->drawing_area, "expose_event", + nsgtk_window_expose_event, g); CONNECT(g->drawing_area, "motion_notify_event", - nsgtk_window_motion_notify_event, g); - CONNECT(g->drawing_area, "button_press_event", - nsgtk_window_button_press_event, g); + nsgtk_window_motion_notify_event, g); + g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] = + CONNECT(g->drawing_area, "button_press_event", + nsgtk_window_button_press_event, g); CONNECT(g->drawing_area, "button_release_event", - nsgtk_window_button_release_event, g); + nsgtk_window_button_release_event, g); CONNECT(g->drawing_area, "key_press_event", - nsgtk_window_keypress_event, g); + nsgtk_window_keypress_event, g); CONNECT(g->viewport, "size_allocate", - nsgtk_window_size_allocate_event, g); + nsgtk_window_size_allocate_event, g); return g; } @@ -344,7 +408,9 @@ gboolean nsgtk_window_motion_notify_event(GtkWidget *widget, struct gui_window *g = data; bool shift = event->state & GDK_SHIFT_MASK; bool ctrl = event->state & GDK_CONTROL_MASK; - + if ((abs(event->x - g->last_x) < 5) && (abs(event->y - g->last_y) < 5)) + /* necessary for touch screens */ + return FALSE; if (g->mouse->state & BROWSER_MOUSE_PRESS_1){ /* Start button 1 drag */ browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_1, @@ -384,29 +450,24 @@ gboolean nsgtk_window_button_press_event(GtkWidget *widget, struct gui_window *g = data; gtk_widget_grab_focus(GTK_WIDGET(g->drawing_area)); + gtk_widget_hide(GTK_WIDGET(nsgtk_scaffolding_history_window( + g->scaffold)->window)); g->mouse->pressed_x = event->x / g->bw->scale; g->mouse->pressed_y = event->y / g->bw->scale; - if (event->button == 3) { - /** \todo - * Firstly, MOUSE_PRESS_2 on GTK is a middle click, which doesn't - * appear correct to me. Secondly, right-clicks are not passed to - * browser_window_mouse_click() at all, which also seems incorrect - * since they should result in browser_window_remove_caret(). - * - * I would surmise we need a MOUSE_PRESS_3, unless right-clicking is - * supposed to be mapped to MOUSE_PRESS_2, but that doesn't appear - * correct either. - */ - browser_window_remove_caret(g->bw); - nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse->pressed_x, g->mouse->pressed_y); - return TRUE; - } - switch (event->button) { - case 1: g->mouse->state = BROWSER_MOUSE_PRESS_1; break; - case 2: g->mouse->state = BROWSER_MOUSE_PRESS_2; break; + case 1: + g->mouse->state = BROWSER_MOUSE_PRESS_1; + break; + case 3: + browser_window_remove_caret(g->bw); + nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse->pressed_x, + g->mouse->pressed_y); + g->mouse->state = BROWSER_MOUSE_PRESS_2; + break; + default: + return FALSE; } /* Handle the modifiers too */ if (event->state & GDK_SHIFT_MASK) @@ -565,7 +626,7 @@ void nsgtk_reflow_all_windows(void) { for (struct gui_window *g = window_list; g; g = g->next) { nsgtk_tab_options_changed(GTK_WIDGET( - nsgtk_scaffolding_get_notebook(g))); + nsgtk_scaffolding_notebook(g->scaffold))); g->bw->reformat_pending = true; } @@ -702,6 +763,12 @@ void gui_window_set_scroll(struct gui_window *g, int sx, int sy) gtk_adjustment_set_value(hadj, x); } +void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, + int x1, int y1) +{ + gui_window_set_scroll(g,x0,y0); +} + /** * Set the scale setting of a window diff --git a/gtk/gtk_window.h b/gtk/gtk_window.h index 71c86bca5..58754bdda 100644 --- a/gtk/gtk_window.h +++ b/gtk/gtk_window.h @@ -23,36 +23,6 @@ #include "desktop/browser.h" #include "gtk/gtk_scaffolding.h" -struct gui_window { - /* All gui_window objects have an ultimate scaffold */ - nsgtk_scaffolding *scaffold; - /* A gui_window is the rendering of a browser_window */ - struct browser_window *bw; - struct browser_mouse *mouse; - - /* These are the storage for the rendering */ - int caretx, carety, careth; - gui_pointer_shape current_pointer; - int last_x, last_y; - - /* Within GTK, a gui_window is a scrolled window - * with a viewport inside - * with a gtkfixed in that - * with a drawing area in that - * The scrolled window is optional and only chosen - * for frames which need it. Otherwise we just use - * a viewport. - */ - GtkWidget *tab; - GtkScrolledWindow *scrolledwindow; - GtkViewport *viewport; - GtkFixed *fixed; - GtkDrawingArea *drawing_area; - - /* Keep gui_windows in a list for cleanup later */ - struct gui_window *next, *prev; -}; - struct browser_mouse { struct gui_window *gui; struct box *box; @@ -63,19 +33,29 @@ struct browser_mouse { browser_mouse_state state; }; -extern struct gui_window * window_list; +typedef enum nsgtk_window_signals { + NSGTK_WINDOW_SIGNAL_CLICK, + NSGTK_WINDOW_SIGNAL_REDRAW, + NSGTK_WINDOW_SIGNAL_COUNT +} nsgtk_window_signal; + +extern struct gui_window *window_list; extern int temp_open_background; void nsgtk_reflow_all_windows(void); void nsgtk_window_process_reformats(void); nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g); -struct browser_window *nsgtk_get_browser_for_gui(struct gui_window *g); float nsgtk_get_scale_for_gui(struct gui_window *g); int nsgtk_gui_window_update_targets(struct gui_window *g); void nsgtk_window_destroy_browser(struct gui_window *g); +unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i); +GtkDrawingArea *nsgtk_window_get_drawing_area(struct gui_window *g); +struct gui_window *nsgtk_window_iterate(struct gui_window *g); +GtkScrolledWindow *nsgtk_window_get_scrolledwindow(struct gui_window *g); +GtkWidget *nsgtk_window_get_tab(struct gui_window *g); +void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w); -struct browser_window *nsgtk_get_browser_window(struct gui_window *g); #endif /* NETSURF_GTK_WINDOW_H */ diff --git a/gtk/options.h b/gtk/options.h index ec48c326d..c2f5e48e8 100644 --- a/gtk/options.h +++ b/gtk/options.h @@ -34,6 +34,8 @@ extern int option_history_age; extern bool option_hover_urls; extern bool option_focus_new; extern bool option_new_blank; +extern bool option_source_tab; +extern int option_current_theme; #define EXTRA_OPTION_DEFINE \ bool option_render_resample = false; \ @@ -48,7 +50,9 @@ bool option_disable_plugins = false; \ int option_history_age = 0; \ bool option_hover_urls = false; \ bool option_focus_new = false; \ -bool option_new_blank = false; +bool option_new_blank = false; \ +bool option_source_tab = false;\ +int option_current_theme = 0; #define EXTRA_OPTION_TABLE \ { "render_resample", OPTION_BOOL, &option_render_resample }, \ @@ -63,6 +67,8 @@ bool option_new_blank = false; { "history_age", OPTION_INTEGER, &option_history_age}, \ { "hover_urls", OPTION_BOOL, &option_hover_urls}, \ { "focus_new", OPTION_BOOL, &option_focus_new}, \ -{ "new_blank", OPTION_BOOL, &option_new_blank} +{ "new_blank", OPTION_BOOL, &option_new_blank}, \ +{ "source_tab", OPTION_BOOL, &option_source_tab},\ +{ "current_theme", OPTION_INTEGER, &option_current_theme} #endif diff --git a/gtk/res/SearchEngines b/gtk/res/SearchEngines new file mode 100644 index 000000000..e9eb466c2 --- /dev/null +++ b/gtk/res/SearchEngines @@ -0,0 +1,20 @@ +Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico| +Yahoo|search.yahoo.com|http://search.yahoo.com/search?p=%s|http://www.yahoo.com/favicon.ico| +Bing|www.bing.com|http://www.bing.com/search?q=%s|http://www.bing.com/favicon.ico| +Business.com|www.business.com|http://www.business.com/search/rslt_default.asp?query=%s|http://www.business.com/favicon.ico| +Omgili|www.omgili.com|http://www.omgili.com/AAAAA/%s.html|http://www.omgili.com/favicon.ico| +BBC News|search.bbc.co.uk|http://search.bbc.co.uk/search?q=%s&tab=ns|http://news.bbc.co.uk/favicon.ico| +Ubuntu Packages|packages.ubuntu.com|http://packages.ubuntu.com/search?keywords=%s|http://packages.ubuntu.com/favicon.ico| +Creative Commons|creativecommons.org|http://creativecommons.org/?s=%s|http://creativecommons.org/favicon.ico| +Ask.com|www.ask.com|http://www.ask.com/web?q=%s|http://www.ask.com/favicon.ico| +Answers.com|www.answers.com|http://www.answers.com/%s|http://www.answers.com/favicon.ico| +Dictionary.com|dictionary.reference.com|http://dictionary.reference.com/browse/%s?jss=0|http://dictionary.reference.com/favicon.ico| +Youtube|www.youtube.com|http://www.youtube.com/results?search_query=%s|http://www.youtube.com/favicon.ico| +AeroMp3|www.aeromp3.com|http://www.aeromp3.com/search?q=%s|http://www.aeromp3.com/favicon.ico| +AOL|search.aol.com|http://search.aol.com/aol/search?query=%s|http://www.aol.com/favicon.ico| +Baidu|www.baidu.com|http://www.baidu.com/s?wd=%s|http://www.baidu.com/favicon.ico| +Amazon|www.amazon.com|http://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|http://www.amazon.com/favicon.ico| +Ebay|shop.ebay.com|http://shop.ebay.com/items/%s|http://www.ebay.com/favicon.ico| +IMDB|www.imdb.com|http://www.imdb.com/find?q=%s|http://www.imdb.com/favicon.ico| +ESPN|search.espn.go.com|http://search.espn.go.com/%s/|http://www.espn.go.com/favicon.ico| +Wikipedia|en.wikipedia.org|http://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|http://en.wikipedia.org/favicon.ico| diff --git a/gtk/res/default.ico b/gtk/res/default.ico Binary files differnew file mode 100644 index 000000000..1cb432828 --- /dev/null +++ b/gtk/res/default.ico diff --git a/gtk/res/html.png b/gtk/res/html.png Binary files differnew file mode 100644 index 000000000..d44dcadce --- /dev/null +++ b/gtk/res/html.png diff --git a/gtk/res/login.glade b/gtk/res/login.glade new file mode 100644 index 000000000..c46740591 --- /dev/null +++ b/gtk/res/login.glade @@ -0,0 +1,222 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkDialog" id="wndLogin"> + <property name="title" translatable="yes">Site Authentication</property> + <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox12"> + <property name="visible">True</property> + <property name="border_width">3</property> + <child> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="yalign">0.10000000149011612</property> + <property name="xpad">12</property> + <property name="icon_size">6</property> + <property name="icon_name">gtk-dialog-authentication</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table5"> + <property name="visible">True</property> + <property name="border_width">1</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="column_spacing">11</property> + <property name="row_spacing">10</property> + <child> + <widget class="GtkLabel" id="labelLoginHost"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">moo.yoo.com</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label57"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Password</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label56"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Username</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label54"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Host</property> + </widget> + <packing> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label55"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Realm</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelLoginRealm"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">my sekr3t area</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryLoginPass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="activates_default">True</property> + <property name="text" translatable="yes">opensesame</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryLoginUser"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="text" translatable="yes">sesame</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">1</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="buttonLoginCan"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="response_id">-6</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="buttonLoginOK"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="response_id">-5</property> + <child> + <widget class="GtkAlignment" id="alignment14"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox11"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-ok</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label49"> + <property name="visible">True</property> + <property name="label" translatable="yes">Login</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/res/netsurf.glade b/gtk/res/netsurf.glade index 13d5e716c..3fef4315d 100644 --- a/gtk/res/netsurf.glade +++ b/gtk/res/netsurf.glade @@ -12,197 +12,10 @@ <widget class="GtkMenuBar" id="menubar"> <property name="visible">True</property> <child> - <widget class="GtkMenuItem" id="menuitem_main"> + <widget class="GtkMenuItem" id="menuitem_file"> <property name="visible">True</property> <property name="label" translatable="yes">_File</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_main_menu"> - <child> - <widget class="GtkImageMenuItem" id="new_window"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Opens a new browser window.</property> - <property name="label" translatable="yes">_New Window</property> - <property name="use_underline">True</property> - <accelerator key="n" modifiers="GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image608"> - <property name="visible">True</property> - <property name="stock">gtk-new</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="new_tab"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Opens a new browser tab.</property> - <property name="label" translatable="yes">New _Tab</property> - <property name="use_underline">True</property> - <accelerator key="t" modifiers="GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image609"> - <property name="visible">True</property> - <property name="stock">gtk-new</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="open_file"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Open a file on your computer into this browser window.</property> - <property name="label" translatable="yes">_Open File...</property> - <property name="use_underline">True</property> - <accelerator key="o" modifiers="GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image610"> - <property name="visible">True</property> - <property name="stock">gtk-open</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="close_window"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Close this browser window.</property> - <property name="label" translatable="yes">_Close Window</property> - <property name="use_underline">True</property> - <accelerator key="w" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image611"> - <property name="visible">True</property> - <property name="stock">gtk-close</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="save_page"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Save this page to disc, optionally including images, etc.</property> - <property name="label" translatable="yes">Save page...</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image612"> - <property name="visible">True</property> - <property name="stock">gtk-save-as</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="export"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Export the page to a different format.</property> - <property name="label" translatable="yes">Export</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="export_menu"> - <child> - <widget class="GtkMenuItem" id="export_plain_text"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Plain ASCII text, readable in text editors and views.</property> - <property name="label" translatable="yes">Plain text...</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="export_drawfile"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">RISC OS Drawfile vector graphic.</property> - <property name="label" translatable="yes">Drawfile...</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="export_postscript"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">PostScript for printing and converting to PDFs.</property> - <property name="label" translatable="yes">PostScript...</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="export_pdf"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Portable Document Format.</property> - <property name="label" translatable="yes">PDF...</property> - <property name="use_underline">True</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator2"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="print_preview"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Show how a print out might look like.</property> - <property name="label" translatable="yes">Print preview...</property> - <property name="use_underline">True</property> - <accelerator key="P" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image613"> - <property name="visible">True</property> - <property name="stock">gtk-print-preview</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="print"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Produce a hardcopy on your printer.</property> - <property name="label" translatable="yes">Print...</property> - <property name="use_underline">True</property> - <accelerator key="P" modifiers="GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image614"> - <property name="visible">True</property> - <property name="stock">gtk-print</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator3"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="quit"> - <property name="visible">True</property> - <property name="label">gtk-quit</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - </widget> - </child> </widget> </child> <child> @@ -210,93 +23,6 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Edit</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_edit_menu"> - <child> - <widget class="GtkImageMenuItem" id="cut"> - <property name="visible">True</property> - <property name="label">gtk-cut</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="copy"> - <property name="visible">True</property> - <property name="label">gtk-copy</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="paste"> - <property name="visible">True</property> - <property name="label">gtk-paste</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="delete"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label">gtk-delete</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator4"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="select_all"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Selects all text in the current browser window.</property> - <property name="label">gtk-select-all</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <accelerator key="a" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator5"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="find"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Find specific text in the current browser window.</property> - <property name="label" translatable="yes">_Find...</property> - <property name="use_underline">True</property> - <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator6"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="preferences"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Change how NetSurf functions.</property> - <property name="label" translatable="yes">P_references...</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image615"> - <property name="visible">True</property> - <property name="stock">gtk-preferences</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> </widget> </child> <child> @@ -304,375 +30,13 @@ <property name="visible">True</property> <property name="label" translatable="yes">_View</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_view_menu"> - <child> - <widget class="GtkImageMenuItem" id="stop"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Stop</property> - <property name="use_underline">True</property> - <accelerator key="Escape" modifiers="" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image616"> - <property name="visible">True</property> - <property name="stock">gtk-stop</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="reload"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Reload</property> - <property name="use_underline">True</property> - <accelerator key="F5" modifiers="" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image617"> - <property name="visible">True</property> - <property name="stock">gtk-refresh</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator10"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="scale_view"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Scale the page in the current browser window to be smaller or larger.</property> - <property name="label" translatable="yes">_Scale View...</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="scale_view_menu"> - <child> - <widget class="GtkImageMenuItem" id="zoom_in"> - <property name="visible">True</property> - <property name="label" translatable="yes">Zoom _in</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image619"> - <property name="visible">True</property> - <property name="stock">gtk-zoom-in</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="normal_size"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Normal size</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image620"> - <property name="visible">True</property> - <property name="stock">gtk-zoom-100</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="zoom_out"> - <property name="visible">True</property> - <property name="label" translatable="yes">Zoom _out</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image621"> - <property name="visible">True</property> - <property name="stock">gtk-zoom-out</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child internal-child="image"> - <widget class="GtkImage" id="image618"> - <property name="visible">True</property> - <property name="stock">gtk-zoom-in</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="full_screen"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Fullscreen</property> - <property name="use_underline">True</property> - <accelerator key="F11" modifiers="" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image622"> - <property name="visible">True</property> - <property name="stock">gtk-fullscreen</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="view_source"> - <property name="visible">True</property> - <property name="label" translatable="yes">View S_ource</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="menu-item-image28"> - <property name="visible">True</property> - <property name="stock">gtk-index</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator12"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="images"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">_Images...</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="images_menu"> - <child> - <widget class="GtkCheckMenuItem" id="foreground_images"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Toggle the display of images in the foreground.</property> - <property name="label" translatable="yes">_Foreground Images</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="background_images"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Toggle the display of images in the background.</property> - <property name="label" translatable="yes">_Background Images</property> - <property name="use_underline">True</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="toolbars"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Toolbars...</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="toolbars_menu"> - <child> - <widget class="GtkCheckMenuItem" id="menu_bar"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Menu Bar</property> - <property name="use_underline">True</property> - <property name="active">True</property> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="tool_bar"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Button Bar</property> - <property name="use_underline">True</property> - <property name="active">True</property> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="status_bar"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Status Bar</property> - <property name="use_underline">True</property> - <property name="active">True</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator11"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="downloads"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Shows the downloads window</property> - <property name="label" translatable="yes">_Downloads...</property> - <property name="use_underline">True</property> - <accelerator key="d" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="save_window_size"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Save this window's size and position for use with new windows.</property> - <property name="label" translatable="yes">S_ave Window Size</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="debugging"> - <property name="visible">True</property> - <property name="label" translatable="yes">De_bugging</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="debugging_menu"> - <child> - <widget class="GtkMenuItem" id="toggle_debug_rendering"> - <property name="visible">True</property> - <property name="label" translatable="yes">T_oggle debug rendering</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="save_box_tree"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Save box tree</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="save_dom_tree"> - <property name="visible">True</property> - <property name="label" translatable="yes">Save DOM tree</property> - <property name="use_underline">True</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> </widget> </child> <child> - <widget class="GtkMenuItem" id="menuitem_navigate"> + <widget class="GtkMenuItem" id="menuitem_nav"> <property name="visible">True</property> <property name="label" translatable="yes">_Navigate</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_navigate_menu"> - <child> - <widget class="GtkImageMenuItem" id="back"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Back</property> - <property name="use_underline">True</property> - <accelerator key="Left" modifiers="GDK_MOD1_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image623"> - <property name="visible">True</property> - <property name="stock">gtk-go-back</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="forward"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Forward</property> - <property name="use_underline">True</property> - <accelerator key="Right" modifiers="GDK_MOD1_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image624"> - <property name="visible">True</property> - <property name="stock">gtk-go-forward</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="home"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Home</property> - <property name="use_underline">True</property> - <accelerator key="Down" modifiers="GDK_MOD1_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image625"> - <property name="visible">True</property> - <property name="stock">gtk-home</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator7"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="local_history"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Show the history tree for this browser window.</property> - <property name="label" translatable="yes">_Local history...</property> - <property name="use_underline">True</property> - <accelerator key="H" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="global_history"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Show the history tree for all windows.</property> - <property name="label" translatable="yes">_Global history...</property> - <property name="use_underline">True</property> - <accelerator key="h" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator8"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="nsgtk_add_to_bookmarks"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Add the current page to your bookmarks.</property> - <property name="label" translatable="yes">_Add to Bookmarks</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="show_bookmarks"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Open a window showing all your bookmarks.</property> - <property name="label" translatable="yes">_Show Bookmarks...</property> - <property name="use_underline">True</property> - <accelerator key="F6" modifiers="" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator13"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="open_location"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Open an address into this browser window.</property> - <property name="label" translatable="yes">_Open location...</property> - <property name="use_underline">True</property> - <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - </widget> - </child> </widget> </child> <child> @@ -680,41 +44,6 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Tabs</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_tabs_menu"> - <child> - <widget class="GtkMenuItem" id="next_tab"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Next Tab</property> - <property name="use_underline">True</property> - <accelerator key="Right" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="prev_tab"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Previous Tab</property> - <property name="use_underline">True</property> - <accelerator key="Left" modifiers="GDK_CONTROL_MASK" signal="activate"/> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="close_tab"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Close tab</property> - <property name="use_underline">True</property> - <accelerator key="W" modifiers="GDK_CONTROL_MASK" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image626"> - <property name="visible">True</property> - <property name="stock">gtk-close</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> </widget> </child> <child> @@ -722,56 +51,6 @@ <property name="visible">True</property> <property name="label" translatable="yes">_Help</property> <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menuitem_help_menu"> - <child> - <widget class="GtkImageMenuItem" id="contents"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Shows the contents of the NetSurf manual.</property> - <property name="label" translatable="yes">_Contents...</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image627"> - <property name="visible">True</property> - <property name="stock">gtk-help</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="guide"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="tooltip" translatable="yes">Shows a guide and tutorial.</property> - <property name="label" translatable="yes">User _guide...</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="user_information"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">User _information...</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separator9"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="about"> - <property name="visible">True</property> - <property name="label">gtk-about</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - </widget> - </child> </widget> </child> </widget> @@ -784,92 +63,123 @@ <widget class="GtkToolbar" id="toolbar"> <property name="visible">True</property> <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkToolbar" id="searchbar"> <child> - <widget class="GtkToolButton" id="toolBack"> - <property name="visible">True</property> - <property name="stock_id">gtk-go-back</property> - </widget> - <packing> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <widget class="GtkToolButton" id="toolHistory"> + <widget class="GtkToolButton" id="closeSearchButton"> <property name="visible">True</property> - <property name="visible_horizontal">False</property> - <property name="visible_vertical">False</property> - <property name="is_important">True</property> - <property name="icon">arrow_down_8x32.png</property> + <property name="stock_id">gtk-close</property> </widget> <packing> - <property name="homogeneous">True</property> + <property name="expand">False</property> + <property name="homogeneous">False</property> </packing> </child> <child> - <widget class="GtkToolButton" id="toolForward"> + <widget class="GtkToolItem" id="searchLabelItem"> <property name="visible">True</property> - <property name="stock_id">gtk-go-forward</property> + <child> + <widget class="GtkLabel" id="searchlabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Match</property> + </widget> + </child> </widget> <packing> - <property name="homogeneous">True</property> + <property name="expand">False</property> + <property name="homogeneous">False</property> </packing> </child> <child> - <widget class="GtkToolButton" id="toolStop"> + <widget class="GtkToolItem" id="toolSearch"> <property name="visible">True</property> - <property name="stock_id">gtk-stop</property> + <child> + <widget class="GtkEntry" id="searchEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> </widget> <packing> - <property name="homogeneous">True</property> + <property name="expand">False</property> + <property name="homogeneous">False</property> </packing> </child> <child> - <widget class="GtkToolButton" id="toolReload"> + <widget class="GtkToolButton" id="searchBackButton"> <property name="visible">True</property> - <property name="stock_id">gtk-refresh</property> + <property name="label" translatable="yes">search _Back</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-go-back</property> </widget> <packing> - <property name="homogeneous">True</property> + <property name="expand">False</property> + <property name="homogeneous">False</property> </packing> </child> <child> - <widget class="GtkToolButton" id="toolHome"> + <widget class="GtkToolButton" id="searchForwardButton"> <property name="visible">True</property> - <property name="stock_id">gtk-home</property> + <property name="label" translatable="yes">search _Forward</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-go-forward</property> </widget> <packing> - <property name="homogeneous">True</property> + <property name="expand">False</property> + <property name="homogeneous">False</property> </packing> </child> <child> - <widget class="GtkToolItem" id="toolURLBar"> + <widget class="GtkToolItem" id="checkAllSearchItem"> <property name="visible">True</property> <child> - <widget class="GtkEntry" id="URLBar"> + <widget class="GtkCheckButton" id="checkAllSearch"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="has_focus">True</property> + <property name="tooltip" translatable="yes">show all matches</property> + <property name="label" translatable="yes">all </property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> </widget> </child> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> </child> <child> - <widget class="GtkToolItem" id="toolthrobber"> + <widget class="GtkToolItem" id="caseSensItem"> <property name="visible">True</property> <child> - <widget class="GtkImage" id="throbber"> + <widget class="GtkCheckButton" id="caseSensButton"> <property name="visible">True</property> - <property name="xpad">2</property> - <property name="icon_name">gtk-yes</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Match case when searching</property> + <property name="label" translatable="yes">case</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> </widget> </child> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> </child> </widget> <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child> @@ -907,7 +217,7 @@ </child> </widget> <packing> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> <child> @@ -917,496 +227,60 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">3</property> + <property name="position">4</property> </packing> </child> </widget> </child> </widget> - <widget class="GtkDialog" id="wndLogin"> - <property name="title" translatable="yes">Site Authentication</property> - <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox2"> + <widget class="GtkMenu" id="menuPopup"> + <child> + <widget class="GtkMenuItem" id="menupopup_file"> <property name="visible">True</property> - <child> - <widget class="GtkHBox" id="hbox12"> - <property name="visible">True</property> - <property name="border_width">3</property> - <child> - <widget class="GtkImage" id="image3"> - <property name="visible">True</property> - <property name="yalign">0.10000000149011612</property> - <property name="xpad">12</property> - <property name="icon_size">6</property> - <property name="icon_name">gtk-dialog-authentication</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkTable" id="table5"> - <property name="visible">True</property> - <property name="border_width">1</property> - <property name="n_rows">4</property> - <property name="n_columns">2</property> - <property name="column_spacing">11</property> - <property name="row_spacing">10</property> - <child> - <widget class="GtkLabel" id="labelLoginHost"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">moo.yoo.com</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label57"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Password</property> - </widget> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label56"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Username</property> - </widget> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label54"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Host</property> - </widget> - <packing> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label55"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Realm</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="labelLoginRealm"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">my sekr3t area</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options"></property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryLoginPass"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="visibility">False</property> - <property name="activates_default">True</property> - <property name="text" translatable="yes">opensesame</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryLoginUser"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="text" translatable="yes">sesame</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">1</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="position">2</property> - </packing> - </child> - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area2"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <widget class="GtkButton" id="buttonLoginCan"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - <property name="response_id">-6</property> - </widget> - </child> - <child> - <widget class="GtkButton" id="buttonLoginOK"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="response_id">-5</property> - <child> - <widget class="GtkAlignment" id="alignment14"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <widget class="GtkHBox" id="hbox11"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <widget class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="stock">gtk-ok</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label49"> - <property name="visible">True</property> - <property name="label" translatable="yes">Login</property> - <property name="use_underline">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> + <property name="label" translatable="yes">File</property> + <property name="use_underline">True</property> </widget> </child> - </widget> - <widget class="GtkDialog" id="wndSSLProblem"> - <property name="border_width">1</property> - <property name="title" translatable="yes">SSL certificate problem</property> - <property name="modal">True</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox3"> + <child> + <widget class="GtkMenuItem" id="menupopup_edit"> <property name="visible">True</property> - <child> - <widget class="GtkHBox" id="hbox15"> - <property name="visible">True</property> - <child> - <widget class="GtkImage" id="image6"> - <property name="visible">True</property> - <property name="yalign">0</property> - <property name="icon_size">6</property> - <property name="icon_name">gtk-dialog-warning</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkVBox" id="vbox13"> - <property name="visible">True</property> - <child> - <widget class="GtkLabel" id="label62"> - <property name="visible">True</property> - <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkFrame" id="frame13"> - <property name="visible">True</property> - <property name="border_width">5</property> - <property name="label_xalign">0</property> - <child> - <widget class="GtkAlignment" id="alignment17"> - <property name="visible">True</property> - <property name="left_padding">12</property> - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <child> - <widget class="GtkTextView" id="textview1"> - <property name="height_request">200</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">False</property> - <property name="text" translatable="yes">(not implemented)</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label63"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Certificate chain</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="position">2</property> - </packing> - </child> - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area3"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <widget class="GtkButton" id="sslreject"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="response_id">-6</property> - <child> - <widget class="GtkAlignment" id="alignment16"> - <property name="visible">True</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <widget class="GtkHBox" id="hbox14"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <widget class="GtkImage" id="image5"> - <property name="visible">True</property> - <property name="stock">gtk-cancel</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label61"> - <property name="visible">True</property> - <property name="label" translatable="yes">Reject</property> - <property name="use_underline">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkButton" id="sslaccept"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="response_id">-5</property> - <child> - <widget class="GtkAlignment" id="alignment15"> - <property name="visible">True</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <widget class="GtkHBox" id="hbox13"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <widget class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="stock">gtk-apply</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label60"> - <property name="visible">True</property> - <property name="label" translatable="yes">Accept</property> - <property name="use_underline">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> + <property name="label" translatable="yes">Edit</property> + <property name="use_underline">True</property> </widget> </child> - </widget> - <widget class="GtkWindow" id="wndWarning"> - <property name="title" translatable="yes">Warning from NetSurf</property> - <property name="window_position">GTK_WIN_POS_CENTER</property> - <property name="icon_name">gtk-dialog-warning</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="urgency_hint">True</property> <child> - <widget class="GtkVBox" id="vbox32"> + <widget class="GtkMenuItem" id="menupopup_view"> + <property name="visible">True</property> + <property name="label" translatable="yes">View</property> + <property name="use_underline">True</property> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menupopup_nav"> + <property name="visible">True</property> + <property name="label" translatable="yes">Navigate</property> + <property name="use_underline">True</property> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menupopup_tabs"> + <property name="visible">True</property> + <property name="label" translatable="yes">Tabs</property> + <property name="use_underline">True</property> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menupopup_help"> + <property name="visible">True</property> + <property name="label" translatable="yes">Help</property> + <property name="use_underline">True</property> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="menupopup_sep"> <property name="visible">True</property> - <property name="border_width">2</property> - <child> - <widget class="GtkHBox" id="hbox30"> - <property name="visible">True</property> - <property name="border_width">3</property> - <child> - <widget class="GtkImage" id="image519"> - <property name="visible">True</property> - <property name="xpad">12</property> - <property name="icon_size">6</property> - <property name="icon_name">gtk-dialog-warning</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="labelWarning"> - <property name="visible">True</property> - <property name="label" translatable="yes">Help help help! I'm being held prisoner by a bunch of RISC OS zealots!</property> - <property name="wrap">True</property> - </widget> - <packing> - <property name="padding">1</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - <child> - <widget class="GtkHSeparator" id="hseparator2"> - <property name="visible">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="padding">3</property> - <property name="position">1</property> - </packing> - </child> - <child> - <widget class="GtkHButtonBox" id="hbuttonbox2"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <widget class="GtkButton" id="button14"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - <signal name="clicked" handler="gtk_widget_hide" object="wndWarning"/> - </widget> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> </widget> </child> - </widget> - <widget class="GtkMenu" id="menuPopup"> <child> <widget class="GtkMenuItem" id="open_link_in_focused_tab_popup"> <property name="visible">True</property> @@ -1422,12 +296,12 @@ </widget> </child> <child> - <widget class="GtkSeparatorMenuItem" id="separator1"> + <widget class="GtkSeparatorMenuItem" id="sep2"> <property name="visible">True</property> </widget> </child> <child> - <widget class="GtkImageMenuItem" id="popupBack"> + <widget class="GtkImageMenuItem" id="back_popup"> <property name="visible">True</property> <property name="label" translatable="yes">_Back</property> <property name="use_underline">True</property> @@ -1441,7 +315,7 @@ </widget> </child> <child> - <widget class="GtkImageMenuItem" id="popupForward"> + <widget class="GtkImageMenuItem" id="forward_popup"> <property name="visible">True</property> <property name="label" translatable="yes">_Forward</property> <property name="use_underline">True</property> @@ -1455,12 +329,12 @@ </widget> </child> <child> - <widget class="GtkSeparatorMenuItem" id="separator"> + <widget class="GtkSeparatorMenuItem" id="sep"> <property name="visible">True</property> </widget> </child> <child> - <widget class="GtkImageMenuItem" id="popupReload"> + <widget class="GtkImageMenuItem" id="reload_popup"> <property name="visible">True</property> <property name="label" translatable="yes">_Reload</property> <property name="use_underline">True</property> @@ -1530,316 +404,11 @@ </widget> </child> <child> - <widget class="GtkMenuItem" id="menupopup_file"> - <property name="visible">True</property> - <property name="label" translatable="yes">File</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menupopup_edit"> - <property name="visible">True</property> - <property name="label" translatable="yes">Edit</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menupopup_view"> - <property name="visible">True</property> - <property name="label" translatable="yes">View</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menupopup_navigate"> - <property name="visible">True</property> - <property name="label" translatable="yes">Navigate</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menupopup_object"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">Object</property> - <property name="use_underline">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menupopup_help"> + <widget class="GtkMenuItem" id="customize_popup"> <property name="visible">True</property> - <property name="label" translatable="yes">Help</property> + <property name="label" translatable="yes">Customize..</property> <property name="use_underline">True</property> </widget> </child> </widget> - <widget class="GtkWindow" id="wndPDFPassword"> - <property name="title" translatable="yes">PDF Password</property> - <property name="modal">True</property> - <property name="window_position">GTK_WIN_POS_CENTER</property> - <child> - <widget class="GtkHBox" id="hbox1"> - <property name="visible">True</property> - <child> - <widget class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="yalign">0.10000000149011612</property> - <property name="xpad">12</property> - <property name="icon_size">6</property> - <property name="icon_name">gtk-dialog-authentication</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkVBox" id="vbox1"> - <property name="visible">True</property> - <property name="border_width">5</property> - <child> - <widget class="GtkLabel" id="labelInfo"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Write and confirm passwords:</property> - </widget> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <widget class="GtkHBox" id="hbox2"> - <property name="visible">True</property> - <property name="border_width">5</property> - <child> - <widget class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="label" translatable="yes">Owner password:</property> - <property name="width_chars">15</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryPDFOwnerPassword"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">20</property> - <property name="visibility">False</property> - <property name="width_chars">20</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <widget class="GtkHBox" id="hbox3"> - <property name="visible">True</property> - <property name="border_width">5</property> - <child> - <widget class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="label" translatable="yes">Repeat password:</property> - <property name="width_chars">15</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryPDFOwnerPassword1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">20</property> - <property name="visibility">False</property> - <property name="width_chars">20</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <widget class="GtkHBox" id="hbox4"> - <property name="visible">True</property> - <property name="border_width">5</property> - <child> - <widget class="GtkLabel" id="label6"> - <property name="visible">True</property> - <property name="label" translatable="yes">User password:</property> - <property name="width_chars">15</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryPDFUserPassword"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">20</property> - <property name="visibility">False</property> - <property name="width_chars">20</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> - </packing> - </child> - <child> - <widget class="GtkHBox" id="hbox5"> - <property name="visible">True</property> - <property name="border_width">5</property> - <child> - <widget class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="label" translatable="yes">Repeat password:</property> - <property name="width_chars">15</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entryPDFUserPassword1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">20</property> - <property name="visibility">False</property> - <property name="width_chars">20</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> - </packing> - </child> - <child> - <widget class="GtkHButtonBox" id="hbuttonbox1"> - <property name="visible">True</property> - <property name="border_width">5</property> - <property name="spacing">10</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <widget class="GtkButton" id="buttonPDFSetPassword"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <child> - <widget class="GtkHBox" id="hbox7"> - <property name="visible">True</property> - <child> - <widget class="GtkImage" id="image7"> - <property name="visible">True</property> - <property name="stock">gtk-ok</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label8"> - <property name="visible">True</property> - <property name="label" translatable="yes">Set password</property> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkButton" id="buttonPDFNoPassword"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <child> - <widget class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <child> - <widget class="GtkHBox" id="hbox6"> - <property name="visible">True</property> - <child> - <widget class="GtkImage" id="image8"> - <property name="visible">True</property> - <property name="stock">gtk-cancel</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="label" translatable="yes">No password</property> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">5</property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> </glade-interface> diff --git a/gtk/res/options.glade b/gtk/res/options.glade index 6bc5cc41e..a1b0414f8 100644 --- a/gtk/res/options.glade +++ b/gtk/res/options.glade @@ -298,7 +298,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">Visited pages are kept in memory for this many days</property> - <property name="adjustment">14 0 100 1 10 10</property> + <property name="adjustment">14 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -471,67 +471,30 @@ <property name="column_spacing">3</property> <property name="row_spacing">3</property> <child> - <widget class="GtkEntry" id="entryProxyPassword"> + <widget class="GtkEntry" id="entryProxyUser"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">If your proxy server requires authentication, enter your password here.</property> - <property name="visibility">False</property> + <property name="tooltip" translatable="yes">If your proxy server requires authentication, enter your username here.</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label76"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Proxy type</property> - </widget> - <packing> - <property name="x_options"></property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label75"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Host</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options"></property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label74"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Username</property> - </widget> - <packing> <property name="top_attach">2</property> <property name="bottom_attach">3</property> - <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label73"> + <widget class="GtkComboBox" id="comboProxyType"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Password</property> + <property name="items" translatable="yes">No proxy +Simple proxy +Basic authentication +NTLM authentication</property> </widget> <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options"></property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="y_options"></property> </packing> </child> @@ -578,30 +541,67 @@ </packing> </child> <child> - <widget class="GtkComboBox" id="comboProxyType"> + <widget class="GtkLabel" id="label73"> <property name="visible">True</property> - <property name="items" translatable="yes">No proxy -Simple proxy -Basic authentication -NTLM authentication</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Password</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkEntry" id="entryProxyUser"> + <widget class="GtkLabel" id="label74"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Username</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label75"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Host</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label76"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Proxy type</property> + </widget> + <packing> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryProxyPassword"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">If your proxy server requires authentication, enter your username here.</property> + <property name="tooltip" translatable="yes">If your proxy server requires authentication, enter your password here.</property> + <property name="visibility">False</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> <property name="y_options"></property> </packing> </child> @@ -643,82 +643,82 @@ NTLM authentication</property> <property name="column_spacing">3</property> <property name="row_spacing">3</property> <child> - <widget class="GtkSpinButton" id="spinMaxFetchers"> + <widget class="GtkLabel" id="label78"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Maximum number of concurrent items to fetch at once.</property> - <property name="adjustment">1 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Maximum fetchers</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinFetchesPerHost"> + <widget class="GtkLabel" id="label79"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Maximum number of item fetches per web server.</property> - <property name="adjustment">1 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Fetches per host</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinCachedConnections"> + <widget class="GtkLabel" id="label80"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Number of connections to keep incase they are needed again.</property> - <property name="adjustment">1 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Cached connections</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="top_attach">2</property> <property name="bottom_attach">3</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label80"> + <widget class="GtkSpinButton" id="spinCachedConnections"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Cached connections</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Number of connections to keep incase they are needed again.</property> + <property name="adjustment">1 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="top_attach">2</property> <property name="bottom_attach">3</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label79"> + <widget class="GtkSpinButton" id="spinFetchesPerHost"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Fetches per host</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Maximum number of item fetches per web server.</property> + <property name="adjustment">1 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label78"> + <widget class="GtkSpinButton" id="spinMaxFetchers"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Maximum fetchers</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Maximum number of concurrent items to fetch at once.</property> + <property name="adjustment">1 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="y_options"></property> </packing> </child> @@ -837,7 +837,7 @@ NTLM authentication</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">Do not update animations any more often than this.</property> - <property name="adjustment">0 0 100 0.10000000149 1 1</property> + <property name="adjustment">0 0 100 0.10000000149 1 0</property> <property name="climb_rate">1</property> <property name="digits">1</property> <property name="numeric">True</property> @@ -934,85 +934,78 @@ NTLM authentication</property> <property name="column_spacing">3</property> <property name="row_spacing">3</property> <child> - <widget class="GtkFontButton" id="fontSansSerif"> + <widget class="GtkLabel" id="label88"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <property name="show_style">False</property> - <property name="show_size">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Sans-serif</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkComboBox" id="comboDefault"> + <widget class="GtkLabel" id="label89"> <property name="visible">True</property> - <property name="items" translatable="yes">Sans-serif -Serif -Monospace -Cursive -Fantasy</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Serif</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options">GTK_FILL</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkFontButton" id="fontFantasy"> + <widget class="GtkLabel" id="label90"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <property name="show_style">False</property> - <property name="show_size">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Monospace</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_options">GTK_FILL</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkFontButton" id="fontCursive"> + <widget class="GtkLabel" id="label91"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <property name="show_style">False</property> - <property name="show_size">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Cursive</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="top_attach">3</property> <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkFontButton" id="fontMonospace"> + <widget class="GtkLabel" id="label92"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="response_id">0</property> - <property name="show_style">False</property> - <property name="show_size">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Fantasy</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label93"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Default</property> + </widget> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> @@ -1034,78 +1027,85 @@ Fantasy</property> </packing> </child> <child> - <widget class="GtkLabel" id="label93"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Default</property> - </widget> - <packing> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options"></property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label92"> + <widget class="GtkFontButton" id="fontMonospace"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Fantasy</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="show_style">False</property> + <property name="show_size">False</property> </widget> <packing> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_options"></property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label91"> + <widget class="GtkFontButton" id="fontCursive"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Cursive</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="show_style">False</property> + <property name="show_size">False</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="top_attach">3</property> <property name="bottom_attach">4</property> - <property name="x_options"></property> + <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label90"> + <widget class="GtkFontButton" id="fontFantasy"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Monospace</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="show_style">False</property> + <property name="show_size">False</property> </widget> <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options"></property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label89"> + <widget class="GtkComboBox" id="comboDefault"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Serif</property> + <property name="items" translatable="yes">Sans-serif +Serif +Monospace +Cursive +Fantasy</property> </widget> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options"></property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label88"> + <widget class="GtkFontButton" id="fontSansSerif"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Sans-serif</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="show_style">False</property> + <property name="show_size">False</property> </widget> <packing> - <property name="x_options"></property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="y_options"></property> </packing> </child> @@ -1146,42 +1146,61 @@ Fantasy</property> <property name="column_spacing">3</property> <property name="row_spacing">3</property> <child> - <widget class="GtkLabel" id="label98"> + <widget class="GtkButton" id="fontPreview"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">pt</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">View the changes in the browser window immediately.</property> + <property name="response_id">0</property> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="border_width">2</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-apply</property> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Preview</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> + <property name="left_attach">3</property> + <property name="right_attach">4</property> <property name="bottom_attach">2</property> + <property name="x_options"></property> <property name="y_options"></property> + <property name="x_padding">2</property> </packing> </child> <child> - <widget class="GtkLabel" id="label97"> + <widget class="GtkLabel" id="label95"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">pt</property> + <property name="label" translatable="yes">Default</property> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinMinimumSize"> + <widget class="GtkLabel" id="label96"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Do not allow text to be displayed any smaller than this.</property> - <property name="adjustment">1 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Minimum</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> <property name="x_options"></property> @@ -1193,7 +1212,7 @@ Fantasy</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">The base-line font size to use.</property> - <property name="adjustment">1 0 100 1 10 10</property> + <property name="adjustment">1 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -1204,12 +1223,16 @@ Fantasy</property> </packing> </child> <child> - <widget class="GtkLabel" id="label96"> + <widget class="GtkSpinButton" id="spinMinimumSize"> <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Minimum</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Do not allow text to be displayed any smaller than this.</property> + <property name="adjustment">1 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> <property name="x_options"></property> @@ -1217,52 +1240,29 @@ Fantasy</property> </packing> </child> <child> - <widget class="GtkLabel" id="label95"> + <widget class="GtkLabel" id="label97"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Default</property> + <property name="label" translatable="yes">pt</property> </widget> <packing> - <property name="x_options"></property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkButton" id="fontPreview"> + <widget class="GtkLabel" id="label98"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">View the changes in the browser window immediately.</property> - <property name="response_id">0</property> - <child> - <widget class="GtkHBox" id="hbox3"> - <property name="visible">True</property> - <property name="border_width">2</property> - <child> - <widget class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="stock">gtk-apply</property> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Preview</property> - <property name="use_underline">True</property> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> + <property name="xalign">0</property> + <property name="label" translatable="yes">pt</property> </widget> <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> <property name="bottom_attach">2</property> - <property name="x_options"></property> <property name="y_options"></property> - <property name="x_padding">2</property> </packing> </child> </widget> @@ -1301,16 +1301,6 @@ Fantasy</property> <property name="column_spacing">10</property> <property name="row_spacing">3</property> <child> - <widget class="GtkLabel" id="label19"> - <property name="visible">True</property> - <property name="label" translatable="yes">Toolbar buttons</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - </widget> - <packing> - <property name="x_options"></property> - </packing> - </child> - <child> <widget class="GtkComboBox" id="comboButtonType"> <property name="visible">True</property> <property name="items" translatable="yes">Small icons @@ -1325,6 +1315,16 @@ Text only</property> <property name="y_options"></property> </packing> </child> + <child> + <widget class="GtkLabel" id="label19"> + <property name="visible">True</property> + <property name="label" translatable="yes">Toolbar buttons</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + </widget> + <packing> + <property name="x_options"></property> + </packing> + </child> </widget> </child> </widget> @@ -1394,7 +1394,7 @@ Text only</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">How much memory to use for caching recently viewed objects in memory.</property> - <property name="adjustment">1 0 100 1 10 10</property> + <property name="adjustment">1 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -1467,7 +1467,7 @@ Text only</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">How long to keep cached items around on disc.</property> - <property name="adjustment">1 0 100 1 10 10</property> + <property name="adjustment">1 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -1742,7 +1742,199 @@ Text only</property> </packing> </child> <child> - <placeholder/> + <widget class="GtkFrame" id="frame10"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <child> + <widget class="GtkAlignment" id="alignment10"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkHBox" id="hbox11"> + <property name="visible">True</property> + <child> + <widget class="GtkRadioButton" id="sourceButtonWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">in own window </property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="sourceButtonTab"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">in new tab</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label24"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>View Source</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame9"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <child> + <widget class="GtkAlignment" id="alignment9"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkHBox" id="hbox9"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="checkUrlSearch"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">search from url bar </property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label23"> + <property name="visible">True</property> + <property name="label" translatable="yes"> default provider</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="comboSearch"> + <property name="visible">True</property> + <property name="items" translatable="yes">Google +Yahoo! +Microsoft live +Business.com +Omgili +BBC News +Ubuntu packages +Creative commons +Ask +Answers +Dictionary.com +Youtube +AeroMp3 +AOL +Baidu +Amazon +Ebay +IMDB +Espn +Wikipedia</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label22"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Search</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame11"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <child> + <widget class="GtkAlignment" id="alignment11"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkHBox" id="themehbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkButton" id="buttonaddtheme"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">add theme..</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label25"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Select themes</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">4</property> + </packing> </child> </widget> <packing> @@ -1785,32 +1977,25 @@ Text only</property> <property name="column_spacing">4</property> <property name="row_spacing">5</property> <child> - <widget class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="label" translatable="yes">Top:</property> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label6"> + <widget class="GtkLabel" id="label10"> <property name="visible">True</property> - <property name="label" translatable="yes">Bottom:</property> + <property name="label" translatable="yes">mm</property> </widget> <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinMarginTop"> + <widget class="GtkLabel" id="label9"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Set the top margin</property> - <property name="adjustment">0 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="label" translatable="yes">mm</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> </packing> </child> <child> @@ -1818,7 +2003,7 @@ Text only</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">Set the bottom margin</property> - <property name="adjustment">0 0 100 1 10 10</property> + <property name="adjustment">0 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -1829,27 +2014,34 @@ Text only</property> </packing> </child> <child> - <widget class="GtkLabel" id="label9"> + <widget class="GtkSpinButton" id="spinMarginTop"> <property name="visible">True</property> - <property name="label" translatable="yes">mm</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Set the top margin</property> + <property name="adjustment">0 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> </packing> </child> <child> - <widget class="GtkLabel" id="label10"> + <widget class="GtkLabel" id="label6"> <property name="visible">True</property> - <property name="label" translatable="yes">mm</property> + <property name="label" translatable="yes">Bottom:</property> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> </packing> </child> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Top:</property> + </widget> + </child> </widget> <packing> <property name="expand">False</property> @@ -1864,32 +2056,25 @@ Text only</property> <property name="column_spacing">4</property> <property name="row_spacing">5</property> <child> - <widget class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="label" translatable="yes">Left:</property> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label8"> + <widget class="GtkLabel" id="label12"> <property name="visible">True</property> - <property name="label" translatable="yes">Right:</property> + <property name="label" translatable="yes">mm</property> </widget> <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinMarginLeft"> + <widget class="GtkLabel" id="label11"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip" translatable="yes">Set the left margin</property> - <property name="adjustment">0 0 100 1 10 10</property> - <property name="climb_rate">1</property> + <property name="label" translatable="yes">mm</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> </packing> </child> <child> @@ -1897,7 +2082,7 @@ Text only</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">Set the right margin</property> - <property name="adjustment">0 0 100 1 10 10</property> + <property name="adjustment">0 0 100 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> @@ -1908,27 +2093,34 @@ Text only</property> </packing> </child> <child> - <widget class="GtkLabel" id="label11"> + <widget class="GtkSpinButton" id="spinMarginLeft"> <property name="visible">True</property> - <property name="label" translatable="yes">mm</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Set the left margin</property> + <property name="adjustment">0 0 100 1 10 0</property> + <property name="climb_rate">1</property> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> </packing> </child> <child> - <widget class="GtkLabel" id="label12"> + <widget class="GtkLabel" id="label8"> <property name="visible">True</property> - <property name="label" translatable="yes">mm</property> + <property name="label" translatable="yes">Right:</property> </widget> <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> </packing> </child> + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Left:</property> + </widget> + </child> </widget> <packing> <property name="expand">False</property> @@ -1983,7 +2175,7 @@ Text only</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip" translatable="yes">Set the scaling for the document - this way more content can fit in a page</property> - <property name="adjustment">0 0 1000 1 10 10</property> + <property name="adjustment">0 0 1000 1 10 0</property> <property name="climb_rate">1</property> </widget> <packing> diff --git a/gtk/res/password.glade b/gtk/res/password.glade new file mode 100644 index 000000000..0d00d65ed --- /dev/null +++ b/gtk/res/password.glade @@ -0,0 +1,274 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="wndPDFPassword"> + <property name="title" translatable="yes">PDF Password</property> + <property name="modal">True</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="yalign">0.10000000149011612</property> + <property name="xpad">12</property> + <property name="icon_size">6</property> + <property name="icon_name">gtk-dialog-authentication</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="border_width">5</property> + <child> + <widget class="GtkLabel" id="labelInfo"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Write and confirm passwords:</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="border_width">5</property> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Owner password:</property> + <property name="width_chars">15</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryPDFOwnerPassword"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">20</property> + <property name="visibility">False</property> + <property name="width_chars">20</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="border_width">5</property> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Repeat password:</property> + <property name="width_chars">15</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryPDFOwnerPassword1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">20</property> + <property name="visibility">False</property> + <property name="width_chars">20</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="border_width">5</property> + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">User password:</property> + <property name="width_chars">15</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryPDFUserPassword"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">20</property> + <property name="visibility">False</property> + <property name="width_chars">20</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="border_width">5</property> + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Repeat password:</property> + <property name="width_chars">15</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entryPDFUserPassword1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">20</property> + <property name="visibility">False</property> + <property name="width_chars">20</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="border_width">5</property> + <property name="spacing">10</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="buttonPDFSetPassword"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image7"> + <property name="visible">True</property> + <property name="stock">gtk-ok</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Set password</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkButton" id="buttonPDFNoPassword"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image8"> + <property name="visible">True</property> + <property name="stock">gtk-cancel</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">No password</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/res/ssl.glade b/gtk/res/ssl.glade new file mode 100644 index 000000000..98d9f9bf3 --- /dev/null +++ b/gtk/res/ssl.glade @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkDialog" id="wndSSLProblem"> + <property name="border_width">1</property> + <property name="title" translatable="yes">SSL certificate problem</property> + <property name="modal">True</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox3"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox15"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image6"> + <property name="visible">True</property> + <property name="yalign">0</property> + <property name="icon_size">6</property> + <property name="icon_name">gtk-dialog-warning</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox13"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label62"> + <property name="visible">True</property> + <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame13"> + <property name="visible">True</property> + <property name="border_width">5</property> + <property name="label_xalign">0</property> + <child> + <widget class="GtkAlignment" id="alignment17"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTextView" id="textview1"> + <property name="height_request">200</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="text" translatable="yes">(not implemented)</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label63"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Certificate chain</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="sslreject"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="response_id">-6</property> + <child> + <widget class="GtkAlignment" id="alignment16"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox14"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-cancel</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label61"> + <property name="visible">True</property> + <property name="label" translatable="yes">Reject</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkButton" id="sslaccept"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="response_id">-5</property> + <child> + <widget class="GtkAlignment" id="alignment15"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox13"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-apply</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label60"> + <property name="visible">True</property> + <property name="label" translatable="yes">Accept</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/res/themelist b/gtk/res/themelist new file mode 100644 index 000000000..4a70e25d6 --- /dev/null +++ b/gtk/res/themelist @@ -0,0 +1,2 @@ +gtk default theme +gtk+ diff --git a/gtk/res/themes/Alpha.png b/gtk/res/themes/Alpha.png Binary files differnew file mode 100644 index 000000000..f76e51dad --- /dev/null +++ b/gtk/res/themes/Alpha.png diff --git a/gtk/res/themes/gtk+/back.png b/gtk/res/themes/gtk+/back.png Binary files differnew file mode 100644 index 000000000..23b89b761 --- /dev/null +++ b/gtk/res/themes/gtk+/back.png diff --git a/gtk/res/themes/gtk+/closetab.png b/gtk/res/themes/gtk+/closetab.png Binary files differnew file mode 100644 index 000000000..312b84dae --- /dev/null +++ b/gtk/res/themes/gtk+/closetab.png diff --git a/gtk/res/themes/gtk+/closewindow.png b/gtk/res/themes/gtk+/closewindow.png Binary files differnew file mode 100644 index 000000000..312b84dae --- /dev/null +++ b/gtk/res/themes/gtk+/closewindow.png diff --git a/gtk/res/themes/gtk+/copy.png b/gtk/res/themes/gtk+/copy.png Binary files differnew file mode 100644 index 000000000..a1178e64f --- /dev/null +++ b/gtk/res/themes/gtk+/copy.png diff --git a/gtk/res/themes/gtk+/cut.png b/gtk/res/themes/gtk+/cut.png Binary files differnew file mode 100644 index 000000000..82b105f80 --- /dev/null +++ b/gtk/res/themes/gtk+/cut.png diff --git a/gtk/res/themes/gtk+/delete.png b/gtk/res/themes/gtk+/delete.png Binary files differnew file mode 100644 index 000000000..e375b894e --- /dev/null +++ b/gtk/res/themes/gtk+/delete.png diff --git a/gtk/res/themes/gtk+/forward.png b/gtk/res/themes/gtk+/forward.png Binary files differnew file mode 100644 index 000000000..727ff37f2 --- /dev/null +++ b/gtk/res/themes/gtk+/forward.png diff --git a/gtk/res/themes/gtk+/fullscreen.png b/gtk/res/themes/gtk+/fullscreen.png Binary files differnew file mode 100644 index 000000000..21462fe0e --- /dev/null +++ b/gtk/res/themes/gtk+/fullscreen.png diff --git a/gtk/res/themes/gtk+/helpabout.png b/gtk/res/themes/gtk+/helpabout.png Binary files differnew file mode 100644 index 000000000..063d0df43 --- /dev/null +++ b/gtk/res/themes/gtk+/helpabout.png diff --git a/gtk/res/themes/gtk+/helpcontents.png b/gtk/res/themes/gtk+/helpcontents.png Binary files differnew file mode 100644 index 000000000..b00fbd8c1 --- /dev/null +++ b/gtk/res/themes/gtk+/helpcontents.png diff --git a/gtk/res/themes/gtk+/history.png b/gtk/res/themes/gtk+/history.png Binary files differnew file mode 100644 index 000000000..0d445027f --- /dev/null +++ b/gtk/res/themes/gtk+/history.png diff --git a/gtk/res/themes/gtk+/home.png b/gtk/res/themes/gtk+/home.png Binary files differnew file mode 100644 index 000000000..a2e0b3c96 --- /dev/null +++ b/gtk/res/themes/gtk+/home.png diff --git a/gtk/res/themes/gtk+/info b/gtk/res/themes/gtk+/info new file mode 100644 index 000000000..36e4f09df --- /dev/null +++ b/gtk/res/themes/gtk+/info @@ -0,0 +1,81 @@ +This file is part of NetSurf, http://www.netsurf-browser.org/ + +The images in this theme folder 'gtk+' are from the gtk stock image set +http://library.gnome.org/devel/gtk/unstable/gtk-Stock-Items.html + +the image history.png is [for what it's worth!] Copyright 2009 Mark Benjamin +<netsurf-browser.org.MarkBenjamin@dfgh.net> + +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/>. + +*** Instructions for theming *** + +to create a theme, make a folder, whose name is the name of the theme; +put in the folder, a set of png images for the toolbuttons; +the names of the images should be a subset of the list + + back.png, + history.png, + forward.png, + stop.png, + reload.png, + home.png, + newwindow.png, + newtab.png, + openfile.png, + closetab.png, + closewindow.png, + savepage.png, + pdf.png, + plaintext.png, + drawfile.png, + postscript.png, + printpreview.png, + print.png, + quit.png, + cut.png, + copy.png, + paste.png, + delete.png, + selectall.png, + find.png, + preferences.png, + zoomplus.png, + zoomminus.png, + zoomnormal.png, + fullscreen.png, + viewsource.png, + downloads.png, + savewindowsize.png, + toggledebugging.png, + saveboxtree.png, + savedomtree.png, + localhistory.png, + globalhistory.png, + addbookmarks.png, + showbookmarks.png, + openlocation.png, + nexttab.png, + prevtab.png, + contents.png, + guide.png, + info.png, + about.png, + searchback.png, + searchforward.png, + searchclose.png + +for local theming, the folder may be placed directly [as a subfolder] into the netsurf/gtk/res/themes folder; then 'add theme' from the preferences->advanced tab; + +for downloadable themes, compile netsurf/utils/container.c according to the instructions in the header of that file; make a netsurf container of the folder, serve it as content-type "application/x-netsurf-theme"; browse to it in NetSurf, then NetSurf should automatically install it + diff --git a/gtk/res/themes/gtk+/newtab.png b/gtk/res/themes/gtk+/newtab.png Binary files differnew file mode 100644 index 000000000..c89e797b7 --- /dev/null +++ b/gtk/res/themes/gtk+/newtab.png diff --git a/gtk/res/themes/gtk+/newwindow.png b/gtk/res/themes/gtk+/newwindow.png Binary files differnew file mode 100644 index 000000000..c89e797b7 --- /dev/null +++ b/gtk/res/themes/gtk+/newwindow.png diff --git a/gtk/res/themes/gtk+/openfile.png b/gtk/res/themes/gtk+/openfile.png Binary files differnew file mode 100644 index 000000000..312e1187f --- /dev/null +++ b/gtk/res/themes/gtk+/openfile.png diff --git a/gtk/res/themes/gtk+/paste.png b/gtk/res/themes/gtk+/paste.png Binary files differnew file mode 100644 index 000000000..e938c3e99 --- /dev/null +++ b/gtk/res/themes/gtk+/paste.png diff --git a/gtk/res/themes/gtk+/preferences.png b/gtk/res/themes/gtk+/preferences.png Binary files differnew file mode 100644 index 000000000..2596f3cc5 --- /dev/null +++ b/gtk/res/themes/gtk+/preferences.png diff --git a/gtk/res/themes/gtk+/print.png b/gtk/res/themes/gtk+/print.png Binary files differnew file mode 100644 index 000000000..05d22d7a8 --- /dev/null +++ b/gtk/res/themes/gtk+/print.png diff --git a/gtk/res/themes/gtk+/printpreview.png b/gtk/res/themes/gtk+/printpreview.png Binary files differnew file mode 100644 index 000000000..7f405de58 --- /dev/null +++ b/gtk/res/themes/gtk+/printpreview.png diff --git a/gtk/res/themes/gtk+/quit.png b/gtk/res/themes/gtk+/quit.png Binary files differnew file mode 100644 index 000000000..0c9de64ba --- /dev/null +++ b/gtk/res/themes/gtk+/quit.png diff --git a/gtk/res/themes/gtk+/reload.png b/gtk/res/themes/gtk+/reload.png Binary files differnew file mode 100644 index 000000000..09b5df1d1 --- /dev/null +++ b/gtk/res/themes/gtk+/reload.png diff --git a/gtk/res/themes/gtk+/savepage.png b/gtk/res/themes/gtk+/savepage.png Binary files differnew file mode 100644 index 000000000..5da8a02dc --- /dev/null +++ b/gtk/res/themes/gtk+/savepage.png diff --git a/gtk/res/themes/gtk+/selectall.png b/gtk/res/themes/gtk+/selectall.png Binary files differnew file mode 100644 index 000000000..1fc5b8282 --- /dev/null +++ b/gtk/res/themes/gtk+/selectall.png diff --git a/gtk/res/themes/gtk+/stop.png b/gtk/res/themes/gtk+/stop.png Binary files differnew file mode 100644 index 000000000..54e1cb3e9 --- /dev/null +++ b/gtk/res/themes/gtk+/stop.png diff --git a/gtk/res/themes/gtk+/viewsource.png b/gtk/res/themes/gtk+/viewsource.png Binary files differnew file mode 100644 index 000000000..9ddbe9b8e --- /dev/null +++ b/gtk/res/themes/gtk+/viewsource.png diff --git a/gtk/res/themes/gtk+/zoomminus.png b/gtk/res/themes/gtk+/zoomminus.png Binary files differnew file mode 100644 index 000000000..22afd1951 --- /dev/null +++ b/gtk/res/themes/gtk+/zoomminus.png diff --git a/gtk/res/themes/gtk+/zoomnormal.png b/gtk/res/themes/gtk+/zoomnormal.png Binary files differnew file mode 100644 index 000000000..499cbd6c6 --- /dev/null +++ b/gtk/res/themes/gtk+/zoomnormal.png diff --git a/gtk/res/themes/gtk+/zoomplus.png b/gtk/res/themes/gtk+/zoomplus.png Binary files differnew file mode 100644 index 000000000..3a386fae7 --- /dev/null +++ b/gtk/res/themes/gtk+/zoomplus.png diff --git a/gtk/res/toolbar.glade b/gtk/res/toolbar.glade new file mode 100644 index 000000000..7e5ff0fb5 --- /dev/null +++ b/gtk/res/toolbar.glade @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--Generated with glade3 3.4.5 on Tue Jun 9 08:21:40 2009 --> +<glade-interface> + <widget class="GtkWindow" id="toolbarwindow"> + <property name="width_request">700</property> + <property name="height_request">450</property> + <child> + <widget class="GtkVBox" id="windowvbox"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="toolbarlabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">move items from store to toolbar rearrange items in toolbar move items from toolbar to store</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <widget class="GtkViewport" id="viewport1"> + <property name="visible">True</property> + <property name="resize_mode">GTK_RESIZE_QUEUE</property> + <child> + <widget class="GtkVBox" id="widgetvbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="buttonhbox"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <widget class="GtkButton" id="resetbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkHBox" id="button1hbox"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-refresh</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="refreshbuttonlabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">reset default</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">10</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkButton" id="okbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-apply</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">10</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="cancelbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/res/warning.glade b/gtk/res/warning.glade new file mode 100644 index 000000000..edfa18076 --- /dev/null +++ b/gtk/res/warning.glade @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="wndWarning"> + <property name="title" translatable="yes">Warning from NetSurf</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="icon_name">gtk-dialog-warning</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="urgency_hint">True</property> + <child> + <widget class="GtkVBox" id="vbox32"> + <property name="visible">True</property> + <property name="border_width">2</property> + <child> + <widget class="GtkHBox" id="hbox30"> + <property name="visible">True</property> + <property name="border_width">3</property> + <child> + <widget class="GtkImage" id="image519"> + <property name="visible">True</property> + <property name="xpad">12</property> + <property name="icon_size">6</property> + <property name="icon_name">gtk-dialog-warning</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelWarning"> + <property name="visible">True</property> + <property name="label" translatable="yes">Help help help! I'm being held prisoner by a bunch of RISC OS zealots!</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="padding">1</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">3</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="button14"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + <signal name="clicked" handler="gtk_widget_hide" object="wndWarning"/> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/gtk/sexy_icon_entry.c b/gtk/sexy_icon_entry.c new file mode 100644 index 000000000..1dce22e31 --- /dev/null +++ b/gtk/sexy_icon_entry.c @@ -0,0 +1,979 @@ +/* + * libsexy/sexy-icon-entry.c Entry widget + * Copyright (C) 2004-2006 Christian Hammond. + * modified for NetSurf + * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * This file before modifications was originally part of LibSexy, + * http://www.chipx86.com/; it is redistributed under GPLv2 + * + * 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/> + * or write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gtk/sexy_icon_entry.h" +#include <string.h> +#include <gtk/gtk.h> + +#define ICON_MARGIN 2 +#define MAX_ICONS 2 + +#define IS_VALID_ICON_ENTRY_POSITION(pos) \ + ((pos) == SEXY_ICON_ENTRY_PRIMARY || \ + (pos) == SEXY_ICON_ENTRY_SECONDARY) + +typedef struct +{ + GtkImage *icon; + gboolean highlight; + gboolean hovered; + GdkWindow *window; + +} SexyIconInfo; + +struct _SexyIconEntryPriv +{ + SexyIconInfo icons[MAX_ICONS]; + + gulong icon_released_id; +}; + +enum +{ + ICON_PRESSED, + ICON_RELEASED, + LAST_SIGNAL +}; + +/* static void sexy_icon_entry_class_init(SexyIconEntryClass *klass); */ +static void sexy_icon_entry_editable_init(GtkEditableClass *iface); +/* static void sexy_icon_entry_init(SexyIconEntry *entry); */ +static void sexy_icon_entry_finalize(GObject *obj); +static void sexy_icon_entry_destroy(GtkObject *obj); +static void sexy_icon_entry_map(GtkWidget *widget); +static void sexy_icon_entry_unmap(GtkWidget *widget); +static void sexy_icon_entry_realize(GtkWidget *widget); +static void sexy_icon_entry_unrealize(GtkWidget *widget); +static void sexy_icon_entry_size_request(GtkWidget *widget, + GtkRequisition *requisition); +static void sexy_icon_entry_size_allocate(GtkWidget *widget, + GtkAllocation *allocation); +static gint sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event); +static gint sexy_icon_entry_enter_notify(GtkWidget *widget, + GdkEventCrossing *event); +static gint sexy_icon_entry_leave_notify(GtkWidget *widget, + GdkEventCrossing *event); +static gint sexy_icon_entry_button_press(GtkWidget *widget, + GdkEventButton *event); +static gint sexy_icon_entry_button_release(GtkWidget *widget, + GdkEventButton *event); + +static GtkEntryClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE_EXTENDED(SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY, + 0, + G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE, + sexy_icon_entry_editable_init)); + +void +sexy_icon_entry_class_init(SexyIconEntryClass *klass) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkEntryClass *entry_class; + + parent_class = g_type_class_peek_parent(klass); + + gobject_class = G_OBJECT_CLASS(klass); + object_class = GTK_OBJECT_CLASS(klass); + widget_class = GTK_WIDGET_CLASS(klass); + entry_class = GTK_ENTRY_CLASS(klass); + + gobject_class->finalize = sexy_icon_entry_finalize; + + object_class->destroy = sexy_icon_entry_destroy; + + widget_class->map = sexy_icon_entry_map; + widget_class->unmap = sexy_icon_entry_unmap; + widget_class->realize = sexy_icon_entry_realize; + widget_class->unrealize = sexy_icon_entry_unrealize; + widget_class->size_request = sexy_icon_entry_size_request; + widget_class->size_allocate = sexy_icon_entry_size_allocate; + widget_class->expose_event = sexy_icon_entry_expose; + widget_class->enter_notify_event = sexy_icon_entry_enter_notify; + widget_class->leave_notify_event = sexy_icon_entry_leave_notify; + widget_class->button_press_event = sexy_icon_entry_button_press; + widget_class->button_release_event = sexy_icon_entry_button_release; + + /** + * SexyIconEntry::icon-pressed: + * @entry: The entry on which the signal is emitted. + * @icon_pos: The position of the clicked icon. + * @button: The mouse button clicked. + * + * The ::icon-pressed signal is emitted when an icon is clicked. + */ + /* signal modified to compile directly in NetSurf - param 8 of + * g_signal_new() changed from marshal type to NULL - so there may + * well be no working signal */ + signals[ICON_PRESSED] = + g_signal_new("icon_pressed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(SexyIconEntryClass, icon_pressed), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + + /** + * SexyIconEntry::icon-released: + * @entry: The entry on which the signal is emitted. + * @icon_pos: The position of the clicked icon. + * @button: The mouse button clicked. + * + * The ::icon-released signal is emitted on the button release from a + * mouse click. + */ + /* signal modified to compile directly in NetSurf - param 8 of + * g_signal_new() changed from marshal type to NULL - so there may + * well be no working signal */ + signals[ICON_RELEASED] = + g_signal_new("icon_released", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(SexyIconEntryClass, icon_released), + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); +} + +static void +sexy_icon_entry_editable_init(GtkEditableClass *iface) +{ +}; + +void +sexy_icon_entry_init(SexyIconEntry *entry) +{ + entry->priv = g_new0(SexyIconEntryPriv, 1); +} + +static void +sexy_icon_entry_finalize(GObject *obj) +{ + SexyIconEntry *entry; + + g_return_if_fail(obj != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(obj)); + + entry = SEXY_ICON_ENTRY(obj); + + g_free(entry->priv); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj); +} + +static void +sexy_icon_entry_destroy(GtkObject *obj) +{ + SexyIconEntry *entry; + + entry = SEXY_ICON_ENTRY(obj); + + sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_PRIMARY, NULL); + sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_SECONDARY, NULL); + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(obj); +} + +static void +sexy_icon_entry_map(GtkWidget *widget) +{ + if (GTK_WIDGET_REALIZED(widget) && !GTK_WIDGET_MAPPED(widget)) + { + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + GTK_WIDGET_CLASS(parent_class)->map(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + if (entry->priv->icons[i].icon != NULL) + gdk_window_show(entry->priv->icons[i].window); + } + } +} + +static void +sexy_icon_entry_unmap(GtkWidget *widget) +{ + if (GTK_WIDGET_MAPPED(widget)) + { + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (entry->priv->icons[i].icon != NULL) + gdk_window_hide(entry->priv->icons[i].window); + } + + GTK_WIDGET_CLASS(parent_class)->unmap(widget); + } +} + +static gint +get_icon_width(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) +{ + GtkRequisition requisition; + gint menu_icon_width; + gint width; + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + + if (icon_info->icon == NULL) + return 0; + + gtk_widget_size_request(GTK_WIDGET(icon_info->icon), &requisition); + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &menu_icon_width, NULL); + + width = MAX(requisition.width, menu_icon_width); + + return width; +} + +static void +get_borders(SexyIconEntry *entry, gint *xborder, gint *yborder) +{ + GtkWidget *widget = GTK_WIDGET(entry); + gint focus_width; + gboolean interior_focus; + + gtk_widget_style_get(widget, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, + NULL); + + if (gtk_entry_get_has_frame(GTK_ENTRY(entry))) + { + *xborder = widget->style->xthickness; + *yborder = widget->style->ythickness; + } + else + { + *xborder = 0; + *yborder = 0; + } + + if (!interior_focus) + { + *xborder += focus_width; + *yborder += focus_width; + } +} + +static void +get_text_area_size(SexyIconEntry *entry, GtkAllocation *alloc) +{ + GtkWidget *widget = GTK_WIDGET(entry); + GtkRequisition requisition; + gint xborder, yborder; + + gtk_widget_get_child_requisition(widget, &requisition); + get_borders(entry, &xborder, &yborder); + + alloc->x = xborder; + alloc->y = yborder; + alloc->width = widget->allocation.width - xborder * 2; + alloc->height = requisition.height - yborder * 2; +} + +static void +get_icon_allocation(SexyIconEntry *icon_entry, + gboolean left, + GtkAllocation *widget_alloc, + GtkAllocation *text_area_alloc, + GtkAllocation *allocation, + SexyIconEntryPosition *icon_pos) +{ + gboolean rtl; + + rtl = (gtk_widget_get_direction(GTK_WIDGET(icon_entry)) == + GTK_TEXT_DIR_RTL); + + if (left) + *icon_pos = (rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY); + else + *icon_pos = (rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY); + + allocation->y = text_area_alloc->y; + allocation->width = get_icon_width(icon_entry, *icon_pos); + allocation->height = text_area_alloc->height; + + if (left) + allocation->x = text_area_alloc->x + ICON_MARGIN; + else + { + allocation->x = text_area_alloc->x + text_area_alloc->width - + allocation->width - ICON_MARGIN; + } +} + +static void +sexy_icon_entry_realize(GtkWidget *widget) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + GdkWindowAttr attributes; + gint attributes_mask; + int i; + + GTK_WIDGET_CLASS(parent_class)->realize(widget); + + attributes.x = 0; + attributes.y = 0; + attributes.width = 1; + attributes.height = 1; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual(widget); + attributes.colormap = gtk_widget_get_colormap(widget); + attributes.event_mask = gtk_widget_get_events(widget); + attributes.event_mask |= + (GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + for (i = 0; i < MAX_ICONS; i++) + { + SexyIconInfo *icon_info; + + icon_info = &entry->priv->icons[i]; + icon_info->window = gdk_window_new(widget->window, &attributes, + attributes_mask); + gdk_window_set_user_data(icon_info->window, widget); + + gdk_window_set_background(icon_info->window, + &widget->style->base[GTK_WIDGET_STATE(widget)]); + } + + gtk_widget_queue_resize(widget); +} + +static void +sexy_icon_entry_unrealize(GtkWidget *widget) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + SexyIconInfo *icon_info = &entry->priv->icons[i]; + + gdk_window_destroy(icon_info->window); + icon_info->window = NULL; + } +} + +static void +sexy_icon_entry_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + GtkEntry *gtkentry; + SexyIconEntry *entry; + gint icon_widths = 0; + int i; + + gtkentry = GTK_ENTRY(widget); + entry = SEXY_ICON_ENTRY(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + int icon_width = get_icon_width(entry, i); + + if (icon_width > 0) + icon_widths += icon_width + ICON_MARGIN; + } + + GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition); + + if (icon_widths > requisition->width) + requisition->width += icon_widths; +} + +static void +place_windows(SexyIconEntry *icon_entry, GtkAllocation *widget_alloc) +{ + SexyIconEntryPosition left_icon_pos; + SexyIconEntryPosition right_icon_pos; + GtkAllocation left_icon_alloc; + GtkAllocation right_icon_alloc; + GtkAllocation text_area_alloc; + + get_text_area_size(icon_entry, &text_area_alloc); + get_icon_allocation(icon_entry, TRUE, widget_alloc, &text_area_alloc, + &left_icon_alloc, &left_icon_pos); + get_icon_allocation(icon_entry, FALSE, widget_alloc, &text_area_alloc, + &right_icon_alloc, &right_icon_pos); + + if (left_icon_alloc.width > 0) + { + text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width + + ICON_MARGIN; + } + + if (right_icon_alloc.width > 0) + text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN; + + text_area_alloc.width -= text_area_alloc.x; + + gdk_window_move_resize(icon_entry->priv->icons[left_icon_pos].window, + left_icon_alloc.x, left_icon_alloc.y, + left_icon_alloc.width, left_icon_alloc.height); + + gdk_window_move_resize(icon_entry->priv->icons[right_icon_pos].window, + right_icon_alloc.x, right_icon_alloc.y, + right_icon_alloc.width, right_icon_alloc.height); + + gdk_window_move_resize(GTK_ENTRY(icon_entry)->text_area, + text_area_alloc.x, text_area_alloc.y, + text_area_alloc.width, text_area_alloc.height); +} + +static void +sexy_icon_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + g_return_if_fail(SEXY_IS_ICON_ENTRY(widget)); + g_return_if_fail(allocation != NULL); + + widget->allocation = *allocation; + + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); + + if (GTK_WIDGET_REALIZED(widget)) + place_windows(SEXY_ICON_ENTRY(widget), allocation); +} + +static GdkPixbuf * +get_pixbuf_from_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) +{ + GdkPixbuf *pixbuf = NULL; + gchar *stock_id; + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + GtkIconSize size; + + switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info->icon))) + { + case GTK_IMAGE_PIXBUF: + pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(icon_info->icon)); + g_object_ref(pixbuf); + break; + + case GTK_IMAGE_STOCK: + gtk_image_get_stock(GTK_IMAGE(icon_info->icon), &stock_id, &size); + pixbuf = gtk_widget_render_icon(GTK_WIDGET(entry), + stock_id, size, NULL); + break; + + default: + return NULL; + } + + return pixbuf; +} + +/* Kudos to the gnome-panel guys. */ +static void +colorshift_pixbuf(GdkPixbuf *dest, GdkPixbuf *src, int shift) +{ + gint i, j; + gint width, height, has_alpha, src_rowstride, dest_rowstride; + guchar *target_pixels; + guchar *original_pixels; + guchar *pix_src; + guchar *pix_dest; + int val; + guchar r, g, b; + + has_alpha = gdk_pixbuf_get_has_alpha(src); + width = gdk_pixbuf_get_width(src); + height = gdk_pixbuf_get_height(src); + src_rowstride = gdk_pixbuf_get_rowstride(src); + dest_rowstride = gdk_pixbuf_get_rowstride(dest); + original_pixels = gdk_pixbuf_get_pixels(src); + target_pixels = gdk_pixbuf_get_pixels(dest); + + for (i = 0; i < height; i++) + { + pix_dest = target_pixels + i * dest_rowstride; + pix_src = original_pixels + i * src_rowstride; + + for (j = 0; j < width; j++) + { + r = *(pix_src++); + g = *(pix_src++); + b = *(pix_src++); + + val = r + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + val = g + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + val = b + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + if (has_alpha) + *(pix_dest++) = *(pix_src++); + } + } +} + +static void +draw_icon(GtkWidget *widget, SexyIconEntryPosition icon_pos) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + GdkPixbuf *pixbuf; + gint x, y, width, height; + + if (icon_info->icon == NULL || !GTK_WIDGET_REALIZED(widget)) + return; + + if ((pixbuf = get_pixbuf_from_icon(entry, icon_pos)) == NULL) + return; + + gdk_drawable_get_size(icon_info->window, &width, &height); + + if (width == 1 || height == 1) + { + /* + * size_allocate hasn't been called yet. These are the default values. + */ + return; + } + + if (gdk_pixbuf_get_height(pixbuf) > height) + { + GdkPixbuf *temp_pixbuf; + int scale; + + scale = height - (2 * ICON_MARGIN); + + temp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, scale, scale, + GDK_INTERP_BILINEAR); + + g_object_unref(pixbuf); + + pixbuf = temp_pixbuf; + } + + x = (width - gdk_pixbuf_get_width(pixbuf)) / 2; + y = (height - gdk_pixbuf_get_height(pixbuf)) / 2; + + if (icon_info->hovered) + { + GdkPixbuf *temp_pixbuf; + + temp_pixbuf = gdk_pixbuf_copy(pixbuf); + + colorshift_pixbuf(temp_pixbuf, pixbuf, 30); + + g_object_unref(pixbuf); + + pixbuf = temp_pixbuf; + } + + gdk_draw_pixbuf(icon_info->window, widget->style->black_gc, pixbuf, + 0, 0, x, y, -1, -1, + GDK_RGB_DITHER_NORMAL, 0, 0); + + g_object_unref(pixbuf); +} + +static gint +sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event) +{ + SexyIconEntry *entry; + + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + entry = SEXY_ICON_ENTRY(widget); + + if (GTK_WIDGET_DRAWABLE(widget)) + { + gboolean found = FALSE; + int i; + + for (i = 0; i < MAX_ICONS && !found; i++) + { + SexyIconInfo *icon_info = &entry->priv->icons[i]; + + if (event->window == icon_info->window) + { + gint width; + GtkAllocation text_area_alloc; + + get_text_area_size(entry, &text_area_alloc); + gdk_drawable_get_size(icon_info->window, &width, NULL); + + gtk_paint_flat_box(widget->style, icon_info->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, + NULL, widget, "entry_bg", + 0, 0, width, text_area_alloc.height); + + draw_icon(widget, i); + + found = TRUE; + } + } + + if (!found) + GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); + } + + return FALSE; +} + +static void +update_icon(GObject *obj, GParamSpec *param, SexyIconEntry *entry) +{ + if (param != NULL) + { + const char *name = g_param_spec_get_name(param); + + if (strcmp(name, "pixbuf") && strcmp(name, "stock") && + strcmp(name, "image") && strcmp(name, "pixmap") && + strcmp(name, "icon_set") && strcmp(name, "pixbuf_animation")) + { + return; + } + } + + gtk_widget_queue_resize(GTK_WIDGET(entry)); +} + +static gint +sexy_icon_entry_enter_notify(GtkWidget *widget, GdkEventCrossing *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = TRUE; + + update_icon(NULL, NULL, entry); + + break; + } + } + } + + return FALSE; +} + +static gint +sexy_icon_entry_leave_notify(GtkWidget *widget, GdkEventCrossing *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = FALSE; + + update_icon(NULL, NULL, entry); + + break; + } + } + } + + return FALSE; +} + +static gint +sexy_icon_entry_button_press(GtkWidget *widget, GdkEventButton *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (event->button == 1 && + sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = FALSE; + + update_icon(NULL, NULL, entry); + } + + g_signal_emit(entry, signals[ICON_PRESSED], 0, i, event->button); + + return TRUE; + } + } + + if (GTK_WIDGET_CLASS(parent_class)->button_press_event) + return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, + event); + + return FALSE; +} + +static gint +sexy_icon_entry_button_release(GtkWidget *widget, GdkEventButton *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + GdkWindow *icon_window = entry->priv->icons[i].window; + + if (event->window == icon_window) + { + int width, height; + gdk_drawable_get_size(icon_window, &width, &height); + + if (event->button == 1 && + sexy_icon_entry_get_icon_highlight(entry, i) && + event->x >= 0 && event->y >= 0 && + event->x <= width && event->y <= height) + { + entry->priv->icons[i].hovered = TRUE; + + update_icon(NULL, NULL, entry); + } + + g_signal_emit(entry, signals[ICON_RELEASED], 0, i, event->button); + + return TRUE; + } + } + + if (GTK_WIDGET_CLASS(parent_class)->button_release_event) + return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, + event); + + return FALSE; +} + +/** + * sexy_icon_entry_new + * + * Creates a new SexyIconEntry widget. + * + * Returns a new #SexyIconEntry. + */ +GtkWidget * +sexy_icon_entry_new(void) +{ + return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY, NULL)); +} + +/** + * sexy_icon_entry_set_icon + * @entry: A #SexyIconEntry. + * @position: Icon position. + * @icon: A #GtkImage to set as the icon. + * + * Sets the icon shown in the entry + */ +void +sexy_icon_entry_set_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + GtkImage *icon) +{ + SexyIconInfo *icon_info; + + g_return_if_fail(entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); + g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); + g_return_if_fail(icon == NULL || GTK_IS_IMAGE(icon)); + + icon_info = &entry->priv->icons[icon_pos]; + + if (icon == icon_info->icon) + return; + + if (icon_pos == SEXY_ICON_ENTRY_SECONDARY && + entry->priv->icon_released_id != 0) + { + g_signal_handler_disconnect(entry, entry->priv->icon_released_id); + entry->priv->icon_released_id = 0; + } + + if (icon == NULL) + { + if (icon_info->icon != NULL) + { + gtk_widget_destroy(GTK_WIDGET(icon_info->icon)); + icon_info->icon = NULL; + + /* + * Explicitly check, as the pointer may become invalidated + * during destruction. + */ + if (icon_info->window != NULL && GDK_IS_WINDOW(icon_info->window)) + gdk_window_hide(icon_info->window); + } + } + else + { + if (icon_info->window != NULL && icon_info->icon == NULL) + gdk_window_show(icon_info->window); + + g_signal_connect(G_OBJECT(icon), "notify", + G_CALLBACK(update_icon), entry); + + icon_info->icon = icon; + g_object_ref(icon); + } + + update_icon(NULL, NULL, entry); +} + +/** + * sexy_icon_entry_set_icon_highlight + * @entry: A #SexyIconEntry; + * @position: Icon position. + * @highlight: TRUE if the icon should highlight on mouse-over + * + * Determines whether the icon will highlight on mouse-over. + */ +void +sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, + SexyIconEntryPosition icon_pos, + gboolean highlight) +{ + SexyIconInfo *icon_info; + + g_return_if_fail(entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); + g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); + + icon_info = &entry->priv->icons[icon_pos]; + + if (icon_info->highlight == highlight) + return; + + icon_info->highlight = highlight; +} + +/** + * sexy_icon_entry_get_icon + * @entry: A #SexyIconEntry. + * @position: Icon position. + * + * Retrieves the image used for the icon + * + * Returns: A #GtkImage. + */ +GtkImage * +sexy_icon_entry_get_icon(const SexyIconEntry *entry, + SexyIconEntryPosition icon_pos) +{ + g_return_val_if_fail(entry != NULL, NULL); + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), NULL); + g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), NULL); + + return entry->priv->icons[icon_pos].icon; +} + +/** + * sexy_icon_entry_get_icon_highlight + * @entry: A #SexyIconEntry. + * @position: Icon position. + * + * Retrieves whether entry will highlight the icon on mouseover. + * + * Returns: TRUE if icon highlights. + */ +gboolean +sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, + SexyIconEntryPosition icon_pos) +{ + g_return_val_if_fail(entry != NULL, FALSE); + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), FALSE); + g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), FALSE); + + return entry->priv->icons[icon_pos].highlight; +} + +static void +clear_button_clicked_cb(SexyIconEntry *icon_entry, + SexyIconEntryPosition icon_pos, + int button) +{ + if (icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1) + return; + + gtk_entry_set_text(GTK_ENTRY(icon_entry), ""); +} + +/** + * sexy_icon_entry_add_clear_button + * @icon_entry: A #SexyIconEntry. + * + * A convenience function to add a clear button to the end of the entry. + * This is useful for search boxes. + */ +void +sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry) +{ + GtkWidget *icon; + + g_return_if_fail(icon_entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry)); + + icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU); + gtk_widget_show(icon); + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry), + SEXY_ICON_ENTRY_SECONDARY, + GTK_IMAGE(icon)); + sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry), + SEXY_ICON_ENTRY_SECONDARY, TRUE); + + if (icon_entry->priv->icon_released_id != 0) + { + g_signal_handler_disconnect(icon_entry, + icon_entry->priv->icon_released_id); + } + + icon_entry->priv->icon_released_id = + g_signal_connect(G_OBJECT(icon_entry), "icon_released", + G_CALLBACK(clear_button_clicked_cb), NULL); +} diff --git a/gtk/sexy_icon_entry.h b/gtk/sexy_icon_entry.h new file mode 100644 index 000000000..94ba90833 --- /dev/null +++ b/gtk/sexy_icon_entry.h @@ -0,0 +1,101 @@ +/* + * file libsexy/sexy-icon-entry.h Entry widget + * + * Copyright (C) 2004-2006 Christian Hammond. + * redistributed under GPLv2 + * + * libsexy 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/> + * or write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _SEXY_ICON_ENTRY_H_ +#define _SEXY_ICON_ENTRY_H_ + +typedef struct _SexyIconEntry SexyIconEntry; +typedef struct _SexyIconEntryClass SexyIconEntryClass; +typedef struct _SexyIconEntryPriv SexyIconEntryPriv; + +#include <gtk/gtkentry.h> +#include <gtk/gtkimage.h> + +#define SEXY_TYPE_ICON_ENTRY (sexy_icon_entry_get_type()) +#define SEXY_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntry)) +#define SEXY_ICON_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) +#define SEXY_IS_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), SEXY_TYPE_ICON_ENTRY)) +#define SEXY_IS_ICON_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), SEXY_TYPE_ICON_ENTRY)) +#define SEXY_ICON_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) + +typedef enum +{ + SEXY_ICON_ENTRY_PRIMARY, + SEXY_ICON_ENTRY_SECONDARY + +} SexyIconEntryPosition; + +struct _SexyIconEntry +{ + GtkEntry parent_object; + + SexyIconEntryPriv *priv; + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +struct _SexyIconEntryClass +{ + GtkEntryClass parent_class; + + /* Signals */ + void (*icon_pressed)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + int button); + void (*icon_released)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + int button); + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType sexy_icon_entry_get_type(void); + +GtkWidget *sexy_icon_entry_new(void); + +void sexy_icon_entry_set_icon(SexyIconEntry *entry, + SexyIconEntryPosition position, + GtkImage *icon); + +void sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, + SexyIconEntryPosition position, + gboolean highlight); + +GtkImage *sexy_icon_entry_get_icon(const SexyIconEntry *entry, + SexyIconEntryPosition position); + +gboolean sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, + SexyIconEntryPosition position); +void sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry); + +G_END_DECLS + +#endif /* _SEXY_ICON_ENTRY_H_ */ |