summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--!NetSurf/Resources/Icons/content.pngbin0 -> 685 bytes
-rw-r--r--!NetSurf/Resources/Icons/directory.pngbin0 -> 259 bytes
-rw-r--r--!NetSurf/Resources/de/Messages10
-rw-r--r--!NetSurf/Resources/en/Messages33
-rw-r--r--!NetSurf/Resources/fr/Messages10
-rwxr-xr-x!NetSurf/Resources/it/Messages10
-rw-r--r--!NetSurf/Resources/nl/Messages10
-rw-r--r--Makefile.sources27
-rwxr-xr-xamiga/cookies.c149
-rwxr-xr-xamiga/cookies.h5
-rwxr-xr-xamiga/gui.c89
-rwxr-xr-xamiga/gui.h12
-rwxr-xr-xamiga/history.c357
-rwxr-xr-xamiga/history.h3
-rwxr-xr-xamiga/hotlist.c134
-rwxr-xr-xamiga/hotlist.h9
-rwxr-xr-xamiga/menu.c476
-rwxr-xr-xamiga/menu.h15
-rwxr-xr-xamiga/object.c14
-rwxr-xr-xamiga/object.h1
-rw-r--r--amiga/options.h3
-rwxr-xr-xamiga/plotters.c20
-rwxr-xr-xamiga/resources/Themes/AISS/Theme8
-rwxr-xr-xamiga/resources/Themes/Default/Theme8
l---------amiga/resources/Themes/Default/content.png1
l---------amiga/resources/Themes/Default/directory.png1
-rw-r--r--amiga/sslcert.c216
-rw-r--r--amiga/sslcert.h (renamed from windows/hotlist.c)12
-rw-r--r--amiga/theme.c17
-rw-r--r--amiga/theme.h2
-rwxr-xr-xamiga/tree.c1313
-rwxr-xr-xamiga/tree.h29
-rw-r--r--beos/beos_bitmap.cpp10
-rw-r--r--beos/beos_gui.cpp7
-rw-r--r--beos/beos_history.cpp183
-rw-r--r--beos/beos_scaffolding.cpp1
-rw-r--r--beos/beos_treeview.cpp140
-rw-r--r--content/urldb.c64
-rw-r--r--content/urldb.h3
-rw-r--r--desktop/browser.c1
-rw-r--r--desktop/cookies.c531
-rw-r--r--desktop/cookies.h36
-rw-r--r--desktop/history_global_core.c464
-rw-r--r--desktop/history_global_core.h44
-rw-r--r--desktop/hotlist.c457
-rw-r--r--desktop/hotlist.h54
-rw-r--r--desktop/options.c363
-rw-r--r--desktop/options.h5
-rw-r--r--desktop/sslcert.c276
-rw-r--r--desktop/sslcert.h43
-rw-r--r--desktop/tree.c3090
-rw-r--r--desktop/tree.h281
-rw-r--r--desktop/tree_url_node.c846
-rw-r--r--desktop/tree_url_node.h56
-rw-r--r--framebuffer/misc.c6
-rw-r--r--framebuffer/tree.c83
-rw-r--r--gtk/gtk_cookies.c213
-rw-r--r--gtk/gtk_cookies.h (renamed from framebuffer/hotlist.c)20
-rw-r--r--gtk/gtk_gui.c149
-rw-r--r--gtk/gtk_history.c703
-rw-r--r--gtk/gtk_history.h18
-rw-r--r--gtk/gtk_hotlist.c277
-rw-r--r--gtk/gtk_hotlist.h (renamed from framebuffer/history.c)30
-rw-r--r--gtk/gtk_menu.c3
-rw-r--r--gtk/gtk_menu.h1
-rw-r--r--gtk/gtk_plotters.c14
-rw-r--r--gtk/gtk_scaffolding.c33
-rw-r--r--gtk/gtk_scaffolding.h2
-rw-r--r--gtk/gtk_theme.c2
-rw-r--r--gtk/gtk_toolbar.c2
-rw-r--r--gtk/gtk_toolbar.h1
-rw-r--r--gtk/gtk_treeview.c545
-rw-r--r--gtk/gtk_treeview.h50
-rw-r--r--gtk/gtk_window.c2
-rw-r--r--gtk/options.h3
-rw-r--r--gtk/res/cookies.glade174
-rw-r--r--gtk/res/history.glade358
-rw-r--r--gtk/res/hotlist.glade218
l---------gtk/res/icons1
-rw-r--r--gtk/res/ssl.glade19
-rw-r--r--riscos/configure/con_home.c6
-rw-r--r--riscos/cookies.c346
-rw-r--r--riscos/cookies.h10
-rw-r--r--riscos/dialog.c76
-rw-r--r--riscos/global_history.c534
-rw-r--r--riscos/global_history.h12
-rw-r--r--riscos/gui.c81
-rw-r--r--riscos/gui.h17
-rw-r--r--riscos/help.c28
-rw-r--r--riscos/hotlist.c540
-rw-r--r--riscos/hotlist.h (renamed from beos/beos_history.h)28
-rw-r--r--riscos/menus.c682
-rw-r--r--riscos/menus.h20
-rw-r--r--riscos/save.c14
-rw-r--r--riscos/sslcert.c515
-rw-r--r--riscos/sslcert.h32
-rw-r--r--riscos/textselection.c25
-rw-r--r--riscos/theme.c28
-rw-r--r--riscos/treeview.c2044
-rw-r--r--riscos/treeview.h49
-rw-r--r--riscos/url_complete.c6
-rw-r--r--riscos/url_suggest.c200
-rw-r--r--riscos/url_suggest.h (renamed from windows/history.c)29
-rw-r--r--riscos/wimp_event.c203
-rw-r--r--riscos/wimp_event.h22
-rw-r--r--riscos/window.c78
-rw-r--r--utils/messages.c31
-rw-r--r--utils/messages.h12
-rw-r--r--windows/tree.c83
109 files changed, 11096 insertions, 7531 deletions
diff --git a/!NetSurf/Resources/Icons/content.png b/!NetSurf/Resources/Icons/content.png
new file mode 100644
index 000000000..53234c38c
--- /dev/null
+++ b/!NetSurf/Resources/Icons/content.png
Binary files differ
diff --git a/!NetSurf/Resources/Icons/directory.png b/!NetSurf/Resources/Icons/directory.png
new file mode 100644
index 000000000..de3d7687f
--- /dev/null
+++ b/!NetSurf/Resources/Icons/directory.png
Binary files differ
diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages
index 175f20008..0349c6f7c 100644
--- a/!NetSurf/Resources/de/Messages
+++ b/!NetSurf/Resources/de/Messages
@@ -189,6 +189,8 @@ ResetUsage:Statistik zurücksetzen
New:Neu
Expand:Expandieren
Collapse:Zusammenfalten
+Tree:Tree
+TreeExport:Export...
# New hotlist entry menu
#
@@ -200,6 +202,7 @@ Link:Eintrag
All:Alles
Folders:Verzeichnisse
Links:Einträge
+Domains:Domains
# Other menus
#
@@ -373,6 +376,13 @@ DateYesterday:Gestern
Date1Week:vorige Woche
Date2Week:vor 2 Wochen
Date3Week:vor 3 Wochen
+Sunday:Sunday
+Monday:Monday
+Tuesday:Tuesday
+Wednesday:Wednesday
+Thursday:Thursday
+Friday:Friday
+Saturday:Saturday
# Download user interface tokens
diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages
index 6d62ac3cd..84ea3f69f 100644
--- a/!NetSurf/Resources/en/Messages
+++ b/!NetSurf/Resources/en/Messages
@@ -189,6 +189,8 @@ ResetUsage:Reset statistics
New:New
Expand:Expand
Collapse:Collapse
+Tree:Tree
+TreeExport:Export...
# New hotlist entry menu
#
@@ -200,6 +202,7 @@ Link:Address
All:All
Folders:Directories
Links:Addresses
+Domains:Domains
# Other menus
#
@@ -332,6 +335,7 @@ TreeNewFolder:New directory
TreeLaunch:Visit URL
TreeDelete:Delete
+
# Tree export
#
TreeHotlist:NetSurf hotlist
@@ -374,6 +378,13 @@ DateYesterday:Yesterday
Date1Week:Last week
Date2Week:2 weeks ago
Date3Week:3 weeks ago
+Sunday:Sunday
+Monday:Monday
+Tuesday:Tuesday
+Wednesday:Wednesday
+Thursday:Thursday
+Friday:Friday
+Saturday:Saturday
# Download user interface tokens
@@ -534,6 +545,8 @@ gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks…
gtkShowBookMarks:_Show Bookmarks…
gtkShowBookMarksAccel:F6
+gtkShowCookies:Show _Cookies…
+gtkShowCookiesAccel:F9
gtkOpenLocation:_Open Location…
gtkOpenLocationAccel:<ctrl>l
@@ -607,15 +620,15 @@ Cancel:Cancel
#
SSLCerts:SSL certificates
SSLError:NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.
-Subject:Subject
-Issuer:Issuer
-Version:Version
-ValidFrom:Valid from
-ValidTo:Valid until
-Type:Type
-Serial:Serial
-Accept:Accept
-Reject:Reject
+SSL_Certificate_Subject:Subject: %s
+SSL_Certificate_Issuer:Issuer: %s
+SSL_Certificate_Version:Version: %ld
+SSL_Certificate_ValidFrom:Valid from: %s
+SSL_Certificate_ValidTo:Valid until: %s
+SSL_Certificate_Type:Type: %i
+SSL_Certificate_Serial:Serial: %ld
+SSL_Certificate_Accept:Accept
+SSL_Certificate_Reject:Reject
# Content
@@ -723,7 +736,7 @@ Resolvers:No domain name servers are configured, so only browsing local files wi
NoDiscSpace:Not enough space available on disc.
Template:A window template is missing from the Templates file. Please reinstall NetSurf.
HotlistSaveError:The hotlist was unable to be correctly saved.
-HotlistLoadError:The hotlist was unable to be correctly loaded.
+TreeLoadError:The tree was unable to be correctly loaded.
NoDirError:%s is not a directory
NoPathError:To save, drag the icon to a directory display
NoNameError:Please enter a name
diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages
index bfe563d90..c16d0f09a 100644
--- a/!NetSurf/Resources/fr/Messages
+++ b/!NetSurf/Resources/fr/Messages
@@ -189,6 +189,8 @@ ResetUsage:RAZ des statistiques
New:Nouveau
Expand:Déployer
Collapse:Regrouper
+Tree:Tree
+TreeExport:Export...
# New hotlist entry menu
#
@@ -200,6 +202,7 @@ Link:Adresse
All:Tout
Folders:Dossiers
Links:Adresses
+Domains:Domains
# Other menus
#
@@ -373,6 +376,13 @@ DateYesterday:Hier
Date1Week:La semaine dernière
Date2Week:Il y a 2 semaines
Date3Week:Il y a 3 semaines
+Sunday:Sunday
+Monday:Monday
+Tuesday:Tuesday
+Wednesday:Wednesday
+Thursday:Thursday
+Friday:Friday
+Saturday:Saturday
# Download user interface tokens
diff --git a/!NetSurf/Resources/it/Messages b/!NetSurf/Resources/it/Messages
index e79ce93a5..7d4e834de 100755
--- a/!NetSurf/Resources/it/Messages
+++ b/!NetSurf/Resources/it/Messages
@@ -191,6 +191,8 @@ ResetUsage:Resetta statistiche
New:Nuovo
Expand:Espandi
Collapse:Raggruppa
+Tree:Tree
+TreeExport:Export...
# New hotlist entry menu
#
@@ -202,6 +204,7 @@ Link:Indirizzo
All:Tutte
Folders:Cartelle
Links:Indirizzi
+Domains:Domains
# Other menus
#
@@ -375,6 +378,13 @@ DateYesterday:Ieri
Date1Week:Ultima settimana
Date2Week:2 settimane fa
Date3Week:3 settimane fa
+Sunday:Sunday
+Monday:Monday
+Tuesday:Tuesday
+Wednesday:Wednesday
+Thursday:Thursday
+Friday:Friday
+Saturday:Saturday
# Download user interface tokens
diff --git a/!NetSurf/Resources/nl/Messages b/!NetSurf/Resources/nl/Messages
index 2c1b3fa9b..f837f7dbd 100644
--- a/!NetSurf/Resources/nl/Messages
+++ b/!NetSurf/Resources/nl/Messages
@@ -189,6 +189,8 @@ ResetUsage:Statistiek op nul zetten
New:Nieuw
Expand:Uitklappen
Collapse:Inklappen
+Tree:Tree
+TreeExport:Export...
# New hotlist entry menu
#
@@ -200,6 +202,7 @@ Link:Adres
All:Alles
Folders:Mappen
Links:Adressen
+Domains:Domains
# Other menus
#
@@ -373,6 +376,13 @@ DateYesterday:gisteren
Date1Week:vorige week
Date2Week:2 weken geleden
Date3Week:3 weken geleden
+Sunday:Sunday
+Monday:Monday
+Tuesday:Tuesday
+Wednesday:Wednesday
+Thursday:Thursday
+Friday:Friday
+Saturday:Saturday
# Download user interface tokens
diff --git a/Makefile.sources b/Makefile.sources
index 57166df51..2239cc7cd 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -13,8 +13,9 @@ S_RENDER := box.c box_construct.c box_normalise.c favicon.c \
hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c
S_UTILS := base64.c filename.c hashtable.c http.c locale.c messages.c \
talloc.c url.c utf8.c utils.c useragent.c findresource.c
-S_DESKTOP := knockout.c options.c plot_style.c print.c search.c \
- searchweb.c scroll.c textarea.c tree.c version.c
+S_DESKTOP := cookies.c history_global_core.c hotlist.c knockout.c \
+ options.c plot_style.c print.c search.c searchweb.c scroll.c \
+ sslcert.c textarea.c tree.c tree_url_node.c version.c \
# S_COMMON are sources common to all builds
S_COMMON := $(addprefix content/,$(S_CONTENT)) \
@@ -47,7 +48,7 @@ S_RISCOS := 401login.c artworks.c assert.c awrender.s bitmap.c buffer.c \
schedule.c search.c searchweb.c sprite.c sslcert.c \
textarea.c textselection.c theme.c theme_install.c thumbnail.c \
treeview.c ucstables.c uri.c url_complete.c url_protocol.c \
- wimp.c wimp_event.c window.c gui/progress_bar.c \
+ url_suggest.c wimp.c wimp_event.c window.c gui/progress_bar.c \
gui/status_bar.c \
$(addprefix configure/,con_cache.c con_connect.c con_content.c \
con_fonts.c con_home.c con_image.c con_inter.c con_language.c \
@@ -62,22 +63,22 @@ S_GTK := font_pango.c gtk_bitmap.c gtk_gui.c gtk_schedule.c \
gtk_completion.c gtk_login.c gtk_throbber.c gtk_selection.c \
gtk_history.c gtk_window.c gtk_filetype.c gtk_download.c \
gtk_menu.c gtk_print.c gtk_save.c gtk_search.c gtk_tabs.c \
- gtk_theme.c gtk_toolbar.c sexy_icon_entry.c gtk_compat.c \
+ gtk_theme.c gtk_toolbar.c sexy_icon_entry.c gtk_compat.c \
+ gtk_cookies.c gtk_hotlist.c \
$(addprefix dialogs/,gtk_options.c gtk_about.c gtk_source.c)
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
# code in utils/container.ch is non-universal it seems
# S_WINDOWS are sources purely for the windows build
-S_WINDOWS := about.c bitmap.c download.c filetype.c findfile.c font.c \
- gui.c history.c hotlist.c localhistory.c login.c misc.c plot.c \
- prefs.c schedule.c thumbnail.c tree.c
+S_WINDOWS := about.c bitmap.c download.c filetype.c findfile.c font.c \
+ gui.c localhistory.c login.c misc.c plot.c prefs.c schedule.c \
+ thumbnail.c tree.c
S_WINDOWS := $(addprefix windows/,$(S_WINDOWS))
# S_BEOS are sources purely for the BeOS build
S_BEOS := beos_about.cpp beos_bitmap.cpp beos_fetch_rsrc.cpp \
- beos_filetype.cpp beos_font.cpp beos_gui.cpp beos_history.cpp \
- beos_login.cpp beos_options.cpp beos_plotters.cpp \
- beos_save_complete.cpp \
+ beos_filetype.cpp beos_font.cpp beos_gui.cpp beos_login.cpp \
+ beos_options.cpp beos_plotters.cpp beos_save_complete.cpp \
beos_scaffolding.cpp beos_search.cpp beos_schedule.cpp \
beos_thumbnail.cpp beos_treeview.cpp beos_throbber.cpp \
beos_window.cpp
@@ -102,9 +103,9 @@ S_AMIGA := $(addprefix amiga/,$(S_AMIGA))
# S_FRAMEBUFFER are sources purely for the framebuffer build
-S_FRAMEBUFFER := gui.c framebuffer.c tree.c history.c hotlist.c \
- save.c schedule.c thumbnail.c misc.c bitmap.c filetype.c \
- login.c findfile.c localhistory.c
+S_FRAMEBUFFER := gui.c framebuffer.c tree.c save.c schedule.c \
+ thumbnail.c misc.c bitmap.c filetype.c login.c findfile.c \
+ localhistory.c
S_FRAMEBUFFER_FBTK := fbtk.c event.c fill.c bitmap.c user.c window.c \
text.c scroll.c osk.c
diff --git a/amiga/cookies.c b/amiga/cookies.c
index cffa52337..76e2173f2 100755
--- a/amiga/cookies.c
+++ b/amiga/cookies.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,151 +16,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Cookies (implementation).
- */
-
-#include <string.h>
-#include "content/urldb.h"
-#include "desktop/cookies.h"
-#include "desktop/tree.h"
-#include "utils/messages.h"
-#include "utils/log.h"
-#include "amiga/cookies.h"
#include <proto/exec.h>
-#include <assert.h>
-#include "utils/utils.h"
-
-static bool cookies_init;
-
-struct node *ami_cookies_find(const char *url);
+#include "amiga/cookies.h"
+#include "desktop/cookies.h"
+#include "amiga/tree.h"
-/**
- * Initialise cookies tree
- */
void ami_cookies_initialise(void)
{
- if(cookies_tree) return;
-
- /* Create an empty tree */
- cookies_tree = AllocVec(sizeof(struct tree),MEMF_CLEAR | MEMF_PRIVATE);
- if (!cookies_tree) {
- warn_user("NoMemory", 0);
- return;
- }
- cookies_tree->root = tree_create_folder_node(NULL, "Root");
- if (!cookies_tree->root) {
- warn_user("NoMemory", 0);
- FreeVec(cookies_tree);
- cookies_tree = NULL;
- }
- cookies_tree->root->expanded = true;
- cookies_tree->movable = false;
- cookies_tree->no_drag = true;
-
- cookies_init = true;
- urldb_iterate_cookies(cookies_update);
- cookies_init = false;
- tree_initialise(cookies_tree);
-}
-
-/**
- * Perform cookie addition
- *
- * \param data Cookie data for a domain, or NULL
- * \return true (for urldb_iterate_entries)
- */
-bool cookies_update(const char *domain, const struct cookie_data *data)
-{
- struct node *parent;
- struct node *node = NULL;
- struct node *child;
- struct node *add;
- const struct cookie_data *cookie = NULL;
- bool expanded;
-
- assert(domain);
-
- /* check if we're a domain, and add get the first cookie */
- if (data)
- for (cookie = data; cookie->prev; cookie = cookie->prev);
-
- if (!cookies_init) {
- node = ami_cookies_find(domain);
- if (node) {
- /* mark as deleted so we don't remove the cookies */
- expanded = node->expanded;
- for (child = node->child; child; child = child->next)
- child->deleted = true;
- if (node->child)
- tree_delete_node(cookies_tree, node->child,
- true);
- /* deleting will have contracted our node */
- node->expanded = expanded;
- }
- if (!data) {
- if (!node)
- return true;
- tree_delete_node(cookies_tree, node, false);
- tree_handle_node_changed(cookies_tree,
- cookies_tree->root, true, false);
- return true;
- }
- }
-
- if (!node) {
- for (parent = cookies_tree->root->child; parent;
- parent = parent->next) {
- if (strcmp(domain, parent->data.text) == 0)
- break;
- }
- if (!parent) {
- node = tree_create_folder_node(cookies_tree->root,
- domain);
- } else {
- node = parent;
- }
- }
- if (!node)
- return true;
- node->editable = false;
+ cookies_window = ami_tree_create(cookies_get_tree_flags(), NULL);
- for (; cookie; cookie = cookie->next) {
- add = tree_create_cookie_node(node, cookie);
- if (add && !cookies_init)
- tree_handle_node_changed(cookies_tree, add,
- true, false);
- }
- if (!cookies_init) {
- tree_handle_node_changed(cookies_tree, node,
- true, false);
-/*
- tree_redraw_area(cookies_tree,
- node->box.x - NODE_INSTEP,
- 0, NODE_INSTEP, 16384);
-*/
- }
- return true;
-}
-
-/**
- * Find an entry in the cookie tree
- *
- * \param url The URL to find
- * \return Pointer to node, or NULL if not found
- */
-struct node *ami_cookies_find(const char *url)
-{
- struct node *node;
+ if(!cookies_window) return;
- for (node = cookies_tree->root->child; node; node = node->next) {
- if (!strcmp(url, node->data.text))
- return node;
- }
- return NULL;
+ cookies_initialise(ami_tree_get_tree(cookies_window));
}
void ami_cookies_free()
{
- FreeVec(cookies_tree);
+ cookies_cleanup();
+ ami_tree_destroy(cookies_window);
+ cookies_window = NULL;
}
diff --git a/amiga/cookies.h b/amiga/cookies.h
index 4d376434c..d6922750c 100755
--- a/amiga/cookies.h
+++ b/amiga/cookies.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -19,9 +19,10 @@
#ifndef AMIGA_COOKIES_H
#define AMIGA_COOKIES_H
#include "desktop/tree.h"
+#include "amiga/tree.h"
void ami_cookies_initialise(void);
void ami_cookies_free(void);
-struct tree *cookies_tree;
+struct treeview_window *cookies_window;
#endif
diff --git a/amiga/gui.c b/amiga/gui.c
index 6372a435a..759b4f932 100755
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -143,6 +143,8 @@ BOOL screen_closed = FALSE;
struct MsgPort *applibport = NULL;
ULONG applibsig = 0;
+const char tree_directory_icon_name[100];
+const char tree_content_icon_name[100];
extern colour scroll_widget_fg_colour;
extern colour scroll_widget_bg_colour;
extern colour scroll_widget_arrow_colour;
@@ -324,9 +326,6 @@ void ami_set_options(void)
if((!option_url_file) || (option_url_file[0] == '\0'))
option_url_file = (char *)strdup("PROGDIR:Resources/URLs");
- if((!option_recent_file) || (option_recent_file[0] == '\0'))
- option_recent_file = (char *)strdup("PROGDIR:Resources/Recent");
-
/*
if((!option_cookie_jar) || (option_cookie_jar[0] == '\0'))
option_cookie_jar = (char *)strdup("PROGDIR:Resources/CookieJar");
@@ -453,7 +452,6 @@ void gui_init(int argc, char** argv)
plot=amiplot;
- ami_init_menulabs();
if(option_context_menu) ami_context_menu_init();
schedule_list = NewObjList();
@@ -462,15 +460,6 @@ void gui_init(int argc, char** argv)
urldb_load(option_url_file);
urldb_load_cookies(option_cookie_file);
- if(lock = Lock(option_hotlist_file,SHARED_LOCK))
- {
- UnLock(lock);
- hotlist = options_load_tree(option_hotlist_file);
- }
-
- if(!hotlist) ami_hotlist_init(&hotlist);
- ami_global_history_initialise();
- ami_cookies_initialise();
save_complete_init();
ami_theme_init();
ami_init_mouse_pointers();
@@ -567,6 +556,18 @@ static void gui_init2(int argc, char** argv)
notalreadyrunning = ami_arexx_init();
+ /* Treeview init code ends up calling a font function which needs this */
+ browserglob.scale = 1.0;
+ glob = &browserglob;
+ /**/
+
+ ami_get_theme_filename(&tree_directory_icon_name,"theme_list_folder",true);
+ ami_get_theme_filename(&tree_content_icon_name,"theme_list_content",true);
+ ami_hotlist_initialise(option_hotlist_file);
+ ami_cookies_initialise();
+ ami_global_history_initialise();
+ sslcert_init();
+
search_web_provider_details(option_search_provider);
if(argc) // argc==0 is started from wb
@@ -1331,7 +1332,7 @@ void ami_handle_msg(void)
case 'h':
if((option_kiosk_mode == false) &&
(gwin->bw->browser_window_type == BROWSER_WINDOW_NORMAL))
- ami_open_tree(hotlist,AMI_TREE_HOTLIST);
+ ami_tree_open(hotlist_window, AMI_TREE_HOTLIST);
break;
/* The following aren't available from the menu at the moment */
@@ -2002,11 +2003,10 @@ void gui_quit(void)
urldb_save(option_url_file);
urldb_save_cookies(option_cookie_file);
- options_save_tree(hotlist,option_hotlist_file,messages_get("TreeHotlist"));
- void ami_global_history_save();
-
+ ami_hotlist_free(option_hotlist_file);
ami_cookies_free();
ami_global_history_free();
+ sslcert_cleanup();
hubbub_finalise(ns_realloc,NULL);
@@ -2033,7 +2033,10 @@ void gui_quit(void)
FreeVec(nsscreentitle);
if(option_context_menu) ami_context_menu_free();
- ami_free_menulabs();
+
+/* fixme: need newmenu struct propd to this function - should this be freed here?
+ ami_free_menulabs(menu);
+*/
ami_mouse_pointers_free();
ami_clipboard_free();
@@ -2187,7 +2190,6 @@ void ami_toggletabbar(struct gui_window_2 *gwin, bool show)
struct gui_window *gui_create_browser_window(struct browser_window *bw,
struct browser_window *clone, bool new_tab)
{
- struct NewMenu *menu;
struct gui_window *gwin = NULL;
bool closegadg=TRUE;
struct Node *node;
@@ -2357,7 +2359,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
{
ULONG addtabclosegadget = TAG_IGNORE;
- menu = ami_create_menu(bw->browser_window_type);
+ ami_create_menu(bw->browser_window_type, gwin->shared);
NewList(&gwin->shared->tab_list);
gwin->tab_node = AllocClickTabNode(TNA_Text,messages_get("NetSurf"),
@@ -2389,28 +2391,28 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
gwin->shared->helphints[GID_ADDTAB] =
remove_escape_chars(messages_get("HelpAddTab"), true);
- ami_get_theme_filename(nav_west,"theme_nav_west");
- ami_get_theme_filename(nav_west_s,"theme_nav_west_s");
- ami_get_theme_filename(nav_west_g,"theme_nav_west_g");
- ami_get_theme_filename(nav_east,"theme_nav_east");
- ami_get_theme_filename(nav_east_s,"theme_nav_east_s");
- ami_get_theme_filename(nav_east_g,"theme_nav_east_g");
- ami_get_theme_filename(stop,"theme_stop");
- ami_get_theme_filename(stop_s,"theme_stop_s");
- ami_get_theme_filename(stop_g,"theme_stop_g");
- ami_get_theme_filename(reload,"theme_reload");
- ami_get_theme_filename(reload_s,"theme_reload_s");
- ami_get_theme_filename(reload_g,"theme_reload_g");
- ami_get_theme_filename(home,"theme_home");
- ami_get_theme_filename(home_s,"theme_home_s");
- ami_get_theme_filename(home_g,"theme_home_g");
- ami_get_theme_filename(closetab,"theme_closetab");
- ami_get_theme_filename(closetab_s,"theme_closetab_s");
- ami_get_theme_filename(closetab_g,"theme_closetab_g");
- ami_get_theme_filename(addtab,"theme_addtab");
- ami_get_theme_filename(addtab_s,"theme_addtab_s");
- ami_get_theme_filename(addtab_g,"theme_addtab_g");
- ami_get_theme_filename(tabthrobber,"theme_tab_loading");
+ ami_get_theme_filename(nav_west,"theme_nav_west",false);
+ ami_get_theme_filename(nav_west_s,"theme_nav_west_s",false);
+ ami_get_theme_filename(nav_west_g,"theme_nav_west_g",false);
+ ami_get_theme_filename(nav_east,"theme_nav_east",false);
+ ami_get_theme_filename(nav_east_s,"theme_nav_east_s",false);
+ ami_get_theme_filename(nav_east_g,"theme_nav_east_g",false);
+ ami_get_theme_filename(stop,"theme_stop",false);
+ ami_get_theme_filename(stop_s,"theme_stop_s",false);
+ ami_get_theme_filename(stop_g,"theme_stop_g",false);
+ ami_get_theme_filename(reload,"theme_reload",false);
+ ami_get_theme_filename(reload_s,"theme_reload_s",false);
+ ami_get_theme_filename(reload_g,"theme_reload_g",false);
+ ami_get_theme_filename(home,"theme_home",false);
+ ami_get_theme_filename(home_s,"theme_home_s",false);
+ ami_get_theme_filename(home_g,"theme_home_g",false);
+ ami_get_theme_filename(closetab,"theme_closetab",false);
+ ami_get_theme_filename(closetab_s,"theme_closetab_s",false);
+ ami_get_theme_filename(closetab_g,"theme_closetab_g",false);
+ ami_get_theme_filename(addtab,"theme_addtab",false);
+ ami_get_theme_filename(addtab_s,"theme_addtab_s",false);
+ ami_get_theme_filename(addtab_g,"theme_addtab_g",false);
+ ami_get_theme_filename(tabthrobber,"theme_tab_loading",false);
gwin->shared->objects[GID_ADDTAB_BM] = BitMapObject,
BITMAP_SourceFile, addtab,
@@ -2482,7 +2484,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
IDCMP_ACTIVEWINDOW | IDCMP_INTUITICKS |
IDCMP_EXTENDEDMOUSE | IDCMP_GADGETDOWN,
- WINDOW_NewMenu,menu,
+ WINDOW_NewMenu, gwin->shared->menu,
WINDOW_VertProp,1,
WINDOW_IDCMPHook,&gwin->shared->scrollerhook,
WINDOW_IDCMPHookBits,IDCMP_IDCMPUPDATE |
@@ -2934,6 +2936,7 @@ void gui_window_destroy(struct gui_window *g)
DisposeObject(g->shared->objects[OID_MAIN]);
+ ami_free_menulabs(g->shared);
free(g->shared->wintitle);
ami_utf8_free(g->shared->status);
FreeVec(g->shared->svbuffer);
diff --git a/amiga/gui.h b/amiga/gui.h
index dce118b89..70c1d2db3 100755
--- a/amiga/gui.h
+++ b/amiga/gui.h
@@ -23,8 +23,10 @@
#include <intuition/classusr.h>
#include "desktop/browser.h"
#include <dos/dos.h>
+#include <devices/inputevent.h>
#include "desktop/gui.h"
#include "amiga/plotters.h"
+#include "amiga/menu.h"
enum
{
@@ -56,11 +58,7 @@ enum
GID_PASS,
GID_LOGIN,
GID_CANCEL,
- GID_TREEBROWSER,
GID_OPEN,
- GID_LEFT,
- GID_UP,
- GID_DOWN,
GID_NEWF,
GID_NEWB,
GID_DEL,
@@ -98,6 +96,11 @@ struct gui_window_2 {
ULONG oldv;
bool redraw_scroll;
bool new_content;
+ char *menulab[AMI_MENU_AREXX_MAX + 1];
+ char menukey[AMI_MENU_AREXX_MAX + 1];
+ UBYTE *menutype;
+ struct NewMenu *menu;
+ ULONG hotlist_items;
char *svbuffer;
char *status;
char *wintitle;
@@ -127,6 +130,7 @@ void ami_close_all_tabs(struct gui_window_2 *gwin);
void ami_quit_netsurf(void);
void ami_do_redraw(struct gui_window_2 *g);
STRPTR ami_locale_langs(void);
+int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie);
struct box *ami_text_box_at_point(struct gui_window_2 *gwin, ULONG *x, ULONG *y);
struct gui_window_2 *ami_window_at_pointer(void);
diff --git a/amiga/history.c b/amiga/history.c
index 5e685b76a..19ba9aff9 100755
--- a/amiga/history.c
+++ b/amiga/history.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2005 Richard Wilson <info@tinct.net>
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,362 +16,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "desktop/browser.h"
#include "amiga/history.h"
#include "amiga/tree.h"
-#include "content/urldb.h"
-#include <proto/dos.h>
-#include "amiga/options.h"
+#include "desktop/history_global_core.h"
#include <proto/exec.h>
-#include <assert.h>
-#include <utils/log.h>
-
-#define MAXIMUM_URL_LENGTH 1024
-#define MAXIMUM_BASE_NODES 16
-
-static struct node *global_history_base_node[MAXIMUM_BASE_NODES];
-static int global_history_base_node_time[MAXIMUM_BASE_NODES];
-static int global_history_base_node_count = 0;
-
-static char *global_history_recent_url[GLOBAL_HISTORY_RECENT_URLS];
-static int global_history_recent_count = 0;
-
-static bool global_history_init;
-
-static struct node *ami_global_history_find(const char *url);
-static bool global_history_add_internal(const char *url,
- const struct url_data *data);
-void ami_global_history_initialise_node(const char *title,
- time_t base, int days_back);
-void ami_global_history_initialise_nodes(void);
+#include "amiga/tree.h"
void ami_global_history_initialise(void)
{
- char s[MAXIMUM_URL_LENGTH];
- BPTR *fp;
-
-// if(global_history_tree) return;
-
- /* Create an empty tree */
- global_history_tree = AllocVec(sizeof(struct tree), MEMF_CLEAR | MEMF_PRIVATE);
- if (!global_history_tree) {
- warn_user("NoMemory", 0);
- return;
- }
- global_history_tree->root = tree_create_folder_node(NULL, "Root");
- if (!global_history_tree->root) {
- warn_user("NoMemory", 0);
- FreeVec(global_history_tree);
- global_history_tree = NULL;
- }
- global_history_tree->root->expanded = true;
- ami_global_history_initialise_nodes();
- global_history_tree->movable = false;
-
- /* load recent URLs */
- fp = FOpen(option_recent_file, MODE_OLDFILE,0);
- if (!fp)
- LOG(("Failed to open file '%s' for reading",
- option_recent_file));
- else {
- while (FGets(fp,s, MAXIMUM_URL_LENGTH)) {
- if (s[strlen(s) - 1] == '\n')
- s[strlen(s) - 1] = '\0';
- global_history_add_recent(s);
- }
- FClose(fp);
- }
-
- global_history_init = true;
- urldb_iterate_entries(global_history_add_internal);
- global_history_init = false;
- tree_initialise(global_history_tree);
-
-}
-
-void global_history_add(const char *url)
-{
- const struct url_data *data;
-
- data = urldb_get_url_data(url);
- if (!data)
- return;
-
- global_history_add_internal(url, data);
-}
-
-/**
- * Internal routine to actually perform global history addition
- *
- * \param url The URL to add
- * \param data URL data associated with URL
- * \return true (for urldb_iterate_entries)
- */
-bool global_history_add_internal(const char *url,
- const struct url_data *data)
-{
- int i, j;
- struct node *parent = NULL;
- struct node *link;
- struct node *node;
- bool before = false;
- int visit_date;
-
- assert(url && data);
-
- visit_date = data->last_visit;
-
- /* find parent node */
- for (i = 0; i < global_history_base_node_count; i++) {
- if (global_history_base_node_time[i] <= visit_date) {
- parent = global_history_base_node[i];
- break;
- }
- }
-
- /* the entry is too old to care about */
- if (!parent)
- return true;
-
- if (parent->deleted) {
- /* parent was deleted, so find place to insert it */
- link = global_history_tree->root;
-
- for (j = global_history_base_node_count - 1; j >= 0; j--) {
- if (!global_history_base_node[j]->deleted &&
- global_history_base_node_time[j] >
- global_history_base_node_time[i]) {
- link = global_history_base_node[j];
- before = true;
- break;
- }
- }
+ global_history_window = ami_tree_create(history_global_get_tree_flags(), NULL);
- tree_set_node_selected(global_history_tree,
- parent, false);
- tree_set_node_expanded(global_history_tree,
- parent, false);
- tree_link_node(link, parent, before);
-/*
- if (!global_history_init) {
- tree_recalculate_node(global_history_tree, parent, true);
- tree_recalculate_node_positions(global_history_tree,
- global_history_tree->root);
- tree_redraw_area(global_history_tree,
- 0, 0, 16384, 16384);
- }
-*/
- }
-
- /* find any previous occurance */
+ if(!global_history_window) return;
- if (!global_history_init) {
- node = ami_global_history_find(url);
- if (node) {
- /* \todo: calculate old/new positions and redraw
- * only the relevant portion */
-/*
- tree_redraw_area(global_history_tree,
- 0, 0, 16384, 16384);
-*/
- tree_update_URL_node(node, url, data);
- tree_delink_node(node);
- tree_link_node(parent, node, false);
- tree_handle_node_changed(global_history_tree,
- node, false, true);
- return true;
- }
- }
-
- /* Add the node at the bottom */
- node = tree_create_URL_node_shared(parent, url, data);
- if ((!global_history_init) && (node)) {
-/*
- tree_redraw_area(global_history_tree,
- node->box.x - NODE_INSTEP,
- 0, NODE_INSTEP, 16384);
-*/
- tree_handle_node_changed(global_history_tree, node,
- true, false);
- }
-
- return true;
-}
-
-/**
- * Find an entry in the global history
- *
- * \param url The URL to find
- * \return Pointer to node, or NULL if not found
- */
-struct node *ami_global_history_find(const char *url)
-{
- int i;
- struct node *node;
- struct node_element *element;
-
- for (i = 0; i < global_history_base_node_count; i++) {
- if (!global_history_base_node[i]->deleted) {
- for (node = global_history_base_node[i]->child;
- node; node = node->next) {
- element = tree_find_element(node,
- TREE_ELEMENT_URL);
- if ((element) && !strcmp(url, element->text))
- return node;
- }
- }
- }
- return NULL;
-}
-
-/**
- * Saves the global history's recent URL data.
- */
-void ami_global_history_save(void)
-{
- BPTR *fp;
- int i;
-
- /* save recent URLs */
- fp = fopen(option_recent_file, "w");
- if (!fp)
- LOG(("Failed to open file '%s' for writing",
- option_recent_file));
- else {
- for (i = global_history_recent_count - 1; i >= 0; i--)
- if (strlen(global_history_recent_url[i]) <
- MAXIMUM_URL_LENGTH)
- fprintf(fp, "%s\n",
- global_history_recent_url[i]);
- fclose(fp);
- }
-}
-
-void global_history_add_recent(const char *url)
-{
- int i;
- int j = -1;
- char *current;
-
- /* try to find a string already there */
- for (i = 0; i < global_history_recent_count; i++)
- if (global_history_recent_url[i] &&
- !strcmp(global_history_recent_url[i], url))
- j = i;
-
- /* already at head of list */
- if (j == 0)
- return;
-
- if (j < 0) {
- /* add to head of list */
- free(global_history_recent_url[
- GLOBAL_HISTORY_RECENT_URLS - 1]);
- memmove(&global_history_recent_url[1],
- &global_history_recent_url[0],
- (GLOBAL_HISTORY_RECENT_URLS - 1) *
- sizeof(char *));
- global_history_recent_url[0] = strdup(url);
- global_history_recent_count++;
- if (global_history_recent_count > GLOBAL_HISTORY_RECENT_URLS)
- global_history_recent_count =
- GLOBAL_HISTORY_RECENT_URLS;
-/*
- if (global_history_recent_count == 1)
- ro_gui_window_prepare_navigate_all();
-*/
- } else {
- /* move to head of list */
- current = global_history_recent_url[j];
- for (i = j; i > 0; i--)
- global_history_recent_url[i] =
- global_history_recent_url[i - 1];
- global_history_recent_url[0] = current;
- }
-}
-
-/**
- * Gets details of the currently used URL list.
- *
- * \param count set to the current number of entries in the URL array on exit
- * \return the current URL array
- */
-char **global_history_get_recent(int *count)
-{
- *count = global_history_recent_count;
- return global_history_recent_url;
+ history_global_initialise(ami_tree_get_tree(global_history_window));
}
void ami_global_history_free()
{
- FreeVec(global_history_tree);
-}
-
-/**
- * Initialises the base nodes
- */
-void ami_global_history_initialise_nodes(void)
-{
- struct tm *full_time;
- time_t t;
- int weekday;
- int i;
-
- /* get the current time */
- t = time(NULL);
- if (t == -1)
- return;
-
- /* get the time at the start of today */
- full_time = localtime(&t);
- weekday = full_time->tm_wday;
- full_time->tm_sec = 0;
- full_time->tm_min = 0;
- full_time->tm_hour = 0;
- t = mktime(full_time);
- if (t == -1)
- return;
-
- ami_global_history_initialise_node((char *)messages_get("DateToday"), t, 0);
- if (weekday > 0)
- ami_global_history_initialise_node(
- (char *)messages_get("DateYesterday"), t, -1);
- for (i = 2; i <= weekday; i++)
- ami_global_history_initialise_node(NULL, t, -i);
- ami_global_history_initialise_node((char *)messages_get("Date1Week"),
- t, -weekday - 7);
- ami_global_history_initialise_node((char *)messages_get("Date2Week"),
- t, -weekday - 14);
- ami_global_history_initialise_node((char *)messages_get("Date3Week"),
- t, -weekday - 21);
+ history_global_cleanup();
+ ami_tree_destroy(global_history_window);
+ global_history_window = NULL;
}
-
-/**
- * Create and initialise a node
- */
-void ami_global_history_initialise_node(const char *title,
- time_t base, int days_back)
-{
- struct tm *full_time;
- char buffer[64];
- struct node *node;
-
- base += days_back * 60 * 60 * 24;
- if (!title) {
- full_time = localtime(&base);
- strftime((char *)&buffer, (size_t)64, "%A", full_time);
- node = tree_create_folder_node(NULL, buffer);
- } else
- node = tree_create_folder_node(NULL, title);
-
- if (!node)
- return;
-
- node->retain_in_memory = true;
- node->deleted = true;
- node->editable = false;
- global_history_base_node[global_history_base_node_count] = node;
- global_history_base_node_time[global_history_base_node_count] = base;
- global_history_base_node_count++;
-}
-
diff --git a/amiga/history.h b/amiga/history.h
index c9f8254dc..b69d46c6a 100755
--- a/amiga/history.h
+++ b/amiga/history.h
@@ -19,11 +19,12 @@
#ifndef AMIGA_HISTORY_H
#define AMIGA_HISTORY_H
#include "desktop/tree.h"
+#include "desktop/history_global_core.h"
#define GLOBAL_HISTORY_RECENT_URLS 16
void ami_global_history_initialise(void);
void ami_global_history_free(void);
-struct tree *global_history_tree;
+struct treeview_window *global_history_window;
#endif
diff --git a/amiga/hotlist.c b/amiga/hotlist.c
index 71c5ddbba..f90f3645e 100755
--- a/amiga/hotlist.c
+++ b/amiga/hotlist.c
@@ -1,5 +1,4 @@
/*
- * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
* Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
@@ -17,137 +16,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "desktop/browser.h"
-#include "desktop/tree.h"
#include <proto/exec.h>
-#include "content/urldb.h"
#include "amiga/hotlist.h"
+#include "desktop/hotlist.h"
#include "amiga/tree.h"
-void ami_gui_hotlist_visited(hlcache_handle *content, struct tree *tree,
- struct node *node);
-
-static const struct {
- const char *url;
- const char *msg_key;
-} default_entries[] = {
- { "http://www.netsurf-browser.org/", "HotlistHomepage" },
- { "http://www.netsurf-browser.org/downloads/amiga/", "HotlistTestBuild" },
- { "http://www.netsurf-browser.org/documentation/", "HotlistDocumentation" },
- { "http://sourceforge.net/tracker/?atid=464312&group_id=51719",
- "HotlistBugTracker" },
- { "http://sourceforge.net/tracker/?atid=464315&group_id=51719",
- "HotlistFeatureRequest" },
- { "http://www.unsatisfactorysoftware.co.uk/",
- "Unsatisfactory Software" }
-};
-#define ENTRIES_COUNT (sizeof(default_entries) / sizeof(default_entries[0]))
-
-void hotlist_visited(hlcache_handle *c)
+void ami_hotlist_initialise(const char *hotlist_file)
{
- if ((!c) || (!content_get_url(c)) || (!hotlist))
- return;
- ami_gui_hotlist_visited(c, hotlist, hotlist->root);
-}
+ hotlist_window = ami_tree_create(hotlist_get_tree_flags(), NULL);
-/**
- * Informs the hotlist that some content has been visited
- *
- * \param content the content visited
- * \param tree the tree to find the URL data from
- * \param node the node to update siblings and children of
- */
-void ami_gui_hotlist_visited(hlcache_handle *content, struct tree *tree,
- struct node *node)
-{
- struct node_element *element;
+ if(!hotlist_window) return;
- for (; node; node = node->next) {
- if (!node->folder) {
- element = tree_find_element(node, TREE_ELEMENT_URL);
- if ((element) && (!strcmp(element->text,
- content_get_url(content)))) {
- tree_update_URL_node(node, content_get_url(content), NULL);
- tree_handle_node_changed(tree, node, true,
- false);
- }
- }
- if (node->child)
- ami_gui_hotlist_visited(content, tree, node->child);
- }
+ hotlist_initialise(ami_tree_get_tree(hotlist_window),
+ hotlist_file);
}
-void ami_hotlist_init(struct tree **hotlist)
+void ami_hotlist_free(const char *hotlist_file)
{
- struct tree *hotlist_tree;
- struct node *node;
- int i;
- const struct url_data *data;
-
- *hotlist = AllocVec(sizeof(struct tree),MEMF_PRIVATE | MEMF_CLEAR);
- hotlist_tree = *hotlist;
-
- if (!hotlist_tree) {
- warn_user("NoMemory", 0);
- return;
- }
-
- hotlist_tree->root = tree_create_folder_node(NULL, "Root");
- if (!hotlist_tree->root) {
- warn_user("NoMemory", 0);
- FreeVec(hotlist_tree);
- hotlist_tree = NULL;
- }
-
- hotlist_tree->root->expanded = true;
-
- node = tree_create_folder_node(hotlist_tree->root, "Menu");
- if (!node)
- node = hotlist_tree->root;
-
- node = tree_create_folder_node(node, "NetSurf");
- if (!node)
- node = hotlist_tree->root;
-
- for (i = 0; i != ENTRIES_COUNT; i++) {
- data = urldb_get_url_data(default_entries[i].url);
- if (!data) {
- urldb_add_url(default_entries[i].url);
- urldb_set_url_persistence(
- default_entries[i].url,
- true);
- data = urldb_get_url_data(
- default_entries[i].url);
- }
- if (data) {
- tree_create_URL_node(node,
- default_entries[i].url, data,
- messages_get(default_entries[i].msg_key));
- }
- }
-
- tree_initialise(hotlist_tree);
-}
-
-void ami_hotlist_add(struct node *node, struct hlcache_handle *c)
-{
- const struct url_data *data;
-
- data = urldb_get_url_data(content_get_url(c));
- if (!data)
- {
- urldb_add_url(content_get_url(c));
- urldb_set_url_persistence(content_get_url(c),true);
- data = urldb_get_url_data(content_get_url(c));
- }
-
- if (data)
- {
- tree_create_URL_node(node,content_get_url(c),data,content_get_title(c));
- }
-
- tree_handle_node_changed(hotlist,node,false,true);
-
- if(hotlist->handle)
- ami_recreate_listbrowser((struct treeview_window *)hotlist->handle);
+ hotlist_cleanup(hotlist_file);
+ ami_tree_destroy(hotlist_window);
+ hotlist_window = NULL;
}
diff --git a/amiga/hotlist.h b/amiga/hotlist.h
index eed5b0eed..ee258af7b 100755
--- a/amiga/hotlist.h
+++ b/amiga/hotlist.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -19,9 +19,10 @@
#ifndef AMIGA_HOTLIST_H
#define AMIGA_HOTLIST_H
#include "desktop/tree.h"
+#include "amiga/tree.h"
-void ami_hotlist_init(struct tree **hotlist);
-void ami_hotlist_add(struct node *node, struct hlcache_handle *c);
+void ami_hotlist_initialise(const char *hotlist_file);
+void ami_hotlist_free(const char *hotlist_file);
-struct tree *hotlist;
+struct treeview_window *hotlist_window;
#endif
diff --git a/amiga/menu.c b/amiga/menu.c
index 9f5aab757..081b1e568 100755
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -41,6 +41,11 @@
#include "amiga/iff_dr2d.h"
#include "amiga/clipboard.h"
#include "amiga/gui_options.h"
+#include "desktop/tree_url_node.h"
+#include <classes/window.h>
+#include <proto/intuition.h>
+#include "desktop/hotlist.h"
+#include <proto/gadtools.h>
#include "amiga/print.h"
#include "amiga/download.h"
@@ -61,226 +66,221 @@ const char * const versvn;
const char * const verdate;
static struct Hook aslhookfunc;
-void ami_menu_scan(struct tree *tree,struct NewMenu *menu);
-void ami_menu_scan_2(struct tree *tree,struct node *root,WORD *gen,ULONG *item,struct NewMenu *menu);
-void ami_menu_arexx_scan(struct NewMenu *menu);
+ULONG ami_menu_scan(struct tree *tree, bool count, struct gui_window_2 *gwin);
+void ami_menu_scan_2(struct tree *tree, struct node *root, WORD *gen,
+ ULONG *item, bool count, struct gui_window_2 *gwin);
+void ami_menu_arexx_scan(struct gui_window_2 *gwin);
static const ULONG ami_asl_mime_hook(struct Hook *mh,struct FileRequester *fr,struct AnchorPathOld *ap);
-void ami_free_menulabs(void)
+void ami_free_menulabs(struct gui_window_2 *gwin)
{
int i;
- for(i=0;i<=AMI_MENU_MAX;i++)
+ for(i=0;i<=AMI_MENU_AREXX_MAX;i++)
{
- if(menulab[i] && (menulab[i] != NM_BARLABEL)) ami_utf8_free(menulab[i]);
+ if(gwin->menulab[i] && (gwin->menulab[i] != NM_BARLABEL))
+ ami_utf8_free(gwin->menulab[i]);
+
+ gwin->menulab[i] = NULL;
+ gwin->menukey[i] = 0;
}
- for(i=AMI_MENU_MAX+1;i<=AMI_MENU_AREXX_MAX;i++)
+ FreeVec(gwin->menutype);
+ FreeVec(gwin->menu);
+
+ gwin->menutype = NULL;
+ gwin->menu = NULL;
+}
+
+void ami_init_menulabs(struct gui_window_2 *gwin)
+{
+ int i;
+
+ gwin->menutype = AllocVec(AMI_MENU_AREXX_MAX + 1, MEMF_PRIVATE | MEMF_CLEAR);
+
+ for(i=0;i <= AMI_MENU_AREXX_MAX;i++)
{
- if(menulab[i] && (menulab[i] != NM_BARLABEL)) free(menulab[i]);
+ gwin->menutype[i] = NM_IGNORE;
+ gwin->menulab[i] = NULL;
}
+
+ gwin->menutype[0] = NM_TITLE;
+ gwin->menulab[0] = ami_utf8_easy((char *)messages_get("Project"));
+ gwin->menutype[1] = NM_ITEM;
+ gwin->menulab[1] = ami_utf8_easy((char *)messages_get("NewWindowNS"));
+ gwin->menukey[1] = 'N';
+ gwin->menutype[2] = NM_ITEM;
+ gwin->menulab[2] = ami_utf8_easy((char *)messages_get("NewTab"));
+ gwin->menukey[1] = 'T';
+ gwin->menutype[3] = NM_ITEM;
+ gwin->menulab[3] = NM_BARLABEL;
+ gwin->menutype[4] = NM_ITEM;
+ gwin->menulab[4] = ami_utf8_easy((char *)messages_get("OpenFile"));
+ gwin->menukey[4] = 'O';
+ gwin->menutype[5] = NM_ITEM;
+ gwin->menulab[5] = ami_utf8_easy((char *)messages_get("SaveAsNS"));
+ gwin->menukey[5] = 'S';
+ gwin->menutype[6] = NM_SUB;
+ gwin->menulab[6] = ami_utf8_easy((char *)messages_get("Source"));
+ gwin->menutype[7] = NM_SUB;
+ gwin->menulab[7] = ami_utf8_easy((char *)messages_get("TextNS"));
+ gwin->menutype[8] = NM_SUB;
+ gwin->menulab[8] = ami_utf8_easy((char *)messages_get("SaveCompNS"));
+ gwin->menutype[9] = NM_SUB;
+ gwin->menulab[9] = ami_utf8_easy((char *)messages_get("PDFNS"));
+ gwin->menutype[10] = NM_SUB;
+ gwin->menulab[10] = ami_utf8_easy((char *)messages_get("IFF"));
+ gwin->menutype[11] = NM_ITEM;
+ gwin->menulab[11] = NM_BARLABEL;
+ gwin->menutype[12] = NM_ITEM;
+ gwin->menulab[12] = ami_utf8_easy((char *)messages_get("CloseTab"));
+ gwin->menukey[12] = 'K';
+ gwin->menutype[13] = NM_ITEM;
+ gwin->menulab[13] = ami_utf8_easy((char *)messages_get("CloseWindow"));
+ gwin->menutype[14] = NM_ITEM;
+ gwin->menulab[14] = NM_BARLABEL;
+ gwin->menutype[15] = NM_ITEM;
+ gwin->menulab[15] = ami_utf8_easy((char *)messages_get("PrintNS"));
+ gwin->menukey[15] = 'P';
+ gwin->menutype[16] = NM_ITEM;
+ gwin->menulab[16] = NM_BARLABEL;
+ gwin->menutype[17] = NM_ITEM;
+ gwin->menulab[17] = ami_utf8_easy((char *)messages_get("About"));
+ gwin->menukey[17] = '?';
+ gwin->menutype[18] = NM_ITEM;
+ gwin->menulab[18] = ami_utf8_easy((char *)messages_get("Quit"));
+ gwin->menukey[18] = 'Q';
+ gwin->menutype[19] = NM_TITLE;
+ gwin->menulab[19] = ami_utf8_easy((char *)messages_get("Edit"));
+ gwin->menutype[20] = NM_ITEM;
+ gwin->menulab[20] = ami_utf8_easy((char *)messages_get("CutNS"));
+ gwin->menukey[20] = 'X';
+ gwin->menutype[21] = NM_ITEM;
+ gwin->menulab[21] = ami_utf8_easy((char *)messages_get("CopyNS"));
+ gwin->menukey[21] = 'C';
+ gwin->menutype[22] = NM_ITEM;
+ gwin->menulab[22] = ami_utf8_easy((char *)messages_get("PasteNS"));
+ gwin->menukey[22] = 'V';
+ gwin->menutype[23] = NM_ITEM;
+ gwin->menulab[23] = NM_BARLABEL;
+ gwin->menutype[24] = NM_ITEM;
+ gwin->menulab[24] = ami_utf8_easy((char *)messages_get("SelectAllNS"));
+ gwin->menukey[24] = 'A';
+ gwin->menutype[25] = NM_ITEM;
+ gwin->menulab[25] = ami_utf8_easy((char *)messages_get("ClearNS"));
+ gwin->menukey[25] = 'Z';
+ gwin->menutype[26] = NM_TITLE;
+ gwin->menulab[26] = ami_utf8_easy((char *)messages_get("Browser"));
+ gwin->menutype[27] = NM_ITEM;
+ gwin->menulab[27] = ami_utf8_easy((char *)messages_get("FindTextNS"));
+ gwin->menukey[27] = 'F';
+ gwin->menutype[28] = NM_ITEM;
+ gwin->menulab[28] = NM_BARLABEL;
+ gwin->menutype[29] = NM_ITEM;
+ gwin->menulab[29] = ami_utf8_easy((char *)messages_get("HistLocalNS"));
+ gwin->menutype[30] = NM_ITEM;
+ gwin->menulab[30] = ami_utf8_easy((char *)messages_get("HistGlobalNS"));
+ gwin->menutype[31] = NM_ITEM;
+ gwin->menulab[31] = NM_BARLABEL;
+ gwin->menutype[32] = NM_ITEM;
+ gwin->menulab[32] = ami_utf8_easy((char *)messages_get("ShowCookies"));
+ gwin->menutype[33] = NM_ITEM;
+ gwin->menulab[33] = NM_BARLABEL;
+ gwin->menutype[34] = NM_ITEM;
+ gwin->menulab[34] = ami_utf8_easy((char *)messages_get("ScaleNS"));
+ gwin->menutype[35] = NM_SUB;
+ gwin->menulab[35] = ami_utf8_easy((char *)messages_get("ScaleDec"));
+ gwin->menukey[35] = '-';
+ gwin->menutype[36] = NM_SUB;
+ gwin->menulab[36] = ami_utf8_easy((char *)messages_get("ScaleNorm"));
+ gwin->menukey[36] = '=';
+ gwin->menutype[37] = NM_SUB;
+ gwin->menulab[37] = ami_utf8_easy((char *)messages_get("ScaleInc"));
+ gwin->menukey[37] = '+';
+ gwin->menutype[38] = NM_ITEM;
+ gwin->menulab[38] = ami_utf8_easy((char *)messages_get("Redraw"));
+ gwin->menutype[39] = NM_TITLE;
+ gwin->menulab[39] = ami_utf8_easy((char *)messages_get("Hotlist"));
+ gwin->menukey[39] = 'H';
+ gwin->menutype[40] = NM_ITEM;
+ gwin->menulab[40] = ami_utf8_easy((char *)messages_get("HotlistAdd"));
+ gwin->menutype[41] = NM_ITEM;
+ gwin->menulab[41] = ami_utf8_easy((char *)messages_get("HotlistShowNS"));
+ gwin->menutype[42] = NM_ITEM;
+ gwin->menulab[42] = NM_BARLABEL;
+
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 1] = NM_TITLE;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 1] = ami_utf8_easy((char *)messages_get("Settings"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 2] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 2] = ami_utf8_easy((char *)messages_get("SettingsEdit"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 3] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 3] = NM_BARLABEL;
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 4] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 4] = ami_utf8_easy((char *)messages_get("SnapshotWindow"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 5] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 5] = ami_utf8_easy((char *)messages_get("SettingsSave"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 6] = NM_TITLE;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 6] = ami_utf8_easy((char *)messages_get("ARexx"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 7] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 7] = ami_utf8_easy((char *)messages_get("ARexxExecute"));
+ gwin->menutype[AMI_MENU_HOTLIST_MAX + 8] = NM_ITEM;
+ gwin->menulab[AMI_MENU_HOTLIST_MAX + 8] = NM_BARLABEL;
+
+ gwin->menutype[AMI_MENU_AREXX_MAX] = NM_END;
}
-void ami_init_menulabs(void)
+void ami_menu_refresh(struct gui_window_2 *gwin)
{
- menulab[0] = ami_utf8_easy((char *)messages_get("Project"));
- menulab[1] = ami_utf8_easy((char *)messages_get("NewWindowNS"));
- menulab[2] = ami_utf8_easy((char *)messages_get("NewTab"));
- menulab[3] = NM_BARLABEL;
- menulab[4] = ami_utf8_easy((char *)messages_get("OpenFile"));
- menulab[5] = ami_utf8_easy((char *)messages_get("SaveAsNS"));
- menulab[6] = ami_utf8_easy((char *)messages_get("Source"));
- menulab[7] = ami_utf8_easy((char *)messages_get("TextNS"));
- menulab[8] = ami_utf8_easy((char *)messages_get("SaveCompNS"));
- menulab[9] = ami_utf8_easy((char *)messages_get("PDFNS"));
- menulab[10] = ami_utf8_easy((char *)messages_get("IFF"));
- menulab[11] = NM_BARLABEL;
- menulab[12] = ami_utf8_easy((char *)messages_get("CloseTab"));
- menulab[13] = ami_utf8_easy((char *)messages_get("CloseWindow"));
- menulab[14] = NM_BARLABEL;
- menulab[15] = ami_utf8_easy((char *)messages_get("PrintNS"));
- menulab[16] = NM_BARLABEL;
- menulab[17] = ami_utf8_easy((char *)messages_get("About"));
- menulab[18] = ami_utf8_easy((char *)messages_get("Quit"));
- menulab[19] = ami_utf8_easy((char *)messages_get("Edit"));
- menulab[20] = ami_utf8_easy((char *)messages_get("CutNS"));
- menulab[21] = ami_utf8_easy((char *)messages_get("CopyNS"));
- menulab[22] = ami_utf8_easy((char *)messages_get("PasteNS"));
- menulab[23] = NM_BARLABEL;
- menulab[24] = ami_utf8_easy((char *)messages_get("SelectAllNS"));
- menulab[25] = ami_utf8_easy((char *)messages_get("ClearNS"));
- menulab[26] = ami_utf8_easy((char *)messages_get("Browser"));
- menulab[27] = ami_utf8_easy((char *)messages_get("FindTextNS"));
- menulab[28] = NM_BARLABEL;
- menulab[29] = ami_utf8_easy((char *)messages_get("HistLocalNS"));
- menulab[30] = ami_utf8_easy((char *)messages_get("HistGlobalNS"));
- menulab[31] = NM_BARLABEL;
- menulab[32] = ami_utf8_easy((char *)messages_get("ShowCookies"));
- menulab[33] = NM_BARLABEL;
- menulab[34] = ami_utf8_easy((char *)messages_get("ScaleNS"));
- menulab[35] = ami_utf8_easy((char *)messages_get("ScaleDec"));
- menulab[36] = ami_utf8_easy((char *)messages_get("ScaleNorm"));
- menulab[37] = ami_utf8_easy((char *)messages_get("ScaleInc"));
- menulab[38] = ami_utf8_easy((char *)messages_get("Redraw"));
- menulab[39] = ami_utf8_easy((char *)messages_get("Hotlist"));
- menulab[40] = ami_utf8_easy((char *)messages_get("HotlistAdd"));
- menulab[41] = ami_utf8_easy((char *)messages_get("HotlistShowNS"));
- menulab[42] = NM_BARLABEL;
-
- menulab[AMI_MENU_HOTLIST_MAX] = ami_utf8_easy((char *)messages_get("Settings"));
- menulab[AMI_MENU_HOTLIST_MAX+1] = ami_utf8_easy((char *)messages_get("SettingsEdit"));
- menulab[AMI_MENU_HOTLIST_MAX+2] = NM_BARLABEL;
- menulab[AMI_MENU_HOTLIST_MAX+3] = ami_utf8_easy((char *)messages_get("SnapshotWindow"));
- menulab[AMI_MENU_HOTLIST_MAX+4] = ami_utf8_easy((char *)messages_get("SettingsSave"));
- menulab[AMI_MENU_HOTLIST_MAX+5] = ami_utf8_easy((char *)messages_get("ARexx"));
- menulab[AMI_MENU_HOTLIST_MAX+6] = ami_utf8_easy((char *)messages_get("ARexxExecute"));
- menulab[AMI_MENU_HOTLIST_MAX+7] = NM_BARLABEL;
+ SetAttrs(gwin->objects[OID_MAIN],
+ WINDOW_NewMenu, NULL,
+ TAG_DONE);
+
+ ami_free_menulabs(gwin);
+ ami_create_menu(BROWSER_WINDOW_NORMAL, gwin);
+
+ SetAttrs(gwin->objects[OID_MAIN],
+ WINDOW_NewMenu, gwin->menu,
+ TAG_DONE);
+
+ schedule(6000,(void *)ami_menu_refresh,gwin);
}
-struct NewMenu *ami_create_menu(ULONG type)
+struct NewMenu *ami_create_menu(ULONG type, struct gui_window_2 *gwin)
{
int i;
ULONG menuflags = 0;
- STATIC struct NewMenu menu[] = {
- {NM_TITLE,0,0,0,0,0,}, // project
- { NM_ITEM,0,"N",0,0,0,}, // new window
- { NM_ITEM,0,"T",0,0,0,}, // new tab
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,"O",0,0,0,}, // open local file
- { NM_ITEM,0,0,0,0,0,}, // save
- { NM_SUB,0,"S",0,0,0,}, // save as source
- { NM_SUB,0,0,0,0,0,}, // save as text
- { NM_SUB,0,0,0,0,0,}, // save as complete
- { NM_SUB,0,0,0,0,0,}, // save as pdf
- { NM_SUB,0,0,0,0,0,}, // save as iff
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,"K",0,0,0,}, // close tab
- { NM_ITEM,0,0,0,0,0,}, // close window
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,"P",0,0,0,}, // print
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,"?",0,0,0,}, // about
- { NM_ITEM,0,"Q",0,0,0,}, // quit
- {NM_TITLE,0,0,0,0,0,}, // edit
- { NM_ITEM,0,"X",0,0,0,}, // cut
- { NM_ITEM,0,"C",0,0,0,}, // copy
- { NM_ITEM,0,"V",0,0,0,}, // paste
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,"A",0,0,0,}, // select all
- { NM_ITEM,0,"Z",0,0,0,}, // clear selection
- {NM_TITLE,0,0,0,0,0,}, // browser
- { NM_ITEM,0,"F",0,0,0,}, // find in page
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,0,0,0,0,}, // local history
- { NM_ITEM,0,0,0,0,0,}, // global history
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,0,0,0,0,}, // cookies
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,0,0,0,0,}, // scale
- { NM_SUB,0,"-",0,0,0,}, // decrease
- { NM_SUB,0,"=",0,0,0,}, // normal
- { NM_SUB,0,"+",0,0,0,}, // increase
- { NM_ITEM,0,0,0,0,0,}, // redraw
- {NM_TITLE,0,0,0,0,0,}, // hotlist
- { NM_ITEM,0,0,0,0,0,}, // add to hotlist
- { NM_ITEM,0,"H",0,0,0,}, // show hotlist (treeview)
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** hotlist entry **
- {NM_TITLE,0,0,0,0,0,}, // settings
- { NM_ITEM,0,0,0,0,0,}, // edit prefs
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_ITEM,0,0,0,0,0,}, // snapshot window
- { NM_ITEM,0,0,0,0,0,}, // save settings
- {NM_TITLE,0,0,0,0,0,}, // arexx
- { NM_ITEM,0,0,0,0,0,}, // execute arexx
- { NM_ITEM,NM_BARLABEL,0,0,0,0,},
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_IGNORE,0,0,0,0,0,}, // ** arexx entry **
- { NM_END,0,0,0,0,0,},
- };
+
+ ami_init_menulabs(gwin);
+ gwin->menu = AllocVec(sizeof(struct NewMenu) * (AMI_MENU_AREXX_MAX + 1), MEMF_CLEAR);
if(type != BROWSER_WINDOW_NORMAL)
{
menuflags = NM_ITEMDISABLED;
}
- for(i=0;i<=AMI_MENU_MAX;i++)
+ for(i=0;i<=AMI_MENU_AREXX_MAX;i++)
{
- menu[i].nm_Label = menulab[i];
+ gwin->menu[i].nm_Type = gwin->menutype[i];
+ gwin->menu[i].nm_Label = gwin->menulab[i];
+ if(gwin->menukey[i]) gwin->menu[i].nm_CommKey = &gwin->menukey[i];
+ gwin->menu[i].nm_Flags = 0;
}
- menu[1].nm_Flags = menuflags;
- menu[2].nm_Flags = menuflags;
- menu[12].nm_Flags = menuflags;
- menu[13].nm_Flags = menuflags;
+ gwin->menu[1].nm_Flags = menuflags;
+ gwin->menu[2].nm_Flags = menuflags;
+ gwin->menu[12].nm_Flags = menuflags;
+ gwin->menu[13].nm_Flags = menuflags;
#ifndef WITH_PDF_EXPORT
- menu[9].nm_Flags = NM_ITEMDISABLED;
+ gwin->menu[9].nm_Flags = NM_ITEMDISABLED;
#endif
+ ami_menu_scan(ami_tree_get_tree(hotlist_window), false, gwin);
+ ami_menu_arexx_scan(gwin);
+
if(!menualreadyinit)
{
- ami_menu_scan(hotlist,menu);
- ami_menu_arexx_scan(&menu);
-
aslhookfunc.h_Entry = (void *)&ami_asl_mime_hook;
aslhookfunc.h_SubEntry = NULL;
aslhookfunc.h_Data = NULL;
@@ -288,10 +288,16 @@ struct NewMenu *ami_create_menu(ULONG type)
menualreadyinit = TRUE;
}
- return(menu);
+/* Set up scheduler to refresh the hotlist menu
+ Disabled as it causes everything to slow down to a halt after
+ several iterations
+ schedule(6000,(void *)ami_menu_refresh,gwin);
+*/
+
+ return(gwin->menu);
}
-void ami_menu_arexx_scan(struct NewMenu *menu)
+void ami_menu_arexx_scan(struct gui_window_2 *gwin)
{
int item = AMI_MENU_AREXX;
BPTR lock = 0;
@@ -323,23 +329,20 @@ void ami_menu_arexx_scan(struct NewMenu *menu)
for(ead = (struct ExAllData *)buffer; ead; ead = ead->ed_Next)
{
if(item >= AMI_MENU_AREXX_MAX) continue;
- if(!strcasecmp(ead->ed_Name, option_arexx_startup)) continue;
- if(!strcasecmp(ead->ed_Name, option_arexx_shutdown)) continue;
-
if(EAD_IS_FILE(ead))
{
- menu[item].nm_Type = NM_ITEM;
+ gwin->menu[item].nm_Type = NM_ITEM;
if(ead->ed_Comment[0] != '\0')
{
- menulab[item] = (char *)strdup(ead->ed_Comment);
+ gwin->menulab[item] = (char *)strdup(ead->ed_Comment);
}
else
{
- menulab[item] = (char *)strdup(ead->ed_Name);
+ gwin->menulab[item] = (char *)strdup(ead->ed_Name);
}
- menu[item].nm_Label = menulab[item];
- menu[item].nm_UserData = (char *)strdup(ead->ed_Name);
+ gwin->menu[item].nm_Label = gwin->menulab[item];
+ gwin->menu[item].nm_UserData = (char *)strdup(ead->ed_Name);
item++;
}
@@ -351,31 +354,37 @@ void ami_menu_arexx_scan(struct NewMenu *menu)
}
UnLock(lock);
}
+
+ gwin->menu[item].nm_Type = NM_END;
+ gwin->menu[item].nm_Label = NULL;
}
-void ami_menu_scan(struct tree *tree,struct NewMenu *menu)
+ULONG ami_menu_scan(struct tree *tree, bool count, struct gui_window_2 *gwin)
{
- struct node *root = tree->root->child;
- struct node_element *element=NULL;
+ struct node *root = tree_node_get_child(tree_get_root(tree));
struct node *node;
+ struct node_element *element;
static WORD gen = 0;
static ULONG item;
item = AMI_MENU_HOTLIST;
- for (node = root; node; node = node->next)
+ for (node = root; node; node = tree_node_get_next(node))
{
- element = tree_find_element(node, TREE_ELEMENT_NAME);
- if(!element) element = tree_find_element(node, TREE_ELEMENT_TITLE);
- if(element && (strcmp(element->text,"Menu")==0))
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ if(!element) element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ if(element && (strcmp(tree_node_element_get_text(element),"Menu")==0))
{
// found menu
- ami_menu_scan_2(tree,node->child,&gen,&item,menu);
+ ami_menu_scan_2(tree,tree_node_get_child(node),&gen,&item,count,gwin);
}
}
+
+ return(item - AMI_MENU_HOTLIST);
}
-void ami_menu_scan_2(struct tree *tree,struct node *root,WORD *gen,ULONG *item,struct NewMenu *menu)
+void ami_menu_scan_2(struct tree *tree,struct node *root,WORD *gen,
+ ULONG *item, bool count, struct gui_window_2 *gwin)
{
struct node *tempnode;
struct node_element *element=NULL;
@@ -383,38 +392,39 @@ void ami_menu_scan_2(struct tree *tree,struct node *root,WORD *gen,ULONG *item,s
*gen = *gen + 1;
- for (node = root; node; node = node->next)
+ for (node = root; node; node = tree_node_get_next(node))
{
- element = tree_find_element(node, TREE_ELEMENT_TITLE);
-
if((*gen > 0) && (*gen < 3))
{
- if(*item >= AMI_MENU_HOTLIST_MAX) return;
-
- if(*gen == 1) menu[*item].nm_Type = NM_ITEM;
- if(*gen == 2) menu[*item].nm_Type = NM_SUB;
+// if(*item >= AMI_MENU_HOTLIST_MAX) return;
- if(strcmp(element->text,"--"))
- {
- menulab[*item] = ami_utf8_easy((char *)element->text);
- }
- else
+ if(!count)
{
- menulab[*item] = NM_BARLABEL;
- }
+ if(*gen == 1) gwin->menu[*item].nm_Type = NM_ITEM;
+ if(*gen == 2) gwin->menu[*item].nm_Type = NM_SUB;
+
+ if(strcmp(tree_url_node_get_title(node),"--"))
+ {
+ gwin->menulab[*item] = ami_utf8_easy((char *)tree_url_node_get_title(node));
+ }
+ else
+ {
+ gwin->menulab[*item] = NM_BARLABEL;
+ }
- menu[*item].nm_Label = menulab[*item];
+ gwin->menu[*item].nm_Label = gwin->menulab[*item];
- element = tree_find_element(node, TREE_ELEMENT_URL);
- if(element && element->text) menu[*item].nm_UserData = (void *)element->text;
- if(node->folder && (!node->child)) menu[*item].nm_Flags = NM_ITEMDISABLED;
+ gwin->menu[*item].nm_UserData = (void *)tree_url_node_get_url(node);
+ if(tree_node_is_folder(node) && (!tree_node_get_child(node)))
+ gwin->menu[*item].nm_Flags = NM_ITEMDISABLED;
+ }
*item = *item + 1;
}
- if (node->child)
+ if (tree_node_get_child(node))
{
- ami_menu_scan_2(tree,node->child,gen,item,menu);
+ ami_menu_scan_2(tree,tree_node_get_child(node),gen,item,count,gwin);
}
}
@@ -698,11 +708,11 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item)
break;
case 3: // global history
- ami_open_tree(global_history_tree,AMI_TREE_HISTORY);
+ ami_tree_open(global_history_window,AMI_TREE_HISTORY);
break;
case 5: // cookies tree
- ami_open_tree(cookies_tree,AMI_TREE_COOKIES);
+ ami_tree_open(cookies_window,AMI_TREE_COOKIES);
break;
case 7: // size
@@ -736,12 +746,18 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item)
switch(itemnum)
{
case 0: // add
- ami_hotlist_add(hotlist->root,gwin->bw->current_content);
- options_save_tree(hotlist,option_hotlist_file,messages_get("TreeHotlist"));
+ if (bw == NULL ||
+ bw->current_content
+ == NULL ||
+ content_get_url(bw->current_content)
+ == NULL)
+ break;
+ hotlist_add_page(content_get_url(gwin->bw->
+ current_content));
break;
case 1: // show
- ami_open_tree(hotlist,AMI_TREE_HOTLIST);
+ ami_tree_open(hotlist_window, AMI_TREE_HOTLIST);
break;
default: // bookmarks
diff --git a/amiga/menu.h b/amiga/menu.h
index 8f925411a..5a739d616 100755
--- a/amiga/menu.h
+++ b/amiga/menu.h
@@ -19,12 +19,14 @@
#ifndef AMIGA_MENU_H
#define AMIGA_MENU_H
#include <exec/types.h>
-#include "amiga/gui.h"
#include <intuition/intuition.h>
+#include <libraries/gadtools.h>
+#include "content/hlcache.h"
/* Number of hotlist items, menu structure needs to be changed in ami_create_menu()
* if this value is changed. */
-#define AMI_HOTLIST_ITEMS 40
+#define AMI_HOTLIST_ITEMS 60
+//gwin->hotlist_items
/* Maximum number of menu items - first value is number of static items
* (ie. everything not intially defined as NM_IGNORE) */
@@ -61,11 +63,12 @@
#define AMI_MENU_CLEAR FULLMENUNUM(1,5,0)
#define AMI_MENU_FIND FULLMENUNUM(2,0,0)
-char *menulab[AMI_MENU_AREXX_MAX+1];
+struct gui_window;
+struct gui_window_2;
-struct NewMenu *ami_create_menu(ULONG type);
-void ami_init_menulabs(void);
-void ami_free_menulabs(void);
+void ami_free_menulabs(struct gui_window_2 *gwin);
+struct NewMenu *ami_create_menu(ULONG type, struct gui_window_2 *gwin);
+void ami_menu_refresh(struct gui_window_2 *gwin);
void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item);
void ami_menu_update_disabled(struct gui_window *g, hlcache_handle *c);
#endif
diff --git a/amiga/object.c b/amiga/object.c
index a51be81c1..93094cbda 100755
--- a/amiga/object.c
+++ b/amiga/object.c
@@ -48,14 +48,24 @@ struct nsObject *AddObject(struct MinList *objlist,ULONG otype)
return(dtzo);
}
-void DelObject(struct nsObject *dtzo)
+void DelObjectInternal(struct nsObject *dtzo, BOOL free_obj)
{
Remove((struct Node *)dtzo);
- if(dtzo->objstruct) FreeVec(dtzo->objstruct);
+ if(dtzo->objstruct && free_obj) FreeVec(dtzo->objstruct);
FreeVec(dtzo);
dtzo = NULL;
}
+void DelObject(struct nsObject *dtzo)
+{
+ DelObjectInternal(dtzo, TRUE);
+}
+
+void DelObjectNoFree(struct nsObject *dtzo)
+{
+ DelObjectInternal(dtzo, FALSE);
+}
+
void FreeObjList(struct MinList *objlist)
{
struct nsObject *node;
diff --git a/amiga/object.h b/amiga/object.h
index 82d01098d..db7869df8 100755
--- a/amiga/object.h
+++ b/amiga/object.h
@@ -48,6 +48,7 @@ struct nsObject
struct MinList *NewObjList(void);
struct nsObject *AddObject(struct MinList *objlist,ULONG otype);
void DelObject(struct nsObject *dtzo);
+void DelObjectNoFree(struct nsObject *dtzo);
void FreeObjList(struct MinList *objlist);
#endif
diff --git a/amiga/options.h b/amiga/options.h
index 7e4e6cc15..f32938969 100644
--- a/amiga/options.h
+++ b/amiga/options.h
@@ -34,7 +34,6 @@ extern bool option_truecolour_mouse_pointers;
extern bool option_use_os_pointers;
extern bool option_new_tab_active;
extern bool option_kiosk_mode;
-extern char *option_recent_file;
extern char *option_search_engines_file;
extern char *option_search_ico_file;
extern char *option_arexx_dir;
@@ -68,7 +67,6 @@ bool option_truecolour_mouse_pointers = false; \
bool option_use_os_pointers = true; \
bool option_new_tab_active = false; \
bool option_kiosk_mode = false; \
-char *option_recent_file = 0; \
char *option_search_engines_file = 0; \
char *option_search_ico_file = 0; \
char *option_arexx_dir = 0; \
@@ -102,7 +100,6 @@ bool option_drag_save_icons = true; \
{ "os_mouse_pointers", OPTION_BOOL, &option_use_os_pointers}, \
{ "new_tab_is_active", OPTION_BOOL, &option_new_tab_active}, \
{ "kiosk_mode", OPTION_BOOL, &option_kiosk_mode}, \
-{ "recent_file", OPTION_STRING, &option_recent_file }, \
{ "search_engines_file", OPTION_STRING, &option_search_engines_file }, \
{ "search_ico_file", OPTION_STRING, &option_search_ico_file }, \
{ "arexx_dir", OPTION_STRING, &option_arexx_dir }, \
diff --git a/amiga/plotters.c b/amiga/plotters.c
index de60b9518..5bd34d2bc 100755
--- a/amiga/plotters.c
+++ b/amiga/plotters.c
@@ -91,7 +91,7 @@ void ami_cairo_set_colour(cairo_t *cr,colour c)
void ami_cairo_set_solid(cairo_t *cr)
{
double dashes = 0;
-
+
cairo_set_dash(glob->cr, &dashes, 0, 0);
}
@@ -240,7 +240,7 @@ bool ami_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
glob->rp.LinePtrn = PATT_DASH;
break;
}
-
+
SetRPAttrs(&glob->rp,
RPTAG_APenColor,
p96EncodeColor(RGBFB_A8B8G8R8, style->stroke_colour),
@@ -272,7 +272,7 @@ bool ami_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
break;
}
- if (style->stroke_width == 0)
+ if (style->stroke_width == 0)
cairo_set_line_width(glob->cr, 1);
else
cairo_set_line_width(glob->cr, style->stroke_width);
@@ -337,13 +337,17 @@ bool ami_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
break;
}
- if (style->stroke_width == 0)
+ if (style->stroke_width == 0)
cairo_set_line_width(glob->cr, 1);
else
cairo_set_line_width(glob->cr, style->stroke_width);
- cairo_move_to(glob->cr, x0 + 0.5, y0 + 0.5);
- cairo_line_to(glob->cr, x1 + 0.5, y1 + 0.5);
+ /* core expects horizontal and vertical lines to be on pixels, not
+ * between pixels */
+ cairo_move_to(current_cr, (x0 == x1) ? x0 + 0.5 : x0,
+ (y0 == y1) ? y0 + 0.5 : y0);
+ cairo_line_to(current_cr, (x0 == x1) ? x1 + 0.5 : x1,
+ (y0 == y1) ? y1 + 0.5 : y1);
cairo_stroke(glob->cr);
#endif
return true;
@@ -426,7 +430,7 @@ bool ami_clip(int x0, int y0, int x1, int y1)
return true;
}
-bool ami_text(int x, int y, const char *text, size_t length,
+bool ami_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
#ifdef AMI_PLOTTER_DEBUG
@@ -459,7 +463,7 @@ bool ami_disc(int x, int y, int radius, const plot_style_t *style)
p96EncodeColor(RGBFB_A8B8G8R8, style->stroke_colour),
TAG_DONE);
- DrawEllipse(&glob->rp,x,y,radius,radius);
+ DrawEllipse(&glob->rp,x,y,radius,radius);
}
#else
if (style->fill_type != PLOT_OP_TYPE_NONE) {
diff --git a/amiga/resources/Themes/AISS/Theme b/amiga/resources/Themes/AISS/Theme
index 8f3dd8aec..8dfa1d3a7 100755
--- a/amiga/resources/Themes/AISS/Theme
+++ b/amiga/resources/Themes/AISS/Theme
@@ -24,12 +24,8 @@ theme_closetab_g:*TBImages:list_cancel
theme_addtab:*TBImages:list_add
theme_addtab_s:*TBImages:list_add
theme_addtab_g:*TBImages:list_add
-theme_list_folder_closed:*TBImages:list_folderfold
-theme_list_folder_open:*TBImages:list_folderunfold
-theme_list_bookmark:*TBImages:list_bookmark
-theme_list_cookie:*TBImages:list_abstract
-theme_list_history:*TBImages:list_archive
-theme_list_sslcert:*TBImages:list_crypt
+theme_list_folder:*TBImages:list_drawer
+theme_list_content:*TBImages:list_abstract
theme_throbber:Throbber
theme_throbber_frames:13
theme_throbber_delay:100
diff --git a/amiga/resources/Themes/Default/Theme b/amiga/resources/Themes/Default/Theme
index eb6b9c3ce..2497af467 100755
--- a/amiga/resources/Themes/Default/Theme
+++ b/amiga/resources/Themes/Default/Theme
@@ -37,12 +37,8 @@ theme_closetab_g:closetab_g.png
theme_addtab:
theme_addtab_s:
theme_addtab_g:
-theme_list_folder_closed:
-theme_list_folder_open:
-theme_list_bookmark:
-theme_list_cookie:
-theme_list_history:
-theme_list_sslcert:
+theme_list_folder:directory.png
+theme_list_content:content.png
theme_throbber:Throbber
theme_throbber_frames:9
theme_throbber_delay:100
diff --git a/amiga/resources/Themes/Default/content.png b/amiga/resources/Themes/Default/content.png
new file mode 120000
index 000000000..4b8c13c1c
--- /dev/null
+++ b/amiga/resources/Themes/Default/content.png
@@ -0,0 +1 @@
+../../../../!NetSurf/Resources/Icons/content.png \ No newline at end of file
diff --git a/amiga/resources/Themes/Default/directory.png b/amiga/resources/Themes/Default/directory.png
new file mode 120000
index 000000000..0e6ce854d
--- /dev/null
+++ b/amiga/resources/Themes/Default/directory.png
@@ -0,0 +1 @@
+../../../../!NetSurf/Resources/Icons/directory.png \ No newline at end of file
diff --git a/amiga/sslcert.c b/amiga/sslcert.c
index c02329449..8eede70f2 100644
--- a/amiga/sslcert.c
+++ b/amiga/sslcert.c
@@ -16,224 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <assert.h>
-#include <string.h>
-#include <proto/dos.h>
#include <proto/exec.h>
-#include <proto/utility.h>
-#include "utils/errors.h"
-#include "utils/utils.h"
-#include "utils/messages.h"
-#include "content/urldb.h"
-#include "content/fetch.h"
-#include "desktop/tree.h"
#include "amiga/tree.h"
-#include "amiga/gui.h"
-
-struct session_data {
- struct session_cert *certs;
- unsigned long num;
- nserror (*cb)(bool proceed, void *pw);
- void *cbpw;
- char *url;
- struct tree *tree;
-};
-struct session_cert {
- char version[16], valid_from[32], valid_to[32], type[8], serial[32];
- char *issuer_t;
- char *subject_t;
- uintptr_t issuer;
- uintptr_t subject;
-};
-
-void ami_gui_cert_close(struct session_data *data);
-bool ami_gui_cert_apply(struct session_data *session);
+#include "amiga/sslcert.h"
void gui_cert_verify(const char *url,
const struct ssl_cert_info *certs, unsigned long num,
nserror (*cb)(bool proceed, void *pw), void *cbpw)
{
- const struct ssl_cert_info *from;
- struct session_cert *to;
- struct session_data *data;
- struct tree *tree;
- struct node *node;
- long i;
- STRPTR yesorno,reqcontents;
- int res = 0;
- struct treeview_window *twin;
-
- assert(certs);
-
- /* copy the certificate information */
- data = calloc(1, sizeof(struct session_data));
- if (!data) {
- warn_user("NoMemory", 0);
- return;
- }
- data->url = strdup(url);
- if (!data->url) {
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
- data->cb = cb;
- data->cbpw = cbpw;
- data->num = num;
- data->certs = calloc(num, sizeof(struct session_cert));
- if (!data->certs) {
- free(data->url);
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
- for (i = 0; i < (long)num; i++) {
- to = &data->certs[i];
- from = &certs[i];
- to->subject_t = strdup(from->subject);
- to->issuer_t = strdup(from->issuer);
- if ((!to->subject_t) || (!to->issuer_t)) {
- for (; i >= 0; i--) {
- to = &data->certs[i];
- free(to->subject_t);
- free(to->issuer_t);
- }
- free(data->certs);
- free(data->url);
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
- snprintf(to->version, sizeof data->certs->version, "%ld",
- from->version);
- snprintf(to->valid_from, sizeof data->certs->valid_from, "%s",
- from->not_before);
- snprintf(to->type, sizeof data->certs->type, "%d",
- from->cert_type);
- snprintf(to->valid_to, sizeof data->certs->valid_to, "%s",
- from->not_after);
- snprintf(to->serial, sizeof data->certs->serial, "%ld",
- from->serial);
- }
-
- tree = calloc(sizeof(struct tree), 1);
- if (!tree) {
- //ro_gui_cert_close(ssl_w);
- warn_user("NoMemory", 0);
- return;
- }
- tree->root = tree_create_folder_node(NULL, "Root");
- if (!tree->root) {
-// ro_gui_cert_close(ssl_w);
- warn_user("NoMemory", 0);
- free(tree);
- tree = NULL;
- return;
- }
- tree->root->expanded = true;
- tree->handle = 0;
- tree->movable = false;
- tree->no_drag = true;
- tree->no_vscroll = true;
- tree->no_furniture = true;
- tree->single_selection = true;
- data->tree = tree;
-
- /* put the SSL names in the tree */
- for (i = 0; i < (long)num; i++) {
- node = tree_create_leaf_node(tree->root, certs[i].subject);
- if (node) {
- node->data.data = TREE_ELEMENT_SSL;
- tree_set_node_sprite(node, "small_xxx", "small_xxx");
- }
- }
- tree_initialise(tree);
-
- ami_open_tree(tree,AMI_TREE_SSLCERT);
- twin = (struct treeview_window *)data->tree->handle;
-
- if(yesorno = ASPrintf("%s|%s",messages_get("Accept"),messages_get("Reject")))
- {
- if(reqcontents = ASPrintf("%s\n\n%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %s",
- messages_get("SSLError"),
- messages_get("Subject"),
- to->subject_t,
- messages_get("Issuer"),
- to->issuer_t,
- messages_get("Version"),
- to->version,
- messages_get("ValidFrom"),
- to->valid_from,
- messages_get("ValidTo"),
- to->valid_to))
- {
- res = TimedDosRequesterTags(TDR_ImageType,TDRIMAGE_QUESTION,
- TDR_Window,twin->win,
- TDR_TitleString,messages_get("NetSurf"),
- TDR_GadgetString,yesorno,
- TDR_FormatString,reqcontents,
- TAG_DONE);
-
- FreeVec(reqcontents);
- }
-
- FreeVec(yesorno);
- }
-
- if(res == 1)
- {
- ami_gui_cert_apply(data);
- }
- ami_gui_cert_close(data);
-
-}
-
-void ami_gui_cert_close(struct session_data *data)
-{
- unsigned long i;
-
- if(data->tree->handle)
- {
- ami_tree_close((struct treeview_window *)data->tree->handle);
- win_destroyed = true;
- }
+ struct sslcert_session_data *data;
+ struct treeview_window *ssl_window;
- assert(data);
+ data = sslcert_create_session_data(num, url, cb, cbpw);
-/*
- for (i = 0; i < data->num; i++) {
- if (data->certs[i].subject)
- textarea_destroy(data->certs[i].subject);
- if (data->certs[i].issuer)
- textarea_destroy(data->certs[i].issuer);
- }
-*/
+ ssl_window = ami_tree_create(sslcert_get_tree_flags(), data);
+ if(!ssl_window) return;
- /* Send failure if callback exists */
- if (data->cb != NULL)
- data->cb(false, data->cbpw);
+ sslcert_load_tree(ami_tree_get_tree(ssl_window), certs, data);
- if (data->tree) {
- tree_delete_node(data->tree, data->tree->root, false);
- free(data->tree);
- }
-
- free(data->certs);
- free(data->url);
- free(data);
+ ami_tree_open(ssl_window, AMI_TREE_SSLCERT);
}
-bool ami_gui_cert_apply(struct session_data *session)
+void ami_ssl_free(struct treeview_window *twin)
{
- assert(session);
-
- urldb_set_cert_permissions(session->url, true);
-
- session->cb(true, session->cbpw);
-
- /* Invalidate callback */
- session->cb = NULL;
- session->cbpw = NULL;
-
- return true;
+ ami_tree_destroy(twin);
}
diff --git a/windows/hotlist.c b/amiga/sslcert.h
index dab18d11c..10078d9bb 100644
--- a/windows/hotlist.c
+++ b/amiga/sslcert.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "desktop/browser.h"
-#include "content/hlcache.h"
+#ifndef AMIGA_SSLCERT_H
+#define AMIGA_SSLCERT_H
+#include "desktop/sslcert.h"
-void hotlist_visited(hlcache_handle *content)
-{
-}
+void ami_ssl_free(struct treeview_window *twin);
+#endif
diff --git a/amiga/theme.c b/amiga/theme.c
index cf9148581..7b10e139b 100644
--- a/amiga/theme.c
+++ b/amiga/theme.c
@@ -121,7 +121,7 @@ void ami_theme_throbber_setup(void)
char throbberfile[1024];
Object *dto;
- ami_get_theme_filename(throbberfile,"theme_throbber");
+ ami_get_theme_filename(throbberfile,"theme_throbber",false);
throbber_frames=atoi(messages_get("theme_throbber_frames"));
throbber_update_interval = atoi(messages_get("theme_throbber_delay"));
if(throbber_update_interval == 0) throbber_update_interval = 100;
@@ -170,15 +170,20 @@ void ami_theme_throbber_free(void)
p96FreeBitMap(throbber);
}
-void ami_get_theme_filename(char *filename, char *themestring)
+void ami_get_theme_filename(char *filename, char *themestring, bool protocol)
{
+ if(protocol)
+ strcpy(filename,"file:///");
+ else
+ strcpy(filename,"");
+
if(messages_get(themestring)[0] == '*')
{
- strncpy(filename, messages_get(themestring) + 1, 100);
+ strncat(filename,messages_get(themestring)+1,100);
}
else
{
- strcpy(filename, option_theme);
+ strcat(filename, option_theme);
AddPart(filename, messages_get(themestring), 100);
}
}
@@ -273,7 +278,7 @@ void ami_init_mouse_pointers(void)
if(option_truecolour_mouse_pointers)
{
- ami_get_theme_filename(&ptrfname,ptrs32[i]);
+ ami_get_theme_filename(&ptrfname,ptrs32[i], false);
if(dobj = GetIconTags(ptrfname,ICONGETA_UseFriendBitMap,TRUE,TAG_DONE))
{
if(IconControl(dobj, ICONCTRLA_GetImageDataFormat, &format, TAG_DONE))
@@ -325,7 +330,7 @@ void ami_init_mouse_pointers(void)
if(!mouseptrobj[i])
{
- ami_get_theme_filename(ptrfname,ptrs[i]);
+ ami_get_theme_filename(ptrfname,ptrs[i], false);
if(ptrfile = Open(ptrfname,MODE_OLDFILE))
{
int mx,my;
diff --git a/amiga/theme.h b/amiga/theme.h
index 3a396fdb1..ba1295d61 100644
--- a/amiga/theme.h
+++ b/amiga/theme.h
@@ -27,7 +27,7 @@
ULONG throbber_width, throbber_height;
void ami_theme_init(void);
-void ami_get_theme_filename(char *filename, char *themestring);
+void ami_get_theme_filename(char *filename, char *themestring, bool protocol);
void ami_theme_throbber_setup(void);
void ami_theme_throbber_free(void);
diff --git a/amiga/tree.c b/amiga/tree.c
index 7000fb76c..f01805314 100755
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008,2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,13 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "desktop/tree.h"
-#include <proto/listbrowser.h>
#include <proto/window.h>
#include <proto/layout.h>
+#include <proto/space.h>
+#include <proto/label.h>
+#include <proto/scroller.h>
#include <classes/window.h>
-#include <gadgets/listbrowser.h>
+#include <gadgets/space.h>
+#include <images/label.h>
#include <gadgets/layout.h>
+#include <gadgets/scroller.h>
#include <reaction/reaction_macros.h>
#include "amiga/gui.h"
#include "content/urldb.h"
@@ -36,222 +39,395 @@
#include "utils/messages.h"
#include <proto/bitmap.h>
#include <images/bitmap.h>
+#include <proto/graphics.h>
+#include <intuition/icclass.h>
+#include <proto/asl.h>
+#include <proto/utility.h>
+#include <libraries/gadtools.h>
+#include <proto/dos.h>
+#include "amiga/utf8.h"
+#include "desktop/cookies.h"
+#include "desktop/history_global_core.h"
+#include "desktop/hotlist.h"
+#include "amiga/sslcert.h"
+#include "utils/utils.h"
+
+#define AMI_TREE_MENU_ITEMS 19
+
+struct treeview_window {
+ struct Window *win;
+ Object *objects[OID_LAST];
+ struct Gadget *gadgets[GID_LAST];
+ struct nsObject *node;
+ ULONG pad[5];
+ int type;
+ struct NewMenu *menu;
+ char *menu_name[AMI_TREE_MENU_ITEMS];
+ struct tree *tree;
+ struct Hook scrollerhook;
+ uint32 key_state;
+ uint32 mouse_state;
+ int drag_x;
+ int drag_y;
+ struct timeval lastclick;
+ int max_width;
+ int max_height;
+ struct gui_globals globals;
+ struct sslcert_session_data *ssl_data;
+};
+
+void ami_tree_draw(struct treeview_window *twin);
+static void ami_tree_redraw_request(int x, int y, int width, int height,
+ void *data);
+static void ami_tree_resized(struct tree *tree, int width,
+ int height, void *data);
+static void ami_tree_scroll_visible(int y, int height, void *data);
+static void ami_tree_get_window_dimensions(int *width, int *height, void *data);
+
+const struct treeview_table ami_tree_callbacks = {
+ .redraw_request = ami_tree_redraw_request,
+ .resized = ami_tree_resized,
+ .scroll_visible = ami_tree_scroll_visible,
+ .get_window_dimensions = ami_tree_get_window_dimensions
+};
+
+struct treeview_window *ami_tree_create(uint8 flags,
+ struct sslcert_session_data *ssl_data)
+{
+ struct treeview_window *twin;
-struct Node *selectednode;
-struct node *selectednode2;
+ twin = AllocVec(sizeof(struct treeview_window),
+ MEMF_PRIVATE | MEMF_CLEAR);
+
+ if(!twin)
+ {
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
-void ami_add_elements(struct treeview_window *twin,struct node *root,WORD *gen);
-bool ami_tree_launch_node(struct tree *tree, struct node *node);
-void free_browserlist(struct List *list);
-void ami_move_node(struct treeview_window *twin,int move);
-void ami_new_bookmark(struct treeview_window *twin);
-void ami_recreate_listbrowser(struct treeview_window *twin);
+ twin->ssl_data = ssl_data;
-void tree_initialise_redraw(struct tree *tree)
-{
+ twin->tree = tree_create(flags, &ami_tree_callbacks, twin);
+ return twin;
}
-void tree_redraw_area(struct tree *tree, int x, int y, int width, int height)
+void ami_tree_destroy(struct treeview_window *twin)
{
+ tree_delete(twin->tree);
+ FreeVec(twin);
}
-void tree_draw_line(int x, int y, int width, int height)
+struct tree *ami_tree_get_tree(struct treeview_window *twin)
{
+ return twin->tree;
}
-void tree_draw_node_element(struct tree *tree, struct node_element *element)
+void ami_tree_resized(struct tree *tree, int width, int height, void *data)
{
- return;
-#if 0
-/* add element to listbrowser list */
+ struct treeview_window *twin = data;
+ struct IBox *bbox;
- struct Node *lbnode;
- struct treeview_window *twin = tree->handle;
- struct node *tempnode;
- int generation=1;
- BOOL edit = FALSE;
+ twin->max_height = height;
+ twin->max_width = width;
- tempnode = element->parent;
- edit = tempnode->editable;
-
- while(tempnode)
+ if(twin->win)
{
- tempnode = tempnode->parent;
- generation++;
- }
+ GetAttr(SPACE_AreaBox,twin->gadgets[GID_BROWSER],(ULONG *)&bbox);
- switch (element->type) {
- case NODE_ELEMENT_TEXT_PLUS_SPRITE:
- case NODE_ELEMENT_TEXT:
- if (lbnode = AllocListBrowserNode(3,
-// LBNA_UserData,nodetime,
- LBNA_Generation,1,
- LBNA_Column, 0,
- LBNCA_CopyText,TRUE,
- LBNCA_Text, element->text,
- LBNCA_Editable,edit,
- LBNA_Column, 1,
- LBNCA_CopyText,TRUE,
- LBNCA_Text, "",
- LBNA_Column, 2,
- LBNCA_CopyText,TRUE,
- LBNCA_Text, "",
- TAG_DONE))
- {
- AddTail(twin->listbrowser_list, lbnode);
- }
- break;
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL,
+ SCROLLER_Total, height,
+ SCROLLER_Visible, bbox->Height,
+ TAG_DONE);
+
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL,
+ SCROLLER_Total, width,
+ SCROLLER_Visible, bbox->Width,
+ TAG_DONE);
}
-#endif
}
-void tree_draw_node_expansion(struct tree *tree, struct node *node)
+/**
+ * Retrieves the dimensions of the window with the tree
+ *
+ * \param data user data assigned to the tree on tree creation
+ * \param width will be updated to window width if not NULL
+ * \param height will be updated to window height if not NULL
+ */
+void ami_tree_get_window_dimensions(int *width, int *height, void *data)
{
- DebugPrintF("tree_draw_node_expansion\n");
+ struct treeview_window *twin = data;
+ struct IBox *bbox;
+
+ GetAttr(SPACE_AreaBox,twin->gadgets[GID_BROWSER],(ULONG *)&bbox);
+
+ if(width) *width = bbox->Width;
+ if(height) *height = bbox->Height;
}
-void tree_recalculate_node_element(struct node_element *element)
+/**
+ * Translates a content_type to the name of a respective icon
+ *
+ * \param content_type content type
+ * \param buffer buffer for the icon name
+ */
+void tree_icon_name_from_content_type(char *buffer, content_type type)
{
+ // TODO: design/acquire icons
+ switch (type) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ case CONTENT_CSS:
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ case CONTENT_PNG:
+#endif
+#ifdef WITH_MNG
+ case CONTENT_JNG:
+ case CONTENT_MNG:
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+#endif
+#ifdef WITH_BMP
+ case CONTENT_BMP:
+ case CONTENT_ICO:
+#endif
+#ifdef WITH_NSSPRITE
+ case CONTENT_SPRITE:
+#endif
+#ifdef WITH_NS_SVG
+ case CONTENT_SVG:
+#endif
+ default:
+ ami_get_theme_filename(buffer,"theme_list_content",true);
+ break;
+ }
}
-void tree_update_URL_node(struct node *node, const char *url,
- const struct url_data *data)
+/**
+ * Scrolls the tree to make an element visible
+ *
+ * \param y Y coordinate of the element
+ * \param height height of the element
+ * \param data user data assigned to the tree on tree creation
+ */
+void ami_tree_scroll_visible(int y, int height, void *data)
{
- struct node_element *element;
- char buffer[256];
+ ULONG sy, scrollset;
+ struct IBox *bbox;
+ struct treeview_window *twin = data;
- assert(node);
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&sy);
+ GetAttr(SPACE_AreaBox,twin->gadgets[GID_BROWSER],(ULONG *)&bbox);
- element = tree_find_element(node, TREE_ELEMENT_URL);
+ if((y > sy) && ((y + height) < (sy + bbox->Height))) return;
- if (!element)
- return;
- if (data) {
- /* node is linked, update */
- assert(!node->editable);
- if (!data->title)
- urldb_set_url_title(url, url);
-
- if (!data->title)
- return;
-
- node->data.text = data->title;
- } else {
- /* node is not linked, find data */
- assert(node->editable);
- data = urldb_get_url_data(element->text);
- if (!data)
- return;
- }
+ if((y <= sy) || (height > bbox->Height)) scrollset = (ULONG)y;
+ else scrollset = sy + (y + height) - (sy + bbox->Height);
-/* not implemented yet
- if (element) {
- sprintf(buffer, "small_%.3x", ro_content_filetype_from_type(data->type));
- if (ro_gui_wimp_sprite_exists(buffer))
- tree_set_node_sprite(node, buffer, buffer);
- else
- tree_set_node_sprite(node, "small_xxx", "small_xxx");
- }
-*/
-
- element = tree_find_element(node, TREE_ELEMENT_LAST_VISIT);
- if (element) {
- snprintf(buffer, 256, (char *)messages_get("TreeLast"),
- (data->last_visit > 0) ?
- ctime((time_t *)&data->last_visit) :
- (char *)messages_get("TreeUnknown"));
- if (data->last_visit > 0)
- buffer[strlen(buffer) - 1] = '\0';
- free((void *)element->text);
- element->text = (char *)strdup(buffer);
- }
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL,
+ SCROLLER_Top, scrollset,
+ TAG_DONE);
- element = tree_find_element(node, TREE_ELEMENT_VISITS);
- if (element) {
- snprintf(buffer, 256, (char *)messages_get("TreeVisits"),
- data->visits);
- free((void *)element->text);
- element->text = (char *)strdup(buffer);
- }
+ ami_tree_draw(twin);
}
-void tree_resized(struct tree *tree)
+void ami_tree_scroll(struct treeview_window *twin, int sx, int sy)
{
+ int x, y;
+
+ if(!twin) return;
+ if(sx<0) sx=0;
+ if(sy<0) sy=0;
+
+ GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&x);
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&y);
+
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL,
+ SCROLLER_Top, y + sy,
+ TAG_DONE);
+
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL,
+ SCROLLER_Top, x + sx,
+ TAG_DONE);
+
+ ami_tree_draw(twin);
}
-void tree_set_node_sprite_folder(struct node *node)
+
+void ami_tree_scroller_hook(struct Hook *hook,Object *object,struct IntuiMessage *msg)
{
-}
+ ULONG gid,x,y;
+ struct treeview_window *twin = hook->h_Data;
+ struct IntuiWheelData *wheel;
+
+ switch(msg->Class)
+ {
+ case IDCMP_IDCMPUPDATE:
+ gid = GetTagData( GA_ID, 0, msg->IAddress );
+
+ switch( gid )
+ {
+ case OID_HSCROLL:
+ case OID_VSCROLL:
+ ami_tree_draw(twin);
+ break;
+ }
+ break;
+
+ case IDCMP_EXTENDEDMOUSE:
+ if(msg->Code == IMSGCODE_INTUIWHEELDATA)
+ {
+ wheel = (struct IntuiWheelData *)msg->IAddress;
+
+ ami_tree_scroll(twin, (wheel->WheelX * 20), (wheel->WheelY * 20));
+ }
+ break;
+ }
+}
-void tree_set_node_sprite(struct node *node, const char *sprite,
- const char *expanded)
+void ami_tree_menu(struct treeview_window *twin)
{
+ if(twin->menu) return;
+
+ if(twin->menu = AllocVec(sizeof(struct NewMenu) * AMI_TREE_MENU_ITEMS, MEMF_CLEAR))
+ {
+ twin->menu[0].nm_Type = NM_TITLE;
+ twin->menu_name[0] = ami_utf8_easy((char *)messages_get("Tree"));
+ twin->menu[0].nm_Label = twin->menu_name[0];
+
+ twin->menu[1].nm_Type = NM_ITEM;
+ twin->menu_name[1] = ami_utf8_easy((char *)messages_get("TreeExport"));
+ twin->menu[1].nm_Label = twin->menu_name[1];
+ if(twin->type == AMI_TREE_COOKIES)
+ twin->menu[1].nm_Flags = NM_ITEMDISABLED;
+ twin->menu[1].nm_CommKey = "S";
+
+ twin->menu[2].nm_Type = NM_ITEM;
+ twin->menu[2].nm_Label = NM_BARLABEL;
+
+ twin->menu[3].nm_Type = NM_ITEM;
+ twin->menu_name[3] = ami_utf8_easy((char *)messages_get("Expand"));
+ twin->menu[3].nm_Label = twin->menu_name[3];
+
+ twin->menu[4].nm_Type = NM_SUB;
+ twin->menu_name[4] = ami_utf8_easy((char *)messages_get("All"));
+ twin->menu[4].nm_Label = twin->menu_name[4];
+ twin->menu[4].nm_CommKey = "+";
+
+ if(twin->type == AMI_TREE_COOKIES)
+ {
+ twin->menu_name[5] = ami_utf8_easy((char *)messages_get("Domains"));
+ twin->menu_name[6] = ami_utf8_easy((char *)messages_get("Cookies"));
+ }
+ else
+ {
+ twin->menu_name[5] = ami_utf8_easy((char *)messages_get("Folders"));
+ twin->menu_name[6] = ami_utf8_easy((char *)messages_get("Links"));
+ }
+
+ twin->menu[5].nm_Type = NM_SUB;
+ twin->menu[5].nm_Label = twin->menu_name[5]; // tree-specific title
+
+ twin->menu[6].nm_Type = NM_SUB;
+ twin->menu[6].nm_Label = twin->menu_name[6]; // tree-specific title
+
+ twin->menu[7].nm_Type = NM_ITEM;
+ twin->menu_name[7] = ami_utf8_easy((char *)messages_get("Collapse"));
+ twin->menu[7].nm_Label = twin->menu_name[7];
+
+ twin->menu[8].nm_Type = NM_SUB;
+ twin->menu[8].nm_Label = twin->menu_name[4];
+ twin->menu[8].nm_CommKey = "-";
+
+ twin->menu[9].nm_Type = NM_SUB;
+ twin->menu[9].nm_Label = twin->menu_name[5]; // tree-specific title
+
+ twin->menu[10].nm_Type = NM_SUB;
+ twin->menu[10].nm_Label = twin->menu_name[6]; // tree-specific title
+
+ twin->menu[11].nm_Type = NM_ITEM;
+ twin->menu[11].nm_Label = NM_BARLABEL;
+
+ twin->menu[12].nm_Type = NM_ITEM;
+ twin->menu_name[12] = ami_utf8_easy((char *)messages_get("CloseWindow"));
+ twin->menu[12].nm_Label = twin->menu_name[12];
+ twin->menu[12].nm_CommKey = "K";
+
+ twin->menu[13].nm_Type = NM_TITLE;
+ twin->menu_name[13] = ami_utf8_easy((char *)messages_get("Edit"));
+ twin->menu[13].nm_Label = twin->menu_name[13];
+
+ twin->menu[14].nm_Type = NM_ITEM;
+ twin->menu_name[14] = ami_utf8_easy((char *)messages_get("TreeDelete"));
+ twin->menu[14].nm_Label = twin->menu_name[14];
+ twin->menu[14].nm_CommKey = "D";
+
+ twin->menu[15].nm_Type = NM_ITEM;
+ twin->menu[15].nm_Label = NM_BARLABEL;
+
+ twin->menu[16].nm_Type = NM_ITEM;
+ twin->menu_name[16] = ami_utf8_easy((char *)messages_get("SelectAllNS"));
+ twin->menu[16].nm_Label = twin->menu_name[16];
+ twin->menu[16].nm_CommKey = "A";
+
+ twin->menu[17].nm_Type = NM_ITEM;
+ twin->menu_name[17] = ami_utf8_easy((char *)messages_get("ClearNS"));
+ twin->menu[17].nm_Label = twin->menu_name[17];
+ twin->menu[17].nm_CommKey = "Z";
+
+ twin->menu[18].nm_Type = NM_END;
+ }
}
-void ami_open_tree(struct tree *tree,int type)
+void ami_tree_open(struct treeview_window *twin,int type)
{
- struct treeview_window *twin;
BOOL msel = TRUE,nothl = TRUE,launchdisable=FALSE;
static WORD gen=0;
char *wintitle;
char folderclosed[100],folderopen[100],item[100];
- if(tree->handle)
+ if(twin->win)
{
- twin = (struct treeview_window *)tree->handle;
WindowToFront(twin->win);
ActivateWindow(twin->win);
return;
}
- twin = AllocVec(sizeof(struct treeview_window),MEMF_PRIVATE | MEMF_CLEAR);
- twin->listbrowser_list = AllocVec(sizeof(struct List),MEMF_PRIVATE | MEMF_CLEAR);
+ twin->type = type;
- static struct ColumnInfo columninfo[] =
- {
- { 80,"Name", CIF_DRAGGABLE | CIF_SORTABLE},
- { 20,"URL", CIF_DRAGGABLE },
-// { 5,"Visits", CIF_DRAGGABLE },
- { -1, (STRPTR)~0, -1 }
- };
-
- if(tree->single_selection) msel = FALSE;
-
- ami_get_theme_filename(&folderclosed,"theme_list_folder_closed");
- ami_get_theme_filename(&folderopen,"theme_list_folder_open");
-
- switch(type)
+ switch(twin->type)
{
case AMI_TREE_HOTLIST:
nothl = FALSE;
wintitle = (char *)messages_get("Hotlist");
- ami_get_theme_filename(&item,"theme_list_bookmark");
break;
case AMI_TREE_COOKIES:
nothl = TRUE;
launchdisable=TRUE;
wintitle = (char *)messages_get("Cookies");
- ami_get_theme_filename(&item,"theme_list_cookie");
break;
case AMI_TREE_HISTORY:
nothl = TRUE;
wintitle = (char *)messages_get("GlobalHistory");
- ami_get_theme_filename(&item,"theme_list_history");
break;
case AMI_TREE_SSLCERT:
nothl = TRUE;
wintitle = (char *)messages_get("SSLCerts");
- ami_get_theme_filename(&item,"theme_list_sslcert");
break;
}
- NewList(twin->listbrowser_list);
+ twin->scrollerhook.h_Entry = (void *)ami_tree_scroller_hook;
+ twin->scrollerhook.h_Data = twin;
- tree->handle = (void *)twin;
- twin->tree = tree;
- ami_add_elements(twin,twin->tree->root,&gen);
+ ami_init_layers(&twin->globals, scrn->Width, scrn->Height);
+ ami_tree_menu(twin);
- twin->objects[OID_MAIN] = WindowObject,
+ if(type == AMI_TREE_SSLCERT)
+ {
+ twin->objects[OID_MAIN] = WindowObject,
WA_ScreenTitle,nsscreentitle,
WA_Title,wintitle,
WA_Activate, TRUE,
@@ -259,43 +435,77 @@ void ami_open_tree(struct tree *tree,int type)
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_SizeGadget, TRUE,
+ WA_Height, scrn->Height / 2,
WA_CustomScreen,scrn,
+ WA_ReportMouse,TRUE,
+ WA_IDCMP,IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
+ IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
+ IDCMP_EXTENDEDMOUSE,
+ WINDOW_HorizProp,1,
+ WINDOW_VertProp,1,
+ WINDOW_IDCMPHook,&twin->scrollerhook,
+ WINDOW_IDCMPHookBits,IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE,
WINDOW_SharedPort,sport,
WINDOW_UserData,twin,
- WINDOW_IconifyGadget, TRUE,
+ /* WINDOW_NewMenu, twin->menu, -> No menu for SSL Cert */
+ WINDOW_IconifyGadget, FALSE,
WINDOW_Position, WPOS_CENTERSCREEN,
WINDOW_ParentGroup, twin->gadgets[GID_MAIN] = VGroupObject,
- LAYOUT_AddChild, twin->gadgets[GID_TREEBROWSER] = ListBrowserObject,
- GA_ID, GID_TREEBROWSER,
- GA_RelVerify, TRUE,
- GA_ReadOnly,FALSE,
- LISTBROWSER_ColumnInfo, &columninfo,
-// LISTBROWSER_ColumnTitles, TRUE,
- LISTBROWSER_Hierarchical,TRUE,
- LISTBROWSER_Editable,TRUE,
-// LISTBROWSER_TitleClickable,TRUE,
- LISTBROWSER_AutoFit, TRUE,
- LISTBROWSER_HorizontalProp, TRUE,
- LISTBROWSER_Labels, twin->listbrowser_list,
-// LISTBROWSER_MultiSelect,msel,
- LISTBROWSER_ShowSelected,TRUE,
- LISTBROWSER_ShowImage,BitMapObject,
- BITMAP_SourceFile,folderclosed,
- BITMAP_Screen,scrn,
- BITMAP_Masking,TRUE,
- BitMapEnd,
- LISTBROWSER_HideImage,BitMapObject,
- BITMAP_SourceFile,folderopen,
- BITMAP_Screen,scrn,
- BITMAP_Masking,TRUE,
- BitMapEnd,
- LISTBROWSER_LeafImage,BitMapObject,
- BITMAP_SourceFile,item,
- BITMAP_Screen,scrn,
- BITMAP_Masking,TRUE,
- BitMapEnd,
- ListBrowserEnd,
- CHILD_NominalSize,TRUE,
+ LAYOUT_AddImage, LabelObject,
+ LABEL_Text, messages_get("SSLError"),
+ LabelEnd,
+ LAYOUT_AddChild, twin->gadgets[GID_BROWSER] = SpaceObject,
+ GA_ID, GID_BROWSER,
+ SPACE_Transparent,TRUE,
+ SPACE_BevelStyle, BVS_DISPLAY,
+ SpaceEnd,
+ LAYOUT_AddChild, HGroupObject,
+ LAYOUT_AddChild, twin->gadgets[GID_OPEN] = ButtonObject,
+ GA_ID,GID_OPEN,
+ GA_Text,messages_get("Accept"),
+ GA_RelVerify,TRUE,
+ ButtonEnd,
+ LAYOUT_AddChild, twin->gadgets[GID_CANCEL] = ButtonObject,
+ GA_ID,GID_CANCEL,
+ GA_Text,messages_get("Reject"),
+ GA_RelVerify,TRUE,
+ ButtonEnd,
+ EndGroup,
+ CHILD_WeightedHeight,0,
+ EndGroup,
+ EndWindow;
+ }
+ else
+ {
+ twin->objects[OID_MAIN] = WindowObject,
+ WA_ScreenTitle,nsscreentitle,
+ WA_Title,wintitle,
+ WA_Activate, TRUE,
+ WA_DepthGadget, TRUE,
+ WA_DragBar, TRUE,
+ WA_CloseGadget, TRUE,
+ WA_SizeGadget, TRUE,
+ WA_Height, scrn->Height / 2,
+ WA_CustomScreen,scrn,
+ WA_ReportMouse,TRUE,
+ WA_IDCMP,IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
+ IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
+ IDCMP_EXTENDEDMOUSE,
+ WINDOW_HorizProp,1,
+ WINDOW_VertProp,1,
+ WINDOW_IDCMPHook,&twin->scrollerhook,
+ WINDOW_IDCMPHookBits,IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE,
+ WINDOW_SharedPort,sport,
+ WINDOW_UserData,twin,
+ WINDOW_NewMenu, twin->menu,
+ WINDOW_IconifyGadget, FALSE,
+ WINDOW_Position, WPOS_CENTERSCREEN,
+ WINDOW_ParentGroup, twin->gadgets[GID_MAIN] = VGroupObject,
+ LAYOUT_AddChild, twin->gadgets[GID_BROWSER] = SpaceObject,
+ GA_ID, GID_BROWSER,
+ SPACE_Transparent,TRUE,
+ SPACE_BevelStyle, BVS_DISPLAY,
+ SpaceEnd,
LAYOUT_AddChild, HGroupObject,
LAYOUT_AddChild, twin->gadgets[GID_OPEN] = ButtonObject,
GA_ID,GID_OPEN,
@@ -315,24 +525,6 @@ void ami_open_tree(struct tree *tree,int type)
GA_RelVerify,TRUE,
GA_Disabled,nothl,
ButtonEnd,
- LAYOUT_AddChild, twin->gadgets[GID_LEFT] = ButtonObject,
- GA_ID,GID_LEFT,
- BUTTON_AutoButton,BAG_LFARROW,
- GA_RelVerify,TRUE,
- GA_Disabled,nothl, //(!tree->movable),
- ButtonEnd,
- LAYOUT_AddChild, twin->gadgets[GID_UP] = ButtonObject,
- GA_ID,GID_UP,
- BUTTON_AutoButton,BAG_UPARROW,
- GA_RelVerify,TRUE,
- GA_Disabled,nothl, //(!tree->movable),
- ButtonEnd,
- LAYOUT_AddChild, twin->gadgets[GID_DOWN] = ButtonObject,
- GA_ID,GID_DOWN,
- BUTTON_AutoButton,BAG_DNARROW,
- GA_RelVerify,TRUE,
- GA_Disabled,nothl, //(!tree->movable),
- ButtonEnd,
LAYOUT_AddChild, twin->gadgets[GID_DEL] = ButtonObject,
GA_ID,GID_DEL,
GA_Text,messages_get("TreeDelete"),
@@ -342,161 +534,89 @@ void ami_open_tree(struct tree *tree,int type)
CHILD_WeightedHeight,0,
EndGroup,
EndWindow;
+ }
twin->win = (struct Window *)RA_OpenWindow(twin->objects[OID_MAIN]);
- twin->node = AddObject(window_list,AMINS_TVWINDOW);
- twin->node->objstruct = twin;
-}
-
-/**
- * Launches a node using all known methods.
- *
- * \param node the node to launch
- * \return whether the node could be launched
- */
-bool ami_tree_launch_node(struct tree *tree, struct node *node)
-{
- struct node_element *element;
+ GetAttr(WINDOW_HorizObject, twin->objects[OID_MAIN],
+ (ULONG *)&twin->objects[OID_HSCROLL]);
+ GetAttr(WINDOW_VertObject, twin->objects[OID_MAIN],
+ (ULONG *)&twin->objects[OID_VSCROLL]);
- assert(node);
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_VSCROLL], twin->win, NULL,
+ GA_ID,OID_VSCROLL,
+ ICA_TARGET,ICTARGET_IDCMP,
+ TAG_DONE);
- element = tree_find_element(node, TREE_ELEMENT_URL);
- if (element) {
- browser_window_create(element->text, NULL, 0, true, false);
- return true;
- }
+ RefreshSetGadgetAttrs((APTR)twin->objects[OID_HSCROLL], twin->win, NULL,
+ GA_ID,OID_HSCROLL,
+ ICA_TARGET,ICTARGET_IDCMP,
+ TAG_DONE);
-/* not implemented yet
- element = tree_find_element(node, TREE_ELEMENT_SSL);
- if (element) {
- ro_gui_cert_open(tree, node);
- return true;
- }
-*/
+ twin->node = AddObject(window_list,AMINS_TVWINDOW);
+ twin->node->objstruct = twin;
- return false;
+ ami_tree_resized(twin->tree, twin->max_width, twin->max_height, twin);
+ tree_set_redraw(twin->tree, true);
+ ami_tree_draw(twin);
}
void ami_tree_close(struct treeview_window *twin)
{
- twin->tree->handle = 0;
- DisposeObject(twin->objects[OID_MAIN]);
- FreeListBrowserList(twin->listbrowser_list);
- FreeVec(twin->listbrowser_list);
- //free_browserlist(twin->listbrowser_list);
- DelObject(twin->node);
-}
-
-void free_browserlist(struct List *list)
-{
- struct Node *node, *nextnode;
-
- if(IsListEmpty(list)) return;
+ int i;
- node = GetHead(list);
+ tree_set_redraw(twin->tree, false);
+ twin->win = NULL;
+ DisposeObject(twin->objects[OID_MAIN]);
+ DelObjectNoFree(twin->node);
+ ami_free_layers(&twin->globals);
- do
- {
- nextnode = GetSucc(node);
-// FreeVec(node->ln_Name);
- FreeListBrowserNode(node);
- } while(node = nextnode);
+ for(i=0;i<AMI_TREE_MENU_ITEMS;i++)
+ {
+ if(twin->menu_name[i] && (twin->menu_name[i] != NM_BARLABEL)) ami_utf8_free(twin->menu_name[i]);
+ }
+ FreeVec(twin->menu);
+ twin->menu = NULL;
+ if(twin->type == AMI_TREE_SSLCERT) ami_ssl_free(twin);
}
-void ami_add_elements(struct treeview_window *twin,struct node *root,WORD *gen)
+void ami_tree_update_quals(struct treeview_window *twin)
{
- struct Node *lbnode;
- struct tree *tree = twin->tree;
- struct node *tempnode;
- int generation=1;
- BOOL edit = FALSE;
- struct node_element *element=NULL,*element2=NULL,*element3=NULL;
- struct node *node;
- ULONG flags = 0;
- STRPTR text1 = "",text2 = "",text3 = "";
-
- *gen = *gen + 1;
- for (node = root; node; node = node->next)
- {
- element = tree_find_element(node, TREE_ELEMENT_NAME);
- if(!element) element = tree_find_element(node, TREE_ELEMENT_TITLE);
- if(!element) element = tree_find_element(node, TREE_ELEMENT_SSL);
- if(element && element->text)
- {
- text1 = (char *)element->text;
- }
+ uint32 quals = 0;
-/* Really, the second column needs axing - relevant data should appear in an
-area below the listview when items are selected */
+ GetAttr(WINDOW_Qualifier, twin->objects[OID_MAIN], (uint32 *)&quals);
- element2 = tree_find_element(node, TREE_ELEMENT_URL);
- if(!element2) element2 = tree_find_element(node, TREE_ELEMENT_VALUE);
- if(!element2) element2 = tree_find_element(node, TREE_ELEMENT_COMMENT);
+ twin->key_state = 0;
- if(element2 && element2->text)
- {
- text2 = (char *)element2->text;
- }
- else
- {
- text2 = "";
- }
+ if((quals & IEQUALIFIER_LSHIFT) || (quals & IEQUALIFIER_RSHIFT))
+ {
+ twin->key_state |= BROWSER_MOUSE_MOD_1;
+ }
-// element = tree_find_element(node, TREE_ELEMENT_VISITS);
-
- flags = 0;
- /*if(node->expanded) */ flags = LBFLG_SHOWCHILDREN;
- if(node->folder) flags |= LBFLG_HASCHILDREN;
- if(!node->parent) flags |= LBFLG_HIDDEN;
-
- switch (element->type) {
- case NODE_ELEMENT_TEXT_PLUS_SPRITE:
- case NODE_ELEMENT_TEXT:
- if (lbnode = AllocListBrowserNode(3,
- LBNA_UserData,node,
- LBNA_Generation,*gen - 1,
- LBNA_Selected,node->selected,
- LBNA_Flags,flags,
- LBNA_Column, 0,
- LBNCA_CopyText,TRUE,
- LBNCA_MaxChars,256,
- LBNCA_Text, text1,
- LBNCA_Editable,node->editable,
- LBNA_Column, 1,
- LBNCA_CopyText,TRUE,
- LBNCA_MaxChars,256,
- LBNCA_Text, text2,
- LBNCA_Editable,FALSE,
- TAG_DONE))
- {
- AddTail(twin->listbrowser_list, lbnode);
- if(node == selectednode2) selectednode = lbnode;
- }
- break;
- }
+ if(quals & IEQUALIFIER_CONTROL)
+ {
+ twin->key_state |= BROWSER_MOUSE_MOD_2;
+ }
- if (node->child)
- {
- ami_add_elements(twin,node->child,gen);
- }
+ if((quals & IEQUALIFIER_LALT) || (quals & IEQUALIFIER_RALT))
+ {
+ twin->key_state |= BROWSER_MOUSE_MOD_3;
}
- *gen = *gen - 1;
}
BOOL ami_tree_event(struct treeview_window *twin)
{
/* return TRUE if window destroyed */
- ULONG class,result,relevent = 0;
- ULONG column;
+ ULONG class,result,storage = 0;
uint16 code;
struct MenuItem *item;
- struct node *treenode;
- struct Node *lbnode;
- struct node_element *element;
- char *text;
-// ULONG editcols[] = {TREE_ELEMENT_TITLE,TREE_ELEMENT_URL};
- static WORD gen=0;
+ ULONG menunum=0,itemnum=0,subnum=0;
+ int xs, ys, x, y;
+ struct IBox *bbox;
+ struct timeval curtime;
+ struct InputEvent *ie;
+ int nskey;
+ char fname[1024];
while((result = RA_HandleInput(twin->objects[OID_MAIN],&code)) != WMHI_LASTMSG)
{
@@ -505,126 +625,386 @@ BOOL ami_tree_event(struct treeview_window *twin)
case WMHI_GADGETUP:
switch(result & WMHI_GADGETMASK)
{
- case GID_TREEBROWSER:
- GetAttrs(twin->gadgets[GID_TREEBROWSER],
- LISTBROWSER_RelEvent,&relevent,
- TAG_DONE);
-
- switch(relevent)
+ case GID_OPEN:
+ if(twin->type == AMI_TREE_SSLCERT)
{
- case LBRE_DOUBLECLICK:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- ami_tree_launch_node(twin->tree,treenode);
- break;
-
- case LBRE_EDIT:
- GetAttrs(twin->gadgets[GID_TREEBROWSER],
- LISTBROWSER_SelectedNode,(ULONG *)&lbnode,
-// LISTBROWSER_RelColumn,(ULONG *)&column,
- TAG_DONE);
-
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
-
- element = tree_find_element(treenode,TREE_ELEMENT_TITLE);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_Column,column,
- LBNCA_Text,(ULONG *)&text,
- TAG_DONE);
- element->text = (char *)strdup(text);
- tree_handle_node_element_changed(twin->tree, element);
- break;
-
- case LBRE_HIDECHILDREN:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- tree_set_node_expanded(twin->tree, treenode, false);
- break;
-
- case LBRE_SHOWCHILDREN:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- tree_set_node_expanded(twin->tree, treenode, true);
- break;
+ sslcert_accept(twin->ssl_data);
+ ami_tree_close(twin);
+ return TRUE;
}
+ else tree_launch_selected(twin->tree);
break;
- case GID_OPEN:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- ami_tree_launch_node(twin->tree,treenode);
+ case GID_CANCEL:
+ sslcert_reject(twin->ssl_data);
+ ami_tree_close(twin);
+ return TRUE;
break;
case GID_NEWF:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- if(lbnode)
- {
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- }
- else
- {
- treenode = twin->tree->root;
- }
-
- tree_create_folder_node(treenode,(char *)messages_get("TreeNewFolder"));
-
- ami_recreate_listbrowser(twin);
+ hotlist_add_folder();
break;
case GID_NEWB:
- ami_new_bookmark(twin);
+ hotlist_add_entry();
break;
- case GID_UP:
- ami_move_node(twin,AMI_MOVE_UP);
+ case GID_DEL:
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_delete_selected();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_delete_selected();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_delete_selected();
+ break;
+ }
break;
+ }
+ break;
- case GID_DOWN:
- ami_move_node(twin,AMI_MOVE_DOWN);
- break;
+ case WMHI_MOUSEMOVE:
+ GetAttr(SPACE_AreaBox, twin->gadgets[GID_BROWSER], (ULONG *)&bbox);
- case GID_LEFT:
- ami_move_node(twin,AMI_MOVE_OUT);
- break;
+ GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&xs);
+ x = twin->win->MouseX - bbox->Left + xs;
- case GID_DEL:
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- tree_delete_node(twin->tree, treenode, false);
-/* We are recreating the list from scratch as there is no obvious easy way
- to delete children from a listbrowser list */
- ami_recreate_listbrowser(twin);
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&ys);
+ y = twin->win->MouseY - bbox->Top + ys;
+
+ if((x >= xs) && (y >= ys) && (x < bbox->Width + xs) &&
+ (y < bbox->Height + ys))
+ {
+ ami_tree_update_quals(twin);
+
+ if(twin->mouse_state & BROWSER_MOUSE_PRESS_1)
+ {
+ tree_mouse_action(twin->tree,
+ BROWSER_MOUSE_DRAG_1 | twin->key_state, x, y);
+ twin->mouse_state = BROWSER_MOUSE_HOLDING_1 |
+ BROWSER_MOUSE_DRAG_ON;
+ if(twin->drag_x == 0) twin->drag_x = x;
+ if(twin->drag_y == 0) twin->drag_y = y;
+
+ }
+ else if(twin->mouse_state & BROWSER_MOUSE_PRESS_2)
+ {
+ tree_mouse_action(twin->tree,
+ BROWSER_MOUSE_DRAG_2 | twin->key_state, x, y);
+ twin->mouse_state = BROWSER_MOUSE_HOLDING_2 |
+ BROWSER_MOUSE_DRAG_ON;
+ if(twin->drag_x == 0) twin->drag_x = x;
+ if(twin->drag_y == 0) twin->drag_y = y;
+ }
+ else
+ {
+ tree_mouse_action(twin->tree,
+ twin->mouse_state | twin->key_state, x, y);
+ }
+ }
+ twin->lastclick.tv_sec = 0;
+ twin->lastclick.tv_usec = 0;
+ break;
+
+ case WMHI_MOUSEBUTTONS:
+ GetAttr(SPACE_AreaBox, twin->gadgets[GID_BROWSER], (ULONG *)&bbox);
+ GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&xs);
+ x = twin->win->MouseX - bbox->Left + xs;
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&ys);
+ y = twin->win->MouseY - bbox->Top + ys;
+
+ ami_tree_update_quals(twin);
+
+ if((x >= xs) && (y >= ys) && (x < bbox->Width + xs) &&
+ (y < bbox->Height + ys))
+ {
+ switch(code)
+ {
+ case SELECTDOWN:
+ twin->mouse_state = BROWSER_MOUSE_PRESS_1;
+ break;
+ case MIDDLEDOWN:
+ twin->mouse_state = BROWSER_MOUSE_PRESS_2;
+ break;
+ }
+ tree_mouse_action(twin->tree,
+ twin->mouse_state | twin->key_state, x, y);
+ }
+
+ if(x < xs) x = xs;
+ if(y < ys) y = ys;
+ if(x >= bbox->Width + xs) x = bbox->Width + xs - 1;
+ if(y >= bbox->Height + ys) y = bbox->Height + ys - 1;
+
+ switch(code)
+ {
+ case SELECTUP:
+ if(twin->mouse_state & BROWSER_MOUSE_PRESS_1)
+ {
+ CurrentTime(&curtime.tv_sec,&curtime.tv_usec);
+
+ twin->mouse_state = BROWSER_MOUSE_CLICK_1;
+
+ if(twin->lastclick.tv_sec)
+ {
+ if(DoubleClick(twin->lastclick.tv_sec,
+ twin->lastclick.tv_usec,
+ curtime.tv_sec, curtime.tv_usec))
+ twin->mouse_state |= BROWSER_MOUSE_DOUBLE_CLICK;
+ }
+ tree_mouse_action(twin->tree,
+ twin->mouse_state | twin->key_state, x, y);
+
+ if(twin->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK)
+ {
+ twin->lastclick.tv_sec = 0;
+ twin->lastclick.tv_usec = 0;
+ }
+ else
+ {
+ twin->lastclick.tv_sec = curtime.tv_sec;
+ twin->lastclick.tv_usec = curtime.tv_usec;
+ }
+ }
+ else
+ {
+ tree_drag_end(twin->tree, twin->mouse_state,
+ twin->drag_x, twin->drag_y, x, y);
+ }
+ twin->mouse_state=0;
+ twin->drag_x = 0;
+ twin->drag_y = 0;
+ break;
+ case MIDDLEUP:
+ if(twin->mouse_state & BROWSER_MOUSE_PRESS_2)
+ {
+ tree_mouse_action(twin->tree,
+ BROWSER_MOUSE_CLICK_2 | twin->key_state, x, y);
+ }
+ else
+ {
+ tree_drag_end(twin->tree, twin->mouse_state,
+ twin->drag_x, twin->drag_y, x, y);
+ }
+ twin->mouse_state=0;
+ twin->drag_x = 0;
+ twin->drag_y = 0;
break;
}
break;
-/* no menus yet, copied in as will probably need it later
+ case WMHI_RAWKEY:
+ storage = result & WMHI_GADGETMASK;
+
+ GetAttr(WINDOW_InputEvent,twin->objects[OID_MAIN],(ULONG *)&ie);
+ nskey = ami_key_to_nskey(storage, ie);
+ tree_keypress(twin->tree, nskey);
+ break;
+
case WMHI_MENUPICK:
- item = ItemAddress(gwin->win->MenuStrip,code);
+ item = ItemAddress(twin->win->MenuStrip,code);
while (code != MENUNULL)
{
- ami_menupick(code,gwin);
+ menunum = MENUNUM(code);
+ itemnum = ITEMNUM(code);
+ subnum = SUBNUM(code);
+
+ switch(menunum)
+ {
+ case 0: // tree
+ switch(itemnum)
+ {
+ case 0: // export
+ if(AslRequestTags(savereq,
+ ASLFR_TitleText,messages_get("NetSurf"),
+ ASLFR_Screen,scrn,
+ ASLFR_InitialFile,"tree_export.html",
+ TAG_DONE))
+ {
+ strlcpy(&fname,savereq->fr_Drawer,1024);
+ AddPart(fname,savereq->fr_File,1024);
+ ami_update_pointer(twin->win,GUI_POINTER_WAIT);
+ if(twin->type == AMI_TREE_HISTORY)
+ history_global_export(fname);
+ else if(twin->type == AMI_TREE_HOTLIST)
+ hotlist_export(fname);
+ ami_update_pointer(twin->win,GUI_POINTER_DEFAULT);
+ }
+ break;
+
+ case 2: // expand
+ switch(subnum)
+ {
+ case 0: // all
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_expand_all();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_expand_all();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_expand_all();
+ break;
+ }
+ break;
+
+ case 1: // lev 1
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_expand_directories();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_expand_domains();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_expand_directories();
+ break;
+ }
+ break;
+
+ case 2: // lev 2
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_expand_addresses();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_expand_cookies();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_expand_addresses();
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 3: // collapse
+ switch(subnum)
+ {
+ case 0: // all
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_collapse_all();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_collapse_all();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_collapse_all();
+ break;
+ }
+ break;
+
+ case 1: // lev 1
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_collapse_directories();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_collapse_domains();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_collapse_directories();
+ break;
+ }
+ break;
+
+ case 2: // lev 2
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_collapse_addresses();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_collapse_cookies();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_collapse_addresses();
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 5: // close
+ ami_tree_close(twin);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case 1: // edit
+ switch(itemnum)
+ {
+ case 0: // delete
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_delete_selected();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_delete_selected();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_delete_selected();
+ break;
+ }
+ break;
+
+ case 2: // select all
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_select_all();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_select_all();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_select_all();
+ break;
+ }
+ break;
+
+ case 3: // clear
+ switch(twin->type)
+ {
+ case AMI_TREE_HISTORY:
+ history_global_clear_selection();
+ break;
+ case AMI_TREE_COOKIES:
+ cookies_clear_selection();
+ break;
+ case AMI_TREE_HOTLIST:
+ hotlist_clear_selection();
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
if(win_destroyed) break;
code = item->NextSelect;
}
break;
-*/
+
+ case WMHI_NEWSIZE:
+ ami_tree_draw(twin);
+ break;
case WMHI_CLOSEWINDOW:
+ if(twin->type == AMI_TREE_SSLCERT)
+ sslcert_reject(twin->ssl_data);
ami_tree_close(twin);
return TRUE;
break;
@@ -633,103 +1013,44 @@ BOOL ami_tree_event(struct treeview_window *twin)
return FALSE;
}
-void ami_move_node(struct treeview_window *twin,int move)
+void ami_tree_draw(struct treeview_window *twin)
{
- struct Node *lbnode = NULL;
- struct node *treenode,*moveto;
- bool before;
-
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
-
- if(!lbnode) return;
-
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
-// for multiselects? LBNA_Selected,(BOOL *)&sel,
- TAG_DONE);
-
- selectednode2 = treenode;
+ struct IBox *bbox;
+ int x, y;
- tree_set_node_selected(twin->tree,twin->tree->root,false);
- tree_set_node_selected(twin->tree,treenode,true);
-
- switch(move)
- {
- case AMI_MOVE_UP:
- moveto = treenode->previous;
- before = true;
- break;
-
- case AMI_MOVE_DOWN:
- moveto = treenode->next;
- before = false;
- break;
-
- case AMI_MOVE_OUT:
- moveto = treenode->parent->previous;
- before = false;
- break;
- }
+ if(!twin) return;
- if(!moveto) return;
+ GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&x);
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&y);
+ GetAttr(SPACE_AreaBox,twin->gadgets[GID_BROWSER],(ULONG *)&bbox);
- tree_delink_node(treenode);
- //tree_move_selected_nodes(twin->tree,moveto,before);
- tree_link_node(moveto,treenode,before);
- ami_recreate_listbrowser(twin);
- selectednode2 = NULL;
+ ami_tree_redraw_request(x, y, bbox->Width, bbox->Height, twin);
}
-void ami_new_bookmark(struct treeview_window *twin)
+void ami_tree_redraw_request(int x, int y, int width, int height, void *data)
{
- const struct url_data *data;
- struct Node *lbnode;
- struct node *treenode;
- char *url,*title;
+ struct treeview_window *twin = data;
+ struct IBox *bbox;
+ int pos_x, pos_y;
- GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode);
- if(lbnode)
- {
- GetListBrowserNodeAttrs(lbnode,
- LBNA_UserData,(ULONG *)&treenode,
- TAG_DONE);
- }
- else
- {
- treenode = twin->tree->root;
- }
+ if(!twin->win) return;
+// if(tree_get_redraw(twin->tree) == false) return;
- url = (char *)strdup("http://www.netsurf-browser.org");
+ ami_update_pointer(twin->win, GUI_POINTER_WAIT);
+ glob = &twin->globals;
- data = urldb_get_url_data(url);
- if (!data)
- {
- urldb_add_url(url);
- urldb_set_url_persistence(url,true);
- data = urldb_get_url_data(url);
- }
+ GetAttr(SPACE_AreaBox,twin->gadgets[GID_BROWSER],(ULONG *)&bbox);
+ GetAttr(SCROLLER_Top, twin->objects[OID_HSCROLL], (ULONG *)&pos_x);
+ GetAttr(SCROLLER_Top, twin->objects[OID_VSCROLL], (ULONG *)&pos_y);
- if (data)
- {
- title = data->title;
- tree_create_URL_node(treenode,url,data,title);
- ami_recreate_listbrowser(twin);
- }
-}
-
-void ami_recreate_listbrowser(struct treeview_window *twin)
-{
- static WORD gen=0;
+ if(x - pos_x + width > bbox->Width) width = bbox->Width - (x - pos_x);
+ if(y - pos_y + height > bbox->Height) height = bbox->Height - (y - pos_y);
- SetGadgetAttrs(twin->gadgets[GID_TREEBROWSER],twin->win,NULL,
- LISTBROWSER_Labels,~0,
- TAG_DONE);
+ tree_draw(twin->tree, -pos_x, -pos_y, x, y, width, height);
- FreeListBrowserList(twin->listbrowser_list);
- ami_add_elements(twin,twin->tree->root,&gen);
+ BltBitMapRastPort(twin->globals.bm, x - pos_x, y - pos_y, twin->win->RPort,
+ bbox->Left + x - pos_x, bbox->Top + y - pos_y, width, height, 0x0C0);
- RefreshSetGadgetAttrs(twin->gadgets[GID_TREEBROWSER],twin->win,NULL,
- LISTBROWSER_Labels,twin->listbrowser_list,
- LISTBROWSER_SelectedNode,selectednode,
- TAG_DONE);
+ ami_update_pointer(twin->win, GUI_POINTER_DEFAULT);
+ glob = &browserglob;
}
diff --git a/amiga/tree.h b/amiga/tree.h
index 4129df1d2..315938d0d 100755
--- a/amiga/tree.h
+++ b/amiga/tree.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008, 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -22,15 +22,10 @@
#include <exec/types.h>
#include <intuition/classusr.h>
#include "amiga/gui.h"
+#include "desktop/tree.h"
+#include "desktop/sslcert.h"
-struct treeview_window {
- struct nsObject *node;
- struct Window *win;
- Object *objects[OID_LAST];
- struct Gadget *gadgets[GID_LAST];
- struct tree *tree;
- struct List *listbrowser_list;
-};
+struct treeview_window;
enum
{
@@ -40,15 +35,15 @@ enum
AMI_TREE_SSLCERT
};
-enum
-{
- AMI_MOVE_UP,
- AMI_MOVE_DOWN,
- AMI_MOVE_OUT
-};
+struct treeview_window *ami_tree_create(uint8 flags,
+ struct sslcert_session_data *ssl_data);
+void ami_tree_destroy(struct treeview_window *twin);
+struct tree *ami_tree_get_tree(struct treeview_window *twin);
-void ami_open_tree(struct tree *tree,int type);
+void ami_tree_open(struct treeview_window *twin,int type);
void ami_tree_close(struct treeview_window *twin);
BOOL ami_tree_event(struct treeview_window *twin);
-void ami_recreate_listbrowser(struct treeview_window *twin);
+
+extern const struct treeview_table ami_tree_callbacks;
+
#endif
diff --git a/beos/beos_bitmap.cpp b/beos/beos_bitmap.cpp
index 881ffe727..5df1fce38 100644
--- a/beos/beos_bitmap.cpp
+++ b/beos/beos_bitmap.cpp
@@ -312,6 +312,16 @@ void bitmap_set_suspendable(void *vbitmap, void *private_word,
struct bitmap *bitmap = (struct bitmap *)vbitmap;
}
+int bitmap_get_width(void *vbitmap){
+ struct bitmap *bitmap = (struct bitmap *)vbitmap;
+ return bitmap->primary->Bounds().Width() + 1;
+}
+
+int bitmap_get_height(void *vbitmap){
+ struct bitmap *bitmap = (struct bitmap *)vbitmap;
+ return bitmap->primary->Bounds().Height() + 1;
+}
+
static BBitmap *
nsbeos_bitmap_generate_pretile(BBitmap *primary, int repeat_x, int repeat_y)
{
diff --git a/beos/beos_gui.cpp b/beos/beos_gui.cpp
index d8cb4bbb2..c06b0c7fc 100644
--- a/beos/beos_gui.cpp
+++ b/beos/beos_gui.cpp
@@ -74,7 +74,6 @@ extern "C" {
#include "beos/beos_window.h"
#include "beos/options.h"
#include "beos/beos_throbber.h"
-#include "beos/beos_history.h"
#include "beos/beos_filetype.h"
//#include "beos/beos_download.h"
#include "beos/beos_schedule.h"
@@ -641,7 +640,6 @@ void gui_init(int argc, char** argv)
urldb_load(option_url_file);
urldb_load_cookies(option_cookie_file);
- nsbeos_history_init();
//nsbeos_download_initialise();
if (!replicated)
@@ -1059,11 +1057,6 @@ void die(const char * const error)
exit(EXIT_FAILURE);
}
-
-void hotlist_visited(hlcache_handle *content)
-{
-}
-
void gui_cert_verify(const char *url, const struct ssl_cert_info *certs,
unsigned long num, nserror (*cb)(bool proceed, void *pw),
void *cbpw)
diff --git a/beos/beos_history.cpp b/beos/beos_history.cpp
deleted file mode 100644
index b35d6d075..000000000
--- a/beos/beos_history.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2008 François Revol <mmu_man@users.sourceforge.net>
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
- *
- * 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/>.
- */
-
-#define __STDBOOL_H__ 1
-extern "C" {
-#include "utils/log.h"
-#include "content/urldb.h"
-}
-
-#include "beos/beos_history.h"
-#include "beos/beos_gui.h"
-#include "beos/beos_window.h"
-
-#include <View.h>
-#include <Window.h>
-
-
-enum
-{
- COL_TITLE = 0,
- COL_ADDRESS,
- COL_LASTVISIT,
- COL_TOTALVISITS,
- COL_THUMBNAIL,
- COL_NCOLS
-};
-
-BWindow *wndHistory;
-#warning XXX
-#if 0 /* GTK */
-static GtkTreeView *treeview;
-static GtkTreeStore *history_tree;
-static GtkTreeSelection *selection;
-
-static bool nsgtk_history_add_internal(const char *, const struct url_data *);
-static void nsgtk_history_selection_changed(GtkTreeSelection *, gpointer);
-#endif
-
-void nsbeos_history_init(void)
-{
-#warning XXX
-#if 0 /* GTK */
- GtkCellRenderer *renderer;
-
- wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeWindows,
- "wndHistory"));
- treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeWindows,
- "treeHistory"));
- history_tree = gtk_tree_store_new(COL_NCOLS,
- G_TYPE_STRING, /* title */
- G_TYPE_STRING, /* address */
- G_TYPE_STRING, /* last visit */
- G_TYPE_INT, /* nr. visits */
- GDK_TYPE_PIXBUF); /* thumbnail */
-
- selection = gtk_tree_view_get_selection(treeview);
- gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
- g_signal_connect(G_OBJECT(selection), "changed",
- G_CALLBACK(nsgtk_history_selection_changed), NULL);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(treeview, -1, "Title",
- renderer,
- "text",
- COL_TITLE,
- NULL);
-
- gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(history_tree));
-
-#endif
- nsbeos_history_update();
-}
-
-void nsbeos_history_update(void)
-{
-#warning XXX
-#if 0 /* GTK */
- gtk_tree_store_clear(history_tree);
- urldb_iterate_entries(nsgtk_history_add_internal);
-#endif
-}
-
-bool nsbeos_history_add_internal(const char *url, const struct url_data *data)
-{
-#warning XXX
-#if 0 /* GTK */
- GtkTreeIter iter;
-
- if (data->visits > 0)
- {
- gtk_tree_store_append(history_tree, &iter, NULL);
- gtk_tree_store_set(history_tree, &iter,
- COL_TITLE, data->title,
- COL_ADDRESS, url,
- COL_LASTVISIT, "Unknown",
- COL_TOTALVISITS, data->visits,
- -1);
- }
-
-#endif
- return true;
-}
-
-#warning XXX
-#if 0 /* GTK */
-void nsgtk_history_selection_changed(GtkTreeSelection *treesel, gpointer g)
-{
- GtkTreeIter iter;
- GtkTreeModel *model = GTK_TREE_MODEL(history_tree);
- if (gtk_tree_selection_get_selected(treesel, &model, &iter))
- {
- gchar *b;
- gint i;
- char buf[20];
-
- gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
- "labelHistoryAddress")), b);
-
- gtk_tree_model_get(model, &iter, COL_LASTVISIT, &b, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
- "labelHistoryLastVisit")), b);
-
- gtk_tree_model_get(model, &iter, COL_TOTALVISITS,
- &i, -1);
- snprintf(buf, 20, "%d", i);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows,
- "labelHistoryVisits")), buf);
-
-
-
- }
- else
- {
-
- }
-}
-
-void nsgtk_history_row_activated(GtkTreeView *tv, GtkTreePath *path,
- GtkTreeViewColumn *column, gpointer g)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model(tv);
- if (gtk_tree_model_get_iter(model, &iter, path))
- {
- gchar *b;
-
- gtk_tree_model_get(model, &iter, COL_ADDRESS, &b, -1);
-
- browser_window_create((const char *)b, NULL, NULL, true);
- }
-}
-#endif
-
-void global_history_add(const char *url)
-{
- const struct url_data *data;
-
- data = urldb_get_url_data(url);
- if (!data)
- return;
-
- nsbeos_history_add_internal(url, data);
-
-}
diff --git a/beos/beos_scaffolding.cpp b/beos/beos_scaffolding.cpp
index a5cc832a7..3fb147f1f 100644
--- a/beos/beos_scaffolding.cpp
+++ b/beos/beos_scaffolding.cpp
@@ -63,7 +63,6 @@ extern "C" {
#include "beos/beos_options.h"
//#include "beos/beos_completion.h"
#include "beos/beos_throbber.h"
-//#include "beos/beos_history.h"
#include "beos/beos_window.h"
//#include "beos/beos_schedule.h"
//#include "beos/beos_download.h"
diff --git a/beos/beos_treeview.cpp b/beos/beos_treeview.cpp
index 1688a95fa..6763c25b8 100644
--- a/beos/beos_treeview.cpp
+++ b/beos/beos_treeview.cpp
@@ -26,107 +26,59 @@
extern "C" {
#include "utils/config.h"
#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
}
+const char tree_directory_icon_name[] = "directory.png";
+const char tree_content_icon_name[] = "content.png";
-/**
- * Sets the origin variables to the correct values for a specified tree
- *
- * \param tree the tree to set the origin for
- */
-void tree_initialise_redraw(struct tree *tree) {
-}
-
-
-/**
- * Informs the current window manager that an area requires updating.
- *
- * \param tree the tree that is requesting a redraw
- * \param x the x co-ordinate of the redraw area
- * \param y the y co-ordinate of the redraw area
- * \param width the width of the redraw area
- * \param height the height of the redraw area
- */
-void tree_redraw_area(struct tree *tree, int x, int y, int width, int height) {
-}
-
-
-/**
- * Draws a line.
- *
- * \param x the x co-ordinate
- * \param x the y co-ordinate
- * \param x the width of the line
- * \param x the height of the line
- */
-void tree_draw_line(int x, int y, int width, int height) {
-}
-
-
-/**
- * Draws an element, including any expansion icons
- *
- * \param tree the tree to draw an element for
- * \param element the element to draw
- */
-void tree_draw_node_element(struct tree *tree, struct node_element *element) {
-}
-
-
-/**
- * Draws an elements expansion icon
- *
- * \param tree the tree to draw the expansion for
- * \param element the element to draw the expansion for
- */
-void tree_draw_node_expansion(struct tree *tree, struct node *node) {
-}
-
-
-/**
- * Recalculates the dimensions of a node element.
- *
- * \param element the element to recalculate
- */
-void tree_recalculate_node_element(struct node_element *element) {
-}
-
-/**
- * Sets a node element as having a specific sprite.
- *
- * \param node the node to update
- * \param sprite the sprite to use
- * \param selected the expanded sprite name to use
- */
-void tree_set_node_sprite(struct node *node, const char *sprite,
- const char *expanded) {
-}
-
-/**
- * Sets a node element as having a folder sprite
- *
- * \param node the node to update
- */
-void tree_set_node_sprite_folder(struct node *node) {
-
-}
-
-/**
- * Updates the node details for a URL node.
- * The internal node dimensions are not updated.
- *
- * \param node the node to update
- */
-void tree_update_URL_node(struct node *node, const char *url,
- const struct url_data *data) {
-}
/**
- * Updates the tree owner following a tree resize
+ * Translates a content_type to the name of a respective icon
*
- * \param tree the tree to update the owner of
+ * \param content_type content type
+ * \param buffer buffer for the icon name
*/
-void tree_resized(struct tree *tree) {
+void tree_icon_name_from_content_type(char *buffer, content_type type)
+{
+ // TODO: design/acquire icons
+ switch (type) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ case CONTENT_CSS:
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ case CONTENT_PNG:
+#endif
+#ifdef WITH_MNG
+ case CONTENT_JNG:
+ case CONTENT_MNG:
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+#endif
+#ifdef WITH_BMP
+ case CONTENT_BMP:
+ case CONTENT_ICO:
+#endif
+#ifdef WITH_SPRITE
+ case CONTENT_SPRITE:
+#endif
+#ifdef WITH_DRAW
+ case CONTENT_DRAW:
+#endif
+#ifdef WITH_ARTWORKS
+ case CONTENT_ARTWORKS:
+#endif
+#ifdef WITH_NS_SVG
+ case CONTENT_SVG:
+#endif
+ default:
+ sprintf(buffer, tree_content_icon_name);
+ break;
+ }
}
diff --git a/content/urldb.c b/content/urldb.c
index e4a163738..ee550503f 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -245,13 +245,11 @@ static bool urldb_iterate_partial_path(const struct path_data *parent,
static bool urldb_iterate_entries_host(struct search_node *parent,
bool (*url_callback)(const char *url,
const struct url_data *data),
- bool (*cookie_callback)(const char *domain,
- const struct cookie_data *data));
+ bool (*cookie_callback)(const struct cookie_data *data));
static bool urldb_iterate_entries_path(const struct path_data *parent,
bool (*url_callback)(const char *url,
const struct url_data *data),
- bool (*cookie_callback)(const char *domain,
- const struct cookie_data *data));
+ bool (*cookie_callback)(const struct cookie_data *data));
/* Insertion */
static struct host_part *urldb_add_host_node(const char *part,
@@ -1390,8 +1388,7 @@ void urldb_iterate_entries(bool (*callback)(const char *url,
*
* \param callback Function to callback for each entry
*/
-void urldb_iterate_cookies(bool (*callback)(const char *domain,
- const struct cookie_data *data))
+void urldb_iterate_cookies(bool (*callback)(const struct cookie_data *data))
{
int i;
@@ -1415,8 +1412,7 @@ void urldb_iterate_cookies(bool (*callback)(const char *domain,
bool urldb_iterate_entries_host(struct search_node *parent,
bool (*url_callback)(const char *url,
const struct url_data *data),
- bool (*cookie_callback)(const char *domain,
- const struct cookie_data *data))
+ bool (*cookie_callback)(const struct cookie_data *data))
{
if (parent == &empty)
return true;
@@ -1452,11 +1448,11 @@ bool urldb_iterate_entries_host(struct search_node *parent,
bool urldb_iterate_entries_path(const struct path_data *parent,
bool (*url_callback)(const char *url,
const struct url_data *data),
- bool (*cookie_callback)(const char *domain,
- const struct cookie_data *data))
+ bool (*cookie_callback)(const struct cookie_data *data))
{
const struct path_data *p = parent;
-
+ const struct cookie_data *c;
+
do {
if (p->children != NULL) {
/* Drill down into children */
@@ -1478,11 +1474,10 @@ bool urldb_iterate_entries_path(const struct path_data *parent,
(const struct url_data *) u))
return false;
} else {
- if (p->cookies && !cookie_callback(
- p->cookies->domain,
- (const struct cookie_data *)
- p->cookies))
- return false;
+ c = (const struct cookie_data *)p->cookies;
+ for (; c != NULL; c = c->next)
+ if (!cookie_callback(c))
+ return false;
}
/* Now, find next node to process. */
@@ -2447,9 +2442,7 @@ char *urldb_get_cookie(const char *url)
url_func_result res;
int i;
- assert(url);
-
-// LOG(("%s", url));
+ assert(url != NULL);
urldb_add_url(url);
@@ -2529,14 +2522,11 @@ char *urldb_get_cookie(const char *url)
version = c->version;
c->last_used = now;
- cookies_update(c->domain,
- (struct cookie_data *)c);
+ cookies_schedule_update((struct cookie_data *)c);
}
}
}
-// LOG(("%s", ret));
-
/* Now consider cookies whose paths prefix-match ours */
for (p = p->parent; p; p = p->parent) {
/* Find directory's path entry(ies) */
@@ -2546,7 +2536,6 @@ char *urldb_get_cookie(const char *url)
continue;
for (c = q->cookies; c; c = c->next) {
-// LOG(("%p: %s=%s", c, c->name, c->value));
if (c->expires != 1 && c->expires < now)
/* cookie has expired => ignore */
continue;
@@ -2565,8 +2554,7 @@ char *urldb_get_cookie(const char *url)
version = c->version;
c->last_used = now;
- cookies_update(c->domain,
- (struct cookie_data *)c);
+ cookies_schedule_update((struct cookie_data *)c);
}
}
@@ -2606,13 +2594,11 @@ char *urldb_get_cookie(const char *url)
version = c->version;
c->last_used = now;
- cookies_update(c->domain, (struct cookie_data *)c);
+ cookies_schedule_update((struct cookie_data *)c);
}
}
-// LOG(("%s", ret));
-
/* Finally consider domain cookies for hosts which domain match ours */
for (h = (const struct host_part *)p; h && h != &db_root;
h = h->parent) {
@@ -2638,12 +2624,10 @@ char *urldb_get_cookie(const char *url)
version = c->version;
c->last_used = now;
- cookies_update(c->domain, (struct cookie_data *)c);
+ cookies_schedule_update((struct cookie_data *)c);
}
}
-// LOG(("%s", ret));
-
if (count == 0) {
/* No cookies found */
free(path);
@@ -2712,8 +2696,6 @@ bool urldb_set_cookie(const char *header, const char *url,
assert(url && header);
-// LOG(("'%s' : '%s'", url, header));
-
/* strip fragment */
urlt = strdup(url);
if (!urlt)
@@ -2928,7 +2910,7 @@ bool urldb_set_cookie(const char *header, const char *url,
/* Now insert into database */
if (!urldb_insert_cookie(c, scheme, urlt))
goto error;
- cookies_update(c->domain, (struct cookie_data *)c);
+ cookies_schedule_update((struct cookie_data *)c);
} while (cur < end);
free(host);
@@ -3378,6 +3360,8 @@ bool urldb_insert_cookie(struct cookie_internal_data *c, const char *scheme,
d->prev->next = d->next;
else
p->cookies = d->next;
+
+ cookies_remove((struct cookie_data *)d);
urldb_free_cookie(d);
urldb_free_cookie(c);
} else {
@@ -3392,8 +3376,11 @@ bool urldb_insert_cookie(struct cookie_internal_data *c, const char *scheme,
c->prev->next = c;
else
p->cookies = c;
+
+ cookies_remove((struct cookie_data *)d);
urldb_free_cookie(d);
-// LOG(("%p: %s=%s", c, c->name, c->value));
+
+ cookies_schedule_update((struct cookie_data *)c);
}
} else {
c->prev = p->cookies_end;
@@ -3403,7 +3390,6 @@ bool urldb_insert_cookie(struct cookie_internal_data *c, const char *scheme,
else
p->cookies = c;
p->cookies_end = c;
-// LOG(("%p: %s=%s", c, c->name, c->value));
}
return true;
@@ -3771,9 +3757,7 @@ void urldb_delete_cookie_paths(const char *domain, const char *path,
else
p->cookies_end = c->prev;
- if (p->cookies == NULL)
- cookies_update(domain, NULL);
-
+ cookies_remove((struct cookie_data *)c);
urldb_free_cookie(c);
return;
diff --git a/content/urldb.h b/content/urldb.h
index 5080dc52d..bbf378332 100644
--- a/content/urldb.h
+++ b/content/urldb.h
@@ -108,8 +108,7 @@ void urldb_iterate_partial(const char *prefix,
/* Iteration */
void urldb_iterate_entries(bool (*callback)(const char *url,
const struct url_data *data));
-void urldb_iterate_cookies(bool (*callback)(const char *domain,
- const struct cookie_data *cookie));
+void urldb_iterate_cookies(bool (*callback)(const struct cookie_data *cookie));
/* Debug */
void urldb_dump(void);
diff --git a/desktop/browser.c b/desktop/browser.c
index 8c53813a6..b301b5fa3 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -46,6 +46,7 @@
#include "desktop/download.h"
#include "desktop/frames.h"
#include "desktop/history_core.h"
+#include "desktop/hotlist.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/selection.h"
diff --git a/desktop/cookies.c b/desktop/cookies.c
new file mode 100644
index 000000000..c5dac5101
--- /dev/null
+++ b/desktop/cookies.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Cookies (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/cookies.h"
+#include "desktop/options.h"
+#include "desktop/tree.h"
+#include "utils/messages.h"
+#include "utils/log.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+
+/** Flags for each type of cookie tree node. */
+enum tree_element_cookie {
+ TREE_ELEMENT_PERSISTENT = 0x01,
+ TREE_ELEMENT_VERSION = 0x02,
+ TREE_ELEMENT_SECURE = 0x03,
+ TREE_ELEMENT_LAST_USED = 0x04,
+ TREE_ELEMENT_EXPIRES = 0x05,
+ TREE_ELEMENT_PATH = 0x06,
+ TREE_ELEMENT_DOMAIN = 0x07,
+ TREE_ELEMENT_COMMENT = 0x08,
+ TREE_ELEMENT_VALUE = 0x09,
+};
+
+static struct tree *cookies_tree;
+static struct node *cookies_tree_root;
+static bool user_delete;
+static hlcache_handle *folder_icon;
+static hlcache_handle *cookie_icon;
+
+
+/**
+ * Find an entry in the cookie tree
+ *
+ * \param node the node to check the children of
+ * \param title The title to find
+ * \return Pointer to node, or NULL if not found
+ */
+static struct node *cookies_find(struct node *node, const char *title)
+{
+ struct node *search;
+ struct node_element *element;
+
+ for (search = tree_node_get_child(node); search;
+ search = tree_node_get_next(search)) {
+ element = tree_node_find_element(search, TREE_ELEMENT_TITLE,
+ NULL);
+ if (strcmp(title, tree_node_element_get_text(element)) == 0)
+ return search;
+ }
+ return NULL;
+}
+
+/**
+ * Callback for all cookie tree nodes.
+ */
+static node_callback_resp cookies_node_callback(void *user_data, struct node_msg_data *msg_data)
+{
+ struct node *node = msg_data->node;
+ struct node_element *domain, *path;
+ const char *domain_t, *path_t, *name_t;
+ char *space;
+ bool is_folder = tree_node_is_folder(node);
+
+ /* we don't remove any icons here */
+ if (msg_data->msg == NODE_DELETE_ELEMENT_IMG)
+ return NODE_CALLBACK_HANDLED;
+
+ /* let the tree handle events other than text data removal */
+ if (msg_data->msg != NODE_DELETE_ELEMENT_TXT)
+ return NODE_CALLBACK_NOT_HANDLED;
+
+ /* check if it's a domain folder */
+ if (is_folder)
+ return NODE_CALLBACK_NOT_HANDLED;
+
+ switch (msg_data->flag) {
+ case TREE_ELEMENT_TITLE:
+ if (!user_delete)
+ break;
+ /* get the rest of the cookie data */
+ domain = tree_node_find_element(node,
+ TREE_ELEMENT_DOMAIN, NULL);
+ path = tree_node_find_element(node, TREE_ELEMENT_PATH,
+ NULL);
+
+ if ((domain != NULL) &&
+ (path != NULL)) {
+ domain_t = tree_node_element_get_text(domain) +
+ strlen(messages_get(
+ "TreeDomain")) - 4;
+ space = strchr(domain_t, ' ');
+ if (space != NULL)
+ *space = '\0';
+ path_t = tree_node_element_get_text(path) +
+ strlen(messages_get("TreePath"))
+ - 4;
+ space = strchr(path_t, ' ');
+ if (space != NULL)
+ *space = '\0';
+ name_t = msg_data->data.text;
+ urldb_delete_cookie(domain_t, path_t, name_t);
+ }
+ break;
+ default:
+ break;
+ }
+
+ free(msg_data->data.text);
+
+ return NODE_CALLBACK_HANDLED;
+}
+
+
+/**
+ * Updates a tree entry for a cookie.
+ *
+ * All information is copied from the cookie_data, and as such can
+ * be edited and should be freed.
+ *
+ * \param node The node to update
+ * \param data The cookie data to use
+ * \return true if node updated, or false for failure
+ */
+static bool cookies_update_cookie_node(struct node *node,
+ const struct cookie_data *data)
+{
+ struct node_element *element;
+ char buffer[32];
+
+ assert(data != NULL);
+
+ /* update the value text */
+ element = tree_node_find_element(node, TREE_ELEMENT_VALUE, NULL);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeValue",
+ data->value != NULL ?
+ data->value :
+ messages_get("TreeUnused")));
+
+
+ /* update the comment text */
+ if ((data->comment != NULL) &&
+ (strcmp(data->comment, "") != 0)) {
+ element = tree_node_find_element(node, TREE_ELEMENT_COMMENT, NULL);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeComment",
+ data->comment));
+ }
+
+ /* update domain text */
+ element = tree_node_find_element(node, TREE_ELEMENT_DOMAIN, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeDomain",
+ data->domain,
+ data->domain_from_set ?
+ messages_get("TreeHeaders") :
+ ""));
+
+ /* update path text */
+ element = tree_node_find_element(node, TREE_ELEMENT_PATH, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreePath", data->path,
+ data->path_from_set ?
+ messages_get("TreeHeaders") :
+ ""));
+
+ /* update expiry text */
+ element = tree_node_find_element(node, TREE_ELEMENT_EXPIRES, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeExpires",
+ (data->expires > 0)
+ ? (data->expires == 1)
+ ? messages_get("TreeSession")
+ : ctime(&data->expires)
+ : messages_get("TreeUnknown")));
+
+ /* update last used text */
+ element = tree_node_find_element(node, TREE_ELEMENT_LAST_USED, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeLastUsed",
+ (data->last_used > 0) ?
+ ctime(&data->last_used) :
+ messages_get("TreeUnknown")));
+
+ /* update secure text */
+ element = tree_node_find_element(node, TREE_ELEMENT_SECURE, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeSecure",
+ data->secure ?
+ messages_get("Yes") :
+ messages_get("No")));
+
+ /* update version text */
+ element = tree_node_find_element(node, TREE_ELEMENT_VERSION, element);
+ snprintf(buffer, sizeof(buffer), "TreeVersion%i", data->version);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreeVersion",
+ messages_get(buffer)));
+
+ /* update persistant text */
+ element = tree_node_find_element(node, TREE_ELEMENT_PERSISTENT, element);
+ tree_update_element_text(cookies_tree,
+ element,
+ messages_get_buff("TreePersistent",
+ data->no_destroy ?
+ messages_get("Yes") :
+ messages_get("No")));
+
+ return node;
+}
+
+/**
+ * Creates an empty tree entry for a cookie, and links it into the tree.
+ *
+ * All information is copied from the cookie_data, and as such can
+ * be edited and should be freed.
+ *
+ * \param parent the node to link to
+ * \param data the cookie data to use
+ * \return the node created, or NULL for failure
+ */
+static struct node *cookies_create_cookie_node(struct node *parent,
+ const struct cookie_data *data)
+{
+ struct node *node;
+ char *name;
+
+ name = strdup(data->name);
+ if (name == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ node = tree_create_leaf_node(cookies_tree, NULL, name,
+ false, false, false);
+ if (node == NULL) {
+ free(name);
+ return NULL;
+ }
+
+ tree_set_node_user_callback(node, cookies_node_callback, NULL);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_PERSISTENT, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_VERSION, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SECURE, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_LAST_USED, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_EXPIRES, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_PATH, false);
+
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_DOMAIN, false);
+
+ if ((data->comment) && (strcmp(data->comment, "")))
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_COMMENT, false);
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_VALUE, false);
+ tree_set_node_icon(cookies_tree, node, cookie_icon);
+
+ if (!cookies_update_cookie_node(node, data))
+ {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+
+ tree_link_node(cookies_tree, parent, node, false);
+ return node;
+}
+
+
+/**
+ * Called when scheduled event gets fired. Actually performs the update.
+ */
+static void cookies_schedule_callback(void *scheduled_data)
+{
+ const struct cookie_data *data = scheduled_data;
+ struct node *node = NULL;
+ struct node *cookie_node = NULL;
+ char *domain_cp;
+
+ assert(data != NULL);
+
+ node = cookies_find(cookies_tree_root, data->domain);
+
+ if (node == NULL) {
+ domain_cp = strdup(data->domain);
+ if (domain_cp == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return;
+ }
+ node = tree_create_folder_node(cookies_tree,
+ cookies_tree_root, domain_cp,
+ false, false, false);
+ if (node != NULL) {
+ tree_set_node_user_callback(node, cookies_node_callback,
+ NULL);
+ tree_set_node_icon(cookies_tree, node, folder_icon);
+ }
+ }
+
+ if (node == NULL)
+ return;
+
+ cookie_node = cookies_find(node, data->name);
+ if (cookie_node == NULL)
+ cookies_create_cookie_node(node, data);
+ else
+ cookies_update_cookie_node(cookie_node, data);
+
+ return;
+}
+
+/**
+ * Initialises cookies tree.
+ *
+ * \param data user data for the callbacks
+ * \param start_redraw callback function called before every redraw
+ * \param end_redraw callback function called after every redraw
+ * \return true on success, false on memory exhaustion
+ */
+bool cookies_initialise(struct tree *tree)
+{
+
+ if (tree == NULL)
+ return false;
+
+ folder_icon = tree_load_icon(tree_directory_icon_name);
+ cookie_icon = tree_load_icon(tree_content_icon_name);
+
+ /* Create an empty tree */
+ cookies_tree = tree;
+ cookies_tree_root = tree_get_root(cookies_tree);
+
+ user_delete = false;
+ urldb_iterate_cookies(cookies_schedule_update);
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ true, true, true);
+
+ return true;
+}
+
+
+/**
+ * Get flags with which the cookies tree should be created;
+ *
+ * \return the flags
+ */
+unsigned int cookies_get_tree_flags(void)
+{
+ return TREE_DELETE_EMPTY_DIRS;
+}
+
+
+/* exported interface documented in cookies.h */
+bool cookies_schedule_update(const struct cookie_data *data)
+{
+ assert(data != NULL);
+ assert(user_delete == false);
+
+ schedule(100, cookies_schedule_callback, (void *)data);
+
+ return true;
+}
+
+
+/* exported interface documented in cookies.h */
+void cookies_remove(const struct cookie_data *data)
+{
+ assert(data != NULL);
+
+ schedule_remove(cookies_schedule_callback, (void *)data);
+}
+
+
+/**
+ * Free memory and release all other resources.
+ */
+void cookies_cleanup(void)
+{
+}
+
+/* Actions to be connected to front end specific toolbars */
+
+/**
+ * Delete nodes which are currently selected.
+ */
+void cookies_delete_selected(void)
+{
+ user_delete = true;
+ tree_delete_selected_nodes(cookies_tree, cookies_tree_root);
+ user_delete = false;
+}
+
+/**
+ * Delete all nodes.
+ */
+void cookies_delete_all(void)
+{
+ bool needs_redraw = tree_get_redraw(cookies_tree);
+ if (needs_redraw)
+ tree_set_redraw(cookies_tree, false);
+
+ user_delete = true;
+ tree_set_node_selected(cookies_tree, cookies_tree_root, true, true);
+ tree_delete_selected_nodes(cookies_tree, cookies_tree_root);
+ user_delete = false;
+
+ if (needs_redraw)
+ tree_set_redraw(cookies_tree, true);
+}
+
+/**
+ * Select all nodes in the tree.
+ */
+void cookies_select_all(void)
+{
+ tree_set_node_selected(cookies_tree, cookies_tree_root, true, true);
+}
+
+/**
+ * Unselect all nodes.
+ */
+void cookies_clear_selection(void)
+{
+ tree_set_node_selected(cookies_tree, cookies_tree_root, true, false);
+}
+
+/**
+ * Expand both domain and cookie nodes.
+ */
+void cookies_expand_all(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ true, true, true);
+}
+
+/**
+ * Expand domain nodes only.
+ */
+void cookies_expand_domains(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ true, true, false);
+}
+
+/**
+ * Expand cookie nodes only.
+ */
+void cookies_expand_cookies(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ true, false, true);
+}
+
+/**
+ * Collapse both domain and cookie nodes.
+ */
+void cookies_collapse_all(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ false, true, true);
+}
+
+/**
+ * Collapse domain nodes only.
+ */
+void cookies_collapse_domains(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ false, true, false);
+}
+
+/**
+ * Collapse cookie nodes only.
+ */
+void cookies_collapse_cookies(void)
+{
+ tree_set_node_expanded(cookies_tree, cookies_tree_root,
+ false, false, true);
+}
diff --git a/desktop/cookies.h b/desktop/cookies.h
index 4311957df..06278c006 100644
--- a/desktop/cookies.h
+++ b/desktop/cookies.h
@@ -25,8 +25,42 @@
#include <stdbool.h>
+#include "desktop/tree.h"
+
struct cookie_data;
-bool cookies_update(const char *domain, const struct cookie_data *data);
+bool cookies_initialise(struct tree *tree);
+unsigned int cookies_get_tree_flags(void);
+
+/**
+ * Perform cookie updates and addition. The update is only scheduled here.
+ * The actual update is performed in the callback function.
+ *
+ * \param data Data of cookie being updated.
+ * \return true (for urldb_iterate_entries)
+ */
+bool cookies_schedule_update(const struct cookie_data *data);
+
+/**
+ * Remove a cookie from the active set.
+ * The cookie is to be removed from the active set and no futher
+ * references made to the cookie data.
+ *
+ * \param data Data of cookie being removed.
+ */
+void cookies_remove(const struct cookie_data *data);
+
+void cookies_cleanup(void);
+
+void cookies_delete_selected(void);
+void cookies_delete_all(void);
+void cookies_select_all(void);
+void cookies_clear_selection(void);
+void cookies_expand_all(void);
+void cookies_expand_domains(void);
+void cookies_expand_cookies(void);
+void cookies_collapse_all(void);
+void cookies_collapse_domains(void);
+void cookies_collapse_cookies(void);
#endif
diff --git a/desktop/history_global_core.c b/desktop/history_global_core.c
new file mode 100644
index 000000000..b8cd9a5b0
--- /dev/null
+++ b/desktop/history_global_core.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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 <stdlib.h>
+
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/history_global_core.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
+
+#ifdef riscos
+#include "riscos/gui.h"
+#endif
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+
+#define MAXIMUM_BASE_NODES 16
+#define GLOBAL_HISTORY_RECENT_URLS 16
+#define URL_CHUNK_LENGTH 512
+
+static struct node *global_history_base_node[MAXIMUM_BASE_NODES];
+static int global_history_base_node_time[MAXIMUM_BASE_NODES];
+static int global_history_base_node_count = 0;
+
+static bool global_history_initialised;
+
+static struct tree *global_history_tree;
+static struct node *global_history_tree_root;
+
+static hlcache_handle *folder_icon;
+
+static const char *const weekday_msg_name [] =
+{
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+};
+
+/**
+ * Find an entry in the global history
+ *
+ * \param url The URL to find
+ * \return Pointer to node, or NULL if not found
+ */
+static struct node *history_global_find(const char *url)
+{
+ int i;
+ struct node *node;
+ const char *text;
+
+ for (i = 0; i < global_history_base_node_count; i++) {
+ if (!tree_node_is_deleted(global_history_base_node[i])) {
+ node = tree_node_get_child(global_history_base_node[i]);
+ for (; node != NULL; node = tree_node_get_next(node)) {
+ text = tree_url_node_get_url(node);
+ if ((text != NULL) && !strcmp(url, text))
+ return node;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Internal routine to actually perform global history addition
+ *
+ * \param url The URL to add
+ * \param data URL data associated with URL
+ * \return true (for urldb_iterate_entries)
+ */
+static bool global_history_add_internal(const char *url,
+ const struct url_data *data)
+{
+ int i, j;
+ struct node *parent = NULL;
+ struct node *link;
+ struct node *node;
+ bool before = false;
+ int visit_date;
+
+ assert((url != NULL) && (data != NULL));
+
+ visit_date = data->last_visit;
+
+ /* find parent node */
+ for (i = 0; i < global_history_base_node_count; i++) {
+ if (global_history_base_node_time[i] <= visit_date) {
+ parent = global_history_base_node[i];
+ break;
+ }
+ }
+
+ /* the entry is too old to care about */
+ if (parent == NULL)
+ return true;
+
+ if (tree_node_is_deleted(parent)) {
+ /* parent was deleted, so find place to insert it */
+ link = global_history_tree_root;
+
+ for (j = global_history_base_node_count - 1; j >= 0; j--) {
+ if (!tree_node_is_deleted(global_history_base_node[j]) &&
+ global_history_base_node_time[j] >
+ global_history_base_node_time[i]) {
+ link = global_history_base_node[j];
+ before = true;
+ break;
+ }
+ }
+
+ tree_set_node_selected(global_history_tree,
+ parent, true, false);
+ tree_set_node_expanded(global_history_tree,
+ parent, false, true, true);
+ tree_link_node(global_history_tree, link, parent, before);
+ }
+
+ /* find any previous occurance */
+ if (global_history_initialised == false) {
+ node = history_global_find(url);
+ if (node != NULL) {
+ tree_update_URL_node(global_history_tree,
+ node, url, data, true);
+ tree_delink_node(global_history_tree, node);
+ tree_link_node(global_history_tree, parent, node,
+ false);
+ return true;
+ }
+ }
+
+ /* Add the node at the bottom */
+ node = tree_create_URL_node_shared(global_history_tree,
+ parent, url, data,
+ tree_url_node_callback, NULL);
+
+ return true;
+}
+
+static node_callback_resp
+history_global_node_callback(void *user_data,
+ struct node_msg_data *msg_data)
+{
+ if (msg_data->msg == NODE_DELETE_ELEMENT_IMG)
+ return NODE_CALLBACK_HANDLED;
+ return NODE_CALLBACK_NOT_HANDLED;
+}
+
+/**
+ * Initialises a single grouping node for the global history tree.
+ *
+ * \return false on memory exhaustion, true otherwise
+ */
+static bool history_global_initialise_node(const char *title,
+ time_t base, int days_back)
+{
+ struct tm *full_time;
+ char *buffer;
+ struct node *node;
+
+ base += days_back * 60 * 60 * 24;
+ if (title == NULL) {
+ full_time = localtime(&base);
+ buffer = strdup(messages_get(weekday_msg_name[full_time->tm_wday]));
+ } else {
+ buffer = strdup(title);
+ }
+
+ if (buffer == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
+ node = tree_create_folder_node(NULL, NULL, buffer,
+ false, true, true);
+ if (node == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ free(buffer);
+ return false;
+ }
+ if (folder_icon != NULL)
+ tree_set_node_icon(global_history_tree, node, folder_icon);
+ tree_set_node_user_callback(node, history_global_node_callback, NULL);
+
+ global_history_base_node[global_history_base_node_count] = node;
+ global_history_base_node_time[global_history_base_node_count] = base;
+ global_history_base_node_count++;
+
+ return true;
+}
+
+/**
+ * Initialises the grouping nodes(Today, Yesterday etc.) for the global history
+ * tree.
+ *
+ * \return false on memory exhaustion, true otherwise
+ */
+static bool history_global_initialise_nodes(void)
+{
+ struct tm *full_time;
+ time_t t;
+ int weekday;
+ int i;
+
+ /* get the current time */
+ t = time(NULL);
+ if (t == -1) {
+ LOG(("time info unaviable"));
+ return false;
+ }
+
+ /* get the time at the start of today */
+ full_time = localtime(&t);
+ weekday = full_time->tm_wday;
+ full_time->tm_sec = 0;
+ full_time->tm_min = 0;
+ full_time->tm_hour = 0;
+ t = mktime(full_time);
+ if (t == -1) {
+ LOG(("mktime failed"));
+ return false;
+ }
+
+ history_global_initialise_node(messages_get("DateToday"), t, 0);
+ if (weekday > 0)
+ if (!history_global_initialise_node(
+ messages_get("DateYesterday"), t, -1))
+ return false;
+ for (i = 2; i <= weekday; i++)
+ if (!history_global_initialise_node(NULL, t, -i))
+ return false;
+
+ if (!history_global_initialise_node(messages_get("Date1Week"),
+ t, -weekday - 7))
+ return false;
+ if (!history_global_initialise_node(messages_get("Date2Week"),
+ t, -weekday - 14))
+ return false;
+ if (!history_global_initialise_node(messages_get("Date3Week"),
+ t, -weekday - 21))
+ return false;
+
+ return true;
+}
+
+/**
+ * Initialises the global history tree.
+ *
+ * \param data user data for the callbacks
+ * \param start_redraw callback function called before every redraw
+ * \param end_redraw callback function called after every redraw
+ * \return true on success, false on memory exhaustion
+ */
+bool history_global_initialise(struct tree *tree)
+{
+ struct node *first;
+
+ folder_icon = tree_load_icon(tree_directory_icon_name);
+ tree_url_node_init();
+
+ if (tree == NULL)
+ return false;
+
+ global_history_tree = tree;
+ global_history_tree_root = tree_get_root(global_history_tree);
+
+ if (!history_global_initialise_nodes())
+ return false;
+
+ global_history_initialised = true;
+ urldb_iterate_entries(global_history_add_internal);
+ global_history_initialised = false;
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ false, true, true);
+ first = tree_node_get_child(global_history_tree_root);
+ if (first != NULL)
+ tree_set_node_expanded(global_history_tree, first,
+ true, false, false);
+
+ return true;
+}
+
+
+/**
+ * Get flags with which the global history tree should be created;
+ *
+ * \return the flags
+ */
+unsigned int history_global_get_tree_flags(void)
+{
+ return TREE_NO_FLAGS;
+}
+
+
+/**
+ * Deletes the global history tree.
+ */
+void history_global_cleanup(void)
+{
+}
+
+
+/**
+ * Adds a url to the global history.
+ *
+ * \param url the url to be added
+ */
+void global_history_add(const char *url)
+{
+ const struct url_data *data;
+
+ data = urldb_get_url_data(url);
+ if (data == NULL)
+ return;
+
+ global_history_add_internal(url, data);
+}
+
+
+/* Actions to be connected to front end specific toolbars */
+
+/**
+ * Save the global history in a human-readable form under the given location.
+ *
+ * \param path the path where the history will be saved
+ */
+bool history_global_export(const char *path)
+{
+ return tree_urlfile_save(global_history_tree, path, "NetSurf history");
+}
+
+/**
+ * Delete nodes which are currently selected.
+ */
+void history_global_delete_selected(void)
+{
+ tree_delete_selected_nodes(global_history_tree,
+ global_history_tree_root);
+}
+
+/**
+ * Delete all nodes.
+ */
+void history_global_delete_all(void)
+{
+ bool redraw_needed = tree_get_redraw(global_history_tree);
+ if (redraw_needed)
+ tree_set_redraw(global_history_tree, false);
+
+ tree_set_node_selected(global_history_tree, global_history_tree_root,
+ true, true);
+ tree_delete_selected_nodes(global_history_tree,
+ global_history_tree_root);
+
+ if (redraw_needed)
+ tree_set_redraw(global_history_tree, true);
+}
+
+/**
+ * Select all nodes in the tree.
+ */
+void history_global_select_all(void)
+{
+ tree_set_node_selected(global_history_tree, global_history_tree_root,
+ true, true);
+}
+
+/**
+ * Unselect all nodes.
+ */
+void history_global_clear_selection(void)
+{
+ tree_set_node_selected(global_history_tree, global_history_tree_root,
+ true, false);
+}
+
+/**
+ * Expand grouping folders and history entries.
+ */
+void history_global_expand_all(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ true, true, true);
+}
+
+/**
+ * Expand grouping folders only.
+ */
+void history_global_expand_directories(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ true, true, false);
+}
+
+/**
+ * Expand history entries only.
+ */
+void history_global_expand_addresses(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ true, false, true);
+}
+
+/**
+ * Collapse grouping folders and history entries.
+ */
+void history_global_collapse_all(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ false, true, true);
+}
+
+/**
+ * Collapse grouping folders only.
+ */
+void history_global_collapse_directories(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ false, true, false);
+}
+
+/**
+ * Collapse history entries only.
+ */
+void history_global_collapse_addresses(void)
+{
+ tree_set_node_expanded(global_history_tree, global_history_tree_root,
+ false, false, true);
+}
+
+/**
+ * Open the selected entries in seperate browser windows.
+ */
+void history_global_launch_selected(void)
+{
+ tree_launch_selected(global_history_tree);
+}
diff --git a/desktop/history_global_core.h b/desktop/history_global_core.h
new file mode 100644
index 000000000..97c578f3d
--- /dev/null
+++ b/desktop/history_global_core.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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_DESKTOP_HISTORY_GLOBAL_H_
+#define _NETSURF_DESKTOP_HISTORY_GLOBAL_H_
+
+#include <stdbool.h>
+
+#include "desktop/tree.h"
+
+bool history_global_initialise(struct tree *tree);
+unsigned int history_global_get_tree_flags(void);
+void history_global_cleanup(void);
+
+bool history_global_export(const char *path);
+void history_global_delete_selected(void);
+void history_global_delete_all(void);
+void history_global_select_all(void);
+void history_global_clear_selection(void);
+void history_global_expand_all(void);
+void history_global_expand_directories(void);
+void history_global_expand_addresses(void);
+void history_global_collapse_all(void);
+void history_global_collapse_directories(void);
+void history_global_collapse_addresses(void);
+void history_global_launch_selected(void);
+
+#endif
diff --git a/desktop/hotlist.c b/desktop/hotlist.c
new file mode 100644
index 000000000..09be05709
--- /dev/null
+++ b/desktop/hotlist.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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 <stdlib.h>
+
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/hotlist.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
+
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+
+#define URL_CHUNK_LENGTH 512
+
+static struct tree *hotlist_tree;
+static struct node *hotlist_tree_root;
+
+static bool creating_node;
+static hlcache_handle *folder_icon;
+
+static const struct {
+ const char *url;
+ const char *msg_key;
+} hotlist_default_entries[] = {
+ { "http://www.netsurf-browser.org/", "HotlistHomepage" },
+ { "http://www.netsurf-browser.org/downloads/riscos/testbuilds",
+ "HotlistTestBuild" },
+ { "http://www.netsurf-browser.org/documentation",
+ "HotlistDocumentation" },
+ { "http://sourceforge.net/tracker/?atid=464312&group_id=51719",
+ "HotlistBugTracker" },
+ { "http://sourceforge.net/tracker/?atid=464315&group_id=51719",
+ "HotlistFeatureRequest" }
+};
+#define HOTLIST_ENTRIES_COUNT (sizeof(hotlist_default_entries) / sizeof(hotlist_default_entries[0]))
+
+static node_callback_resp hotlist_node_callback(void *user_data,
+ struct node_msg_data *msg_data)
+{
+ struct node *node = msg_data->node;
+ const char *text;
+ char *norm_text;
+ bool is_folder = tree_node_is_folder(node);
+
+ switch (msg_data->msg) {
+ case NODE_ELEMENT_EDIT_FINISHED:
+ if (creating_node &&
+ (is_folder == false) &&
+ (msg_data->flag == TREE_ELEMENT_TITLE)) {
+ tree_url_node_edit_url(hotlist_tree, node);
+ } else {
+ creating_node = false;
+ }
+ return NODE_CALLBACK_HANDLED;
+
+ case NODE_ELEMENT_EDIT_FINISHING:
+ if (creating_node && (is_folder == false))
+ return tree_url_node_callback(hotlist_tree, msg_data);
+
+ if (is_folder == true) {
+ text = msg_data->data.text;
+ while (isspace(*text))
+ text++;
+ norm_text = strdup(text);
+ if (norm_text == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NODE_CALLBACK_REJECT;
+ }
+ /* don't allow zero length entry text, return false */
+ if (norm_text[0] == '\0') {
+ warn_user("NoNameError", 0);
+ msg_data->data.text = NULL;
+ return NODE_CALLBACK_CONTINUE;
+ }
+ msg_data->data.text = norm_text;
+ }
+ break;
+
+ case NODE_DELETE_ELEMENT_IMG:
+ return NODE_CALLBACK_HANDLED;
+
+ default:
+ if (is_folder == false)
+ return tree_url_node_callback(hotlist_tree, msg_data);
+ }
+
+ return NODE_CALLBACK_NOT_HANDLED;
+}
+
+
+bool hotlist_initialise(struct tree *tree, const char *hotlist_path)
+{
+ struct node *node;
+ const struct url_data *url_data;
+ char *name;
+ int hlst_loop;
+
+ /* Either load or create a hotlist */
+
+ creating_node = false;
+
+ folder_icon = tree_load_icon(tree_directory_icon_name);
+
+ tree_url_node_init();
+
+ if (tree == NULL)
+ return false;
+
+ hotlist_tree = tree;
+ hotlist_tree_root = tree_get_root(hotlist_tree);
+
+ if (tree_urlfile_load(hotlist_path,
+ hotlist_tree,
+ hotlist_node_callback,
+ NULL)) {
+ return true;
+ }
+
+
+ /* failed to load hotlist file, use default list */
+ name = strdup("NetSurf");
+ if (name == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ node = tree_create_folder_node(hotlist_tree, hotlist_tree_root,
+ name, true, false, false);
+ if (node == NULL) {
+ free(name);
+ return false;
+ }
+
+ tree_set_node_user_callback(node, hotlist_node_callback, NULL);
+ tree_set_node_icon(hotlist_tree, node, folder_icon);
+
+ for (hlst_loop = 0; hlst_loop != HOTLIST_ENTRIES_COUNT; hlst_loop++) {
+ url_data = urldb_get_url_data(hotlist_default_entries[hlst_loop].url);
+ if (url_data == NULL) {
+ urldb_add_url(hotlist_default_entries[hlst_loop].url);
+ urldb_set_url_persistence(
+ hotlist_default_entries[hlst_loop].url,
+ true);
+ url_data = urldb_get_url_data(
+ hotlist_default_entries[hlst_loop].url);
+ }
+ if (url_data != NULL) {
+ tree_create_URL_node(hotlist_tree, node,
+ hotlist_default_entries[hlst_loop].url,
+ messages_get(hotlist_default_entries[hlst_loop].msg_key),
+ hotlist_node_callback, NULL);
+ tree_update_URL_node(hotlist_tree, node,
+ hotlist_default_entries[hlst_loop].url,
+ url_data, false);
+ }
+ }
+
+
+
+ return true;
+}
+
+
+/**
+ * Get flags with which the hotlist tree should be created;
+ *
+ * \return the flags
+ */
+unsigned int hotlist_get_tree_flags(void)
+{
+ return TREE_MOVABLE;
+}
+
+
+/**
+ * Deletes the global history tree and saves the hotlist.
+ * \param hotlist_path the path where the hotlist should be saved
+ */
+void hotlist_cleanup(const char *hotlist_path)
+{
+ hotlist_export(hotlist_path);
+}
+
+
+/**
+ * Informs the hotlist that some content has been visited. Internal procedure.
+ *
+ * \param content the content visited
+ * \param node the node to update siblings and children of
+ */
+static void hotlist_visited_internal(hlcache_handle *content, struct node *node)
+{
+ struct node *child;
+ const char *text;
+ const char *url;
+
+ if (content == NULL ||
+ content_get_url(content) == NULL ||
+ hotlist_tree == NULL)
+ return;
+
+ url = content_get_url(content);
+
+ for (; node; node = tree_node_get_next(node)) {
+ if (!tree_node_is_folder(node)) {
+ text = tree_url_node_get_url(node);
+ if (strcmp(text, url) == 0) {
+ tree_update_URL_node(hotlist_tree, node,
+ url, NULL, false);
+ }
+ }
+ child = tree_node_get_child(node);
+ if (child != NULL) {
+ hotlist_visited_internal(content, child);
+ }
+ }
+}
+
+/**
+ * Informs the hotlist that some content has been visited
+ *
+ * \param content the content visited
+ */
+void hotlist_visited(hlcache_handle *content)
+{
+ if (hotlist_tree != NULL) {
+ hotlist_visited_internal(content, tree_get_root(hotlist_tree));
+ }
+}
+
+/**
+ * Save the hotlist in a human-readable form under the given location.
+ *
+ * \param path the path where the hotlist will be saved
+ */
+bool hotlist_export(const char *path)
+{
+ return tree_urlfile_save(hotlist_tree, path, "NetSurf hotlist");
+}
+
+/**
+ * Edit the node which is currently selected. Works only if one node is
+ * selected.
+ */
+void hotlist_edit_selected(void)
+{
+ struct node *node;
+ struct node_element *element;
+
+ node = tree_get_selected_node(hotlist_tree_root);
+
+ if (node != NULL) {
+ creating_node = true;
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ tree_start_edit(hotlist_tree, element);
+ }
+}
+
+/**
+ * Delete nodes which are currently selected.
+ */
+void hotlist_delete_selected(void)
+{
+ tree_delete_selected_nodes(hotlist_tree, hotlist_tree_root);
+}
+
+/**
+ * Select all nodes in the tree.
+ */
+void hotlist_select_all(void)
+{
+ tree_set_node_selected(hotlist_tree, hotlist_tree_root,
+ true, true);
+}
+
+/**
+ * Unselect all nodes.
+ */
+void hotlist_clear_selection(void)
+{
+ tree_set_node_selected(hotlist_tree, hotlist_tree_root,
+ true, false);
+}
+
+/**
+ * Expand grouping folders and history entries.
+ */
+void hotlist_expand_all(void)
+{
+ tree_set_node_expanded(hotlist_tree, hotlist_tree_root,
+ true, true, true);
+}
+
+/**
+ * Expand grouping folders only.
+ */
+void hotlist_expand_directories(void)
+{
+ tree_set_node_expanded(hotlist_tree, hotlist_tree_root,
+ true, true, false);
+}
+
+/**
+ * Expand history entries only.
+ */
+void hotlist_expand_addresses(void)
+{
+ tree_set_node_expanded(hotlist_tree, hotlist_tree_root,
+ true, false, true);
+}
+
+/**
+ * Collapse grouping folders and history entries.
+ */
+void hotlist_collapse_all(void)
+{
+ tree_set_node_expanded(hotlist_tree, hotlist_tree_root,
+ false, true, true);
+}
+
+/**
+ * Collapse grouping folders only.
+ */
+void hotlist_collapse_directories(void)
+{
+ tree_set_node_expanded(hotlist_tree, hotlist_tree_root,
+ false, true, false);
+}
+
+/**
+ * Collapse history entries only.
+ */
+void hotlist_collapse_addresses(void)
+{
+ tree_set_node_expanded(hotlist_tree,
+ hotlist_tree_root, false, false, true);
+}
+
+/**
+ * Add a folder node.
+ */
+void hotlist_add_folder(void)
+{
+ struct node *node;
+ struct node_element *element;
+ char *title = strdup("Untitled");
+
+ if (title == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return;
+ }
+ creating_node = true;
+ node = tree_create_folder_node(hotlist_tree, hotlist_tree_root, title,
+ true, false, false);
+ if (node == NULL) {
+ free(title);
+ return;
+ }
+ tree_set_node_user_callback(node, hotlist_node_callback, NULL);
+ tree_set_node_icon(hotlist_tree, node, folder_icon);
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ tree_start_edit(hotlist_tree, element);
+}
+
+/**
+ * Add an entry node.
+ */
+void hotlist_add_entry(void)
+{
+ struct node *node;
+ creating_node = true;
+ node = tree_create_URL_node(hotlist_tree, hotlist_tree_root, "Address",
+ "Untitled", hotlist_node_callback, NULL);
+
+ if (node == NULL)
+ return;
+ tree_set_node_user_callback(node, hotlist_node_callback, NULL);
+ tree_url_node_edit_title(hotlist_tree, node);
+}
+
+/**
+ * Adds the currently viewed page to the hotlist
+ */
+void hotlist_add_page(const char *url)
+{
+ const struct url_data *data;
+ struct node *node;
+
+ if (url == NULL)
+ return;
+ data = urldb_get_url_data(url);
+ if (data == NULL)
+ return;
+
+ node = tree_create_URL_node(hotlist_tree, hotlist_tree_root, url, NULL,
+ hotlist_node_callback, NULL);
+ tree_update_URL_node(hotlist_tree, node, url, data, false);
+}
+
+/**
+ * Adds the currently viewed page to the hotlist at the given cooridinates
+ * \param url url of the page
+ * \param x X cooridinate with respect to tree origin
+ * \param y Y cooridinate with respect to tree origin
+ */
+void hotlist_add_page_xy(const char *url, int x, int y)
+{
+ const struct url_data *data;
+ struct node *link, *node;
+ bool before;
+
+ data = urldb_get_url_data(url);
+ if (data == NULL) {
+ urldb_add_url(url);
+ urldb_set_url_persistence(url, true);
+ data = urldb_get_url_data(url);
+ }
+ if (data != NULL) {
+ link = tree_get_link_details(hotlist_tree, x, y, &before);
+ node = tree_create_URL_node(NULL, NULL, url,
+ NULL, hotlist_node_callback, NULL);
+ tree_link_node(hotlist_tree, link, node, before);
+ }
+}
+
+/**
+ * Open the selected entries in separate browser windows.
+ */
+void hotlist_launch_selected(void)
+{
+ tree_launch_selected(hotlist_tree);
+}
diff --git a/desktop/hotlist.h b/desktop/hotlist.h
new file mode 100644
index 000000000..84f573a90
--- /dev/null
+++ b/desktop/hotlist.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Hotlist (interface).
+ */
+
+#ifndef _NETSURF_DESKTOP_HOTLIST_H_
+#define _NETSURF_DESKTOP_HOTLIST_H_
+
+#include <stdbool.h>
+
+#include "desktop/tree.h"
+
+bool hotlist_initialise(struct tree *tree, const char *hotlist_path);
+unsigned int hotlist_get_tree_flags(void);
+void hotlist_cleanup(const char *hotlist_path);
+
+bool hotlist_export(const char *path);
+void hotlist_edit_selected(void);
+void hotlist_delete_selected(void);
+void hotlist_select_all(void);
+void hotlist_clear_selection(void);
+void hotlist_expand_all(void);
+void hotlist_expand_directories(void);
+void hotlist_expand_addresses(void);
+void hotlist_collapse_all(void);
+void hotlist_collapse_directories(void);
+void hotlist_collapse_addresses(void);
+void hotlist_add_folder(void);
+void hotlist_add_entry(void);
+void hotlist_add_page(const char *url);
+void hotlist_add_page_xy(const char *url, int x, int y);
+void hotlist_launch_selected(void);
+
+#endif
diff --git a/desktop/options.c b/desktop/options.c
index 9ed8b192c..47b42dc3b 100644
--- a/desktop/options.c
+++ b/desktop/options.c
@@ -31,16 +31,10 @@
#include <stdio.h>
#include <string.h>
#include <strings.h>
-#include <libxml/HTMLparser.h>
-#include <libxml/HTMLtree.h>
-#include "content/urldb.h"
#include "css/css.h"
#include "desktop/options.h"
#include "desktop/plot_style.h"
-#include "desktop/tree.h"
#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/url.h"
#include "utils/utils.h"
#if defined(riscos)
@@ -145,6 +139,7 @@ unsigned int option_min_reflow_period = 100; /* time in cs */
#else
unsigned int option_min_reflow_period = 25; /* time in cs */
#endif
+char *option_tree_icons_dir = NULL;
bool option_core_select_menu = false;
/** top margin of exported page*/
int option_margin_top = DEFAULT_MARGIN_TOP_MM;
@@ -247,6 +242,7 @@ struct {
{ "scale", OPTION_INTEGER, &option_scale },
{ "incremental_reflow", OPTION_BOOL, &option_incremental_reflow },
{ "min_reflow_period", OPTION_INTEGER, &option_min_reflow_period },
+ { "tree_icons_dir", OPTION_STRING, &option_tree_icons_dir },
{ "core_select_menu", OPTION_BOOL, &option_core_select_menu },
/* Fetcher options */
{ "max_fetchers", OPTION_INTEGER, &option_max_fetchers },
@@ -276,13 +272,6 @@ struct {
#define option_table_entries (sizeof option_table / sizeof option_table[0])
-static void options_load_tree_directory(xmlNode *ul, struct node *directory);
-static void options_load_tree_entry(xmlNode *li, struct node *directory);
-xmlNode *options_find_tree_element(xmlNode *node, const char *name);
-bool options_save_tree_directory(struct node *directory, xmlNode *node);
-bool options_save_tree_entry(struct node *entry, xmlNode *node);
-
-
/**
* Read options from a file.
*
@@ -429,351 +418,3 @@ void options_dump(void)
fprintf(stderr, "\n");
}
}
-
-/**
- * Loads a hotlist as a tree from a specified file.
- *
- * \param filename name of file to read
- * \return the hotlist file represented as a tree, or NULL on failure
- */
-struct tree *options_load_tree(const char *filename) {
- xmlDoc *doc;
- xmlNode *html, *body, *ul;
- struct tree *tree;
-
- doc = htmlParseFile(filename, "iso-8859-1");
- if (!doc) {
- warn_user("HotlistLoadError", messages_get("ParsingFail"));
- return NULL;
- }
-
- html = options_find_tree_element((xmlNode *) doc, "html");
- body = options_find_tree_element(html, "body");
- ul = options_find_tree_element(body, "ul");
- if (!ul) {
- xmlFreeDoc(doc);
- warn_user("HotlistLoadError",
- "(<html>...<body>...<ul> not found.)");
- return NULL;
- }
-
- tree = calloc(sizeof(struct tree), 1);
- if (!tree) {
- xmlFreeDoc(doc);
- warn_user("NoMemory", 0);
- return NULL;
- }
- tree->root = tree_create_folder_node(NULL, "Root");
- if (!tree->root) {
- free(tree);
- xmlFreeDoc(doc);
-
- return NULL;
- }
-
- options_load_tree_directory(ul, tree->root);
- tree->root->expanded = true;
- tree_initialise(tree);
-
- xmlFreeDoc(doc);
- return tree;
-}
-
-
-/**
- * Parse a directory represented as a ul.
- *
- * \param ul xmlNode for parsed ul
- * \param directory directory to add this directory to
- */
-void options_load_tree_directory(xmlNode *ul, struct node *directory) {
- char *title;
- struct node *dir;
- xmlNode *n;
-
- assert(ul);
- assert(directory);
-
- for (n = ul->children; n; n = n->next) {
- /* The ul may contain entries as a li, or directories as
- * an h4 followed by a ul. Non-element nodes may be present
- * (eg. text, comments), and are ignored. */
-
- if (n->type != XML_ELEMENT_NODE)
- continue;
-
- if (strcmp((const char *) n->name, "li") == 0) {
- /* entry */
- options_load_tree_entry(n, directory);
-
- } else if (strcmp((const char *) n->name, "h4") == 0) {
- /* directory */
- title = (char *) xmlNodeGetContent(n);
- if (!title) {
- warn_user("HotlistLoadError", "(Empty <h4> "
- "or memory exhausted.)");
- return;
- }
-
- for (n = n->next;
- n && n->type != XML_ELEMENT_NODE;
- n = n->next)
- ;
- if (!n || strcmp((const char *) n->name, "ul") != 0) {
- /* next element isn't expected ul */
- free(title);
- warn_user("HotlistLoadError", "(Expected "
- "<ul> not present.)");
- return;
- }
-
- dir = tree_create_folder_node(directory, title);
- if (!dir) {
- free(title);
-
- return;
- }
- options_load_tree_directory(n, dir);
- }
- }
-}
-
-
-/**
- * Parse an entry represented as a li.
- *
- * \param li xmlNode for parsed li
- * \param directory directory to add this entry to
- */
-void options_load_tree_entry(xmlNode *li, struct node *directory) {
- char *url = NULL, *url1 = NULL;
- char *title = NULL;
- struct node *entry;
- xmlNode *n;
- const struct url_data *data;
- url_func_result res;
-
- for (n = li->children; n; n = n->next) {
- /* The li must contain an "a" element */
- if (n->type == XML_ELEMENT_NODE &&
- strcmp((const char *) n->name, "a") == 0) {
- url1 = (char *) xmlGetProp(n, (const xmlChar *) "href");
- title = (char *) xmlNodeGetContent(n);
- }
- }
-
- if (!url1 || !title) {
- warn_user("HotlistLoadError", "(Missing <a> in <li> or "
- "memory exhausted.)");
- return;
- }
-
- /* We're loading external input.
- * This may be garbage, so attempt to normalise
- */
- res = url_normalize(url1, &url);
- if (res != URL_FUNC_OK) {
- LOG(("Failed normalising '%s'", url1));
-
- if (res == URL_FUNC_NOMEM)
- warn_user("NoMemory", NULL);
-
- xmlFree(url1);
- xmlFree(title);
-
- return;
- }
-
- /* No longer need this */
- xmlFree(url1);
-
- data = urldb_get_url_data(url);
- if (!data) {
- /* No entry in database, so add one */
- urldb_add_url(url);
- /* now attempt to get url data */
- data = urldb_get_url_data(url);
- }
- if (!data) {
- xmlFree(title);
- free(url);
-
- return;
- }
-
- /* Make this URL persistent */
- urldb_set_url_persistence(url, true);
-
- if (!data->title)
- urldb_set_url_title(url, title);
-
- entry = tree_create_URL_node(directory, url, data, title);
- if (entry == NULL) {
- /** \todo why isn't this fatal? */
- warn_user("NoMemory", 0);
- }
-
- xmlFree(title);
- free(url);
-}
-
-
-/**
- * Search the children of an xmlNode for an element.
- *
- * \param node xmlNode to search children of, or 0
- * \param name name of element to find
- * \return first child of node which is an element and matches name, or
- * 0 if not found or parameter node is 0
- */
-xmlNode *options_find_tree_element(xmlNode *node, const char *name) {
- xmlNode *n;
- if (!node)
- return 0;
- for (n = node->children;
- n && !(n->type == XML_ELEMENT_NODE &&
- strcmp((const char *) n->name, name) == 0);
- n = n->next)
- ;
- return n;
-}
-
-
-/**
- * Perform a save to a specified file
- *
- * /param filename the file to save to
- */
-bool options_save_tree(struct tree *tree, const char *filename, const char *page_title) {
- int res;
- xmlDoc *doc;
- xmlNode *html, *head, *title, *body;
-
- /* Unfortunately the Browse Hotlist format is invalid HTML,
- * so this is a lie. */
- doc = htmlNewDoc(
- (const xmlChar *) "http://www.w3.org/TR/html4/strict.dtd",
- (const xmlChar *) "-//W3C//DTD HTML 4.01//EN");
- if (!doc) {
- warn_user("NoMemory", 0);
- return false;
- }
-
- html = xmlNewNode(NULL, (const xmlChar *) "html");
- if (!html) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return false;
- }
- xmlDocSetRootElement(doc, html);
-
- head = xmlNewChild(html, NULL, (const xmlChar *) "head", NULL);
- if (!head) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return false;
- }
-
- title = xmlNewTextChild(head, NULL, (const xmlChar *) "title",
- (const xmlChar *) page_title);
- if (!title) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return false;
- }
-
- body = xmlNewChild(html, NULL, (const xmlChar *) "body", NULL);
- if (!body) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return false;
- }
-
- if (!options_save_tree_directory(tree->root, body)) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return false;
- }
-
- doc->charset = XML_CHAR_ENCODING_UTF8;
- res = htmlSaveFileEnc(filename, doc, "iso-8859-1");
- if (res == -1) {
- warn_user("HotlistSaveError", 0);
- xmlFreeDoc(doc);
- return false;
- }
-
- xmlFreeDoc(doc);
- return true;
-}
-
-
-/**
- * Add a directory to the HTML tree for saving.
- *
- * \param directory hotlist directory to add
- * \param node node to add ul to
- * \return true on success, false on memory exhaustion
- */
-bool options_save_tree_directory(struct node *directory, xmlNode *node) {
- struct node *child;
- xmlNode *ul, *h4;
-
- ul = xmlNewChild(node, NULL, (const xmlChar *) "ul", NULL);
- if (!ul)
- return false;
-
- for (child = directory->child; child; child = child->next) {
- if (!child->folder) {
- /* entry */
- if (!options_save_tree_entry(child, ul))
- return false;
- } else {
- /* directory */
- /* invalid HTML */
- h4 = xmlNewTextChild(ul, NULL,
- (const xmlChar *) "h4",
- (const xmlChar *) child->data.text);
- if (!h4)
- return false;
-
- if (!options_save_tree_directory(child, ul))
- return false;
- } }
-
- return true;
-}
-
-
-/**
- * Add an entry to the HTML tree for saving.
- *
- * The node must contain a sequence of node_elements in the following order:
- *
- * \param entry hotlist entry to add
- * \param node node to add li to
- * \return true on success, false on memory exhaustion
- */
-bool options_save_tree_entry(struct node *entry, xmlNode *node) {
- xmlNode *li, *a;
- xmlAttr *href;
- struct node_element *element;
-
- li = xmlNewChild(node, NULL, (const xmlChar *) "li", NULL);
- if (!li)
- return false;
-
- a = xmlNewTextChild(li, NULL, (const xmlChar *) "a",
- (const xmlChar *) entry->data.text);
- if (!a)
- return false;
-
- element = tree_find_element(entry, TREE_ELEMENT_URL);
- if (!element)
- return false;
- href = xmlNewProp(a, (const xmlChar *) "href",
- (const xmlChar *) element->text);
- if (!href)
- return false;
- return true;
-}
diff --git a/desktop/options.h b/desktop/options.h
index ca92ee90a..2779692b6 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -85,6 +85,7 @@ extern int option_toolbar_status_width;
extern int option_scale;
extern bool option_incremental_reflow;
extern unsigned int option_min_reflow_period;
+extern char *option_tree_icons_dir;
extern bool option_core_select_menu;
extern int option_margin_top;
@@ -114,8 +115,4 @@ void options_read(const char *path);
void options_write(const char *path);
void options_dump(void);
-struct tree *options_load_tree(const char *filename);
-bool options_save_tree(struct tree *tree, const char *filename,
- const char *page_title);
-
#endif
diff --git a/desktop/sslcert.c b/desktop/sslcert.c
new file mode 100644
index 000000000..2d10b4719
--- /dev/null
+++ b/desktop/sslcert.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * SSL Certificate verification UI (implementation)
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "content/content.h"
+#include "content/fetch.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/sslcert.h"
+#include "desktop/tree.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+/** Flags for each type of ssl tree node. */
+enum tree_element_ssl {
+ TREE_ELEMENT_SSL_VERSION = 0x01,
+ TREE_ELEMENT_SSL_VALID_FROM = 0x02,
+ TREE_ELEMENT_SSL_VALID_TO = 0x03,
+ TREE_ELEMENT_SSL_CERT_TYPE = 0x04,
+ TREE_ELEMENT_SSL_SERIAL = 0x05,
+ TREE_ELEMENT_SSL_ISSUER = 0x06,
+};
+
+/** ssl certificate verification context. */
+struct sslcert_session_data {
+ unsigned long num; /**< The number of ssl certificates in the chain */
+ char *url; /**< The url of the certificate */
+ struct tree *tree; /**< The root of the treeview */
+ llcache_query_response cb; /**< callback when cert is accepted or rejected */
+ void *cbpw; /**< context passed to callback */
+};
+
+/** Handle for the window icon. */
+static hlcache_handle *sslcert_icon;
+
+/** Initialise ssl certificate window. */
+void sslcert_init(void)
+{
+ sslcert_icon = tree_load_icon(tree_content_icon_name);
+}
+
+
+/**
+ * Get flags with which the sslcert tree should be created;
+ *
+ * \return the flags
+ */
+unsigned int sslcert_get_tree_flags(void)
+{
+ return TREE_NO_DRAGS | TREE_NO_SELECT;
+}
+
+
+void sslcert_cleanup(void)
+{
+ return;
+}
+
+struct sslcert_session_data *
+sslcert_create_session_data(unsigned long num,
+ const char *url,
+ llcache_query_response cb,
+ void *cbpw)
+{
+ struct sslcert_session_data *data;
+
+ data = malloc(sizeof(struct sslcert_session_data));
+ if (data == NULL) {
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+ data->url = strdup(url);
+ if (data->url == NULL) {
+ free(data);
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+ data->num = num;
+ data->cb = cb;
+ data->cbpw = cbpw;
+
+ return data;
+}
+
+static node_callback_resp sslcert_node_callback(void *user_data,
+ struct node_msg_data *msg_data)
+{
+ if (msg_data->msg == NODE_DELETE_ELEMENT_IMG)
+ return NODE_CALLBACK_HANDLED;
+ return NODE_CALLBACK_NOT_HANDLED;
+}
+
+static struct node *sslcert_create_node(const struct ssl_cert_info *cert)
+{
+ struct node *node;
+ struct node_element *element;
+ char *text;
+
+ text = messages_get_buff("SSL_Certificate_Subject", cert->subject);
+ if (text == NULL)
+ return NULL;
+
+ node = tree_create_leaf_node(NULL, NULL, text, false, false, false);
+ if (node == NULL) {
+ free(text);
+ return NULL;
+ }
+ tree_set_node_user_callback(node, sslcert_node_callback, NULL);
+
+ /* add issuer node */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_ISSUER, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_Issuer", cert->issuer);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+ /* add version node */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_VERSION, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_Version", cert->version);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+ /* add valid from node */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_VALID_FROM, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_ValidFrom", cert->not_before);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+
+ /* add valid to node */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_VALID_TO, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_ValidTo", cert->not_after);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+ /* add certificate type */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_CERT_TYPE, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_Type", cert->cert_type);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+ /* add serial node */
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_SSL_SERIAL, false);
+ if (element != NULL) {
+ text = messages_get_buff("SSL_Certificate_Serial", cert->serial);
+ if (text == NULL) {
+ tree_delete_node(NULL, node, false);
+ return NULL;
+ }
+ tree_update_node_element(NULL, element, text, NULL);
+ }
+
+ /* set the display icon */
+ tree_set_node_icon(NULL, node, sslcert_icon);
+
+ return node;
+}
+
+bool sslcert_load_tree(struct tree *tree,
+ const struct ssl_cert_info *certs,
+ struct sslcert_session_data *data)
+{
+ struct node *tree_root;
+ struct node *node;
+ unsigned long cert_loop;
+
+ assert(data != NULL && certs != NULL && tree != NULL);
+
+ tree_root = tree_get_root(tree);
+
+ for (cert_loop = 0; cert_loop < data->num; cert_loop++) {
+ node = sslcert_create_node(&(certs[cert_loop]));
+ if (node != NULL) {
+ /* There is no problem creating the node
+ * add an entry for it in the root of the
+ * treeview .
+ */
+ tree_link_node(tree, tree_root, node, false);
+ }
+ }
+
+ data->tree = tree;
+
+ return tree;
+
+}
+
+
+static void sslcert_cleanup_session(struct sslcert_session_data *session)
+{
+ assert(session != NULL);
+
+ free(session->url);
+ free(session);
+}
+
+
+
+bool sslcert_reject(struct sslcert_session_data *session)
+{
+ session->cb(false, session->cbpw);
+ sslcert_cleanup_session(session);
+ return true;
+}
+
+
+/**
+ * Handle acceptance of certificate
+ */
+bool sslcert_accept(struct sslcert_session_data *session)
+{
+ assert(session != NULL);
+
+ urldb_set_cert_permissions(session->url, true);
+
+ session->cb(true, session->cbpw);
+
+ sslcert_cleanup_session(session);
+
+ return true;
+}
diff --git a/desktop/sslcert.h b/desktop/sslcert.h
new file mode 100644
index 000000000..bc1b8bef8
--- /dev/null
+++ b/desktop/sslcert.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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_DESKTOP_SSLCERT_H_
+#define _NETSURF_DESKTOP_SSLCERT_H_
+
+#include <stdbool.h>
+
+#include "desktop/tree.h"
+
+struct sslcert_session_data;
+
+void sslcert_init(void);
+unsigned int sslcert_get_tree_flags(void);
+void sslcert_cleanup(void);
+
+struct sslcert_session_data *sslcert_create_session_data(unsigned long num,
+ const char *url, llcache_query_response cb, void *cbpw);
+bool sslcert_load_tree(struct tree *tree,
+ const struct ssl_cert_info *certs,
+ struct sslcert_session_data *data);
+
+bool sslcert_reject(struct sslcert_session_data *session);
+bool sslcert_accept(struct sslcert_session_data *session);
+
+
+#endif
diff --git a/desktop/tree.c b/desktop/tree.c
index 295bef195..36ba38d7e 100644
--- a/desktop/tree.c
+++ b/desktop/tree.c
@@ -1,5 +1,6 @@
/*
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -25,135 +26,367 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "content/urldb.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/textarea.h"
+#include "desktop/textinput.h"
#include "desktop/tree.h"
#include "desktop/options.h"
+#include "desktop/plotters.h"
+#include "render/font.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
+#include "utils/url.h"
+
+typedef enum {
+ TREE_NO_DRAG = 0,
+ TREE_SELECT_DRAG,
+ TREE_MOVE_DRAG
+} tree_drag_type;
+
+
+#define MAXIMUM_URL_LENGTH 1024
+
+#define TREE_ICON_SIZE 16
+#define NODE_INSTEP 20
+#define TREE_TEXT_HEIGHT 20
+#define FURNITURE_COLOUR 0x888888
+
+static plot_font_style_t plot_fstyle = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 10240,
+ .weight = 400,
+ .flags = FONTF_NONE,
+ .background = 0xFFFFFF,
+ .foreground = 0x000000
+};
+
+static plot_font_style_t plot_fstyle_selected = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 10240,
+ .weight = 400,
+ .flags = FONTF_NONE,
+ .background = 0x000000,
+ .foreground = 0xEEEEEE
+};
+
+struct node;
+struct tree;
+
+struct node_element_box {
+ int x; /**< X offset from origin */
+ int y; /**< Y offset from origin */
+ int width; /**< Element width */
+ int height; /**< Element height */
+};
+
+struct node_element {
+ struct node *parent; /**< Parent node */
+ node_element_type type; /**< Element type */
+ struct node_element_box box; /**< Element bounding box */
+ const char *text; /**< Text for the element */
+ void *bitmap; /**< Bitmap for the element */
+ struct node_element *next; /**< Next node element */
+ unsigned int flag; /**< Client specified flag for data
+ being represented */
+ bool editable; /**< Whether the node text can be
+ * modified, editable text is deleted
+ * without noticing the tree user
+ */
+};
+
+struct node {
+ bool selected; /**< Whether the node is selected */
+ bool expanded; /**< Whether the node is expanded */
+ bool folder; /**< Whether the node is a folder */
+ bool retain_in_memory; /**< Whether the node remains
+ in memory after deletion */
+ bool deleted; /**< Whether the node is currently
+ deleted */
+ bool processing; /**< Internal flag used when moving */
+ struct node_element_box box; /**< Bounding box of all elements */
+ struct node_element data; /**< Data to display */
+ struct node *parent; /**< Parent entry (NULL for root) */
+ struct node *child; /**< First child */
+ struct node *last_child; /**< Last child */
+ struct node *previous; /**< Previous child of the parent */
+ struct node *next; /**< Next child of the parent */
+
+ /** Sorting function for the node (for folder nodes only) */
+ int (*sort) (struct node *, struct node *);
+ /** Gets called for each deleted node_element and on node launch */
+ tree_node_user_callback user_callback;
+ /** User data to be passed to delete_callback */
+ void *callback_data;
+};
+
+struct tree {
+ /* These coordinates are only added to the coordinates passed to the
+ plotters. This means they are invisible to the tree, what has to be
+ taken into account i.e in keyboard/mouse event passing */
+ struct node *root; /* Tree root element */
+ int width; /* Tree width */
+ int height; /* Tree height */
+ unsigned int flags; /* Tree flags */
+ struct text_area *textarea; /* Handle for UTF-8 textarea */
+ bool textarea_drag_start; /* whether the start of a mouse drag
+ was in the textarea */
+ struct node_element *editing; /* Node element being edited */
+
+ bool redraw; /* Flag indicating whether the tree
+ should be redrawn on layout
+ changes */
+ tree_drag_type drag;
+ const struct treeview_table *callbacks;
+ void *client_data; /* User assigned data for the
+ callbacks */
+};
-static void tree_draw_node(struct tree *tree, struct node *node, int clip_x,
- int clip_y, int clip_width, int clip_height);
-static struct node_element *tree_create_node_element(struct node *parent,
- node_element_data data);
-static void tree_delete_node_internal(struct tree *tree, struct node *node, bool siblings);
-static int tree_get_node_width(struct node *node);
-static int tree_get_node_height(struct node *node);
-static void tree_handle_selection_area_node(struct tree *tree,
- struct node *node, int x, int y, int width, int height,
- bool invert);
-static void tree_selected_to_processing(struct node *node);
-void tree_clear_processing(struct node *node);
-struct node *tree_move_processing_node(struct node *node, struct node *link,
- bool before, bool first);
-struct node *tree_create_leaf_node_shared(struct node *parent, const char *title);
-static int tree_initialising = 0;
+/**
+ * Creates and initialises a new tree.
+ *
+ * \param flags flag word for flags to create the new tree with
+ * \param redraw_request function to be called each time the tree wants to
+ * be redrawn
+ * \param client_data data to be passed to start_redraw and end_redraw
+ * \param root gets updated to point at the root of the tree,
+ * if not NULL
+ * \return the newly created tree, or NULL on memory exhaustion
+ */
+struct tree *tree_create(unsigned int flags,
+ const struct treeview_table *callbacks, void *client_data)
+{
+ struct tree *tree;
+ char *title;
+
+ tree = calloc(sizeof(struct tree), 1);
+ if (tree == NULL) {
+ LOG(("calloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ title = strdup("Root");
+ if (title == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ free(tree);
+ return NULL;
+ }
+ tree->root = tree_create_folder_node(NULL, NULL, title,
+ false, false, false);
+ if (tree->root == NULL) {
+ free(title);
+ free(tree);
+ return NULL;
+ }
+ tree->root->expanded = true;
+
+ tree->width = 0;
+ tree->height = 0;
+ tree->flags = flags;
+ tree->textarea = NULL;
+ tree->textarea_drag_start = false;
+ tree->editing = NULL;
+ tree->redraw = false;
+ tree->drag = TREE_NO_DRAG;
+ tree->callbacks = callbacks;
+ tree->client_data = client_data;
+
+ return tree;
+}
/**
- * Initialises a user-created tree
+ * Recalculates the dimensions of a node element.
*
- * \param tree the tree to initialise
+ * \param tree the tree to which the element belongs, may be NULL
+ * \param element the element to recalculate
*/
-void tree_initialise(struct tree *tree) {
+static void tree_recalculate_node_element(struct tree *tree,
+ struct node_element *element)
+{
+ struct bitmap *bitmap = NULL;
+ int width, height;
- assert(tree);
+ assert(element != NULL);
- tree_set_node_expanded(tree, tree->root, true);
- tree_initialise_nodes(tree, tree->root);
- tree_recalculate_node_positions(tree, tree->root);
- tree_set_node_expanded(tree, tree->root, false);
- tree->root->expanded = true;
- tree_recalculate_node_positions(tree, tree->root);
- tree_recalculate_size(tree);
+ switch (element->type) {
+ case NODE_ELEMENT_TEXT_PLUS_ICON:
+ case NODE_ELEMENT_TEXT:
+ if(element->text == NULL)
+ break;
+
+ if (tree != NULL && element == tree->editing) {
+ textarea_get_dimensions(tree->textarea,
+ &element->box.width, NULL);
+ } else {
+ nsfont.font_width(&plot_fstyle,
+ element->text,
+ strlen(element->text),
+ &element->box.width);
+ }
+
+ element->box.width += 8;
+ element->box.height = TREE_TEXT_HEIGHT;
+
+ if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ element->box.width += NODE_INSTEP;
+
+ break;
+
+ case NODE_ELEMENT_BITMAP:
+ bitmap = element->bitmap;
+ if (bitmap != NULL) {
+ width = bitmap_get_width(bitmap);
+ height = bitmap_get_height(bitmap);
+ element->box.width = width + 1;
+ element->box.height = height + 2;
+ } else {
+ element->box.width = 0;
+ element->box.height = 0;
+ }
+ break;
+ }
}
/**
- * Initialises a user-created node structure
+ * Calculates the height of a node including any children
*
- * \param root the root node to update from
+ * \param node the node to calculate the height of
+ * \return the total height of the node and children
*/
-void tree_initialise_nodes(struct tree *tree, struct node *root) {
- struct node *node;
+static int tree_get_node_height(struct node *node)
+{
+ int y1;
- assert(root);
+ assert(node != NULL);
- tree_initialising++;
- for (node = root; node; node = node->next) {
- tree_recalculate_node(tree, node, true);
- if (node->child) {
- tree_initialise_nodes(tree, node->child);
- }
+ if ((node->child == NULL) || (node->expanded == false)) {
+ return node->box.height;
+ }
+
+ y1 = node->box.y;
+ if (y1 < 0) {
+ y1 = 0;
}
- tree_initialising--;
+ node = node->child;
- if (tree_initialising == 0)
- tree_recalculate_node_positions(tree, root);
+ while ((node->next != NULL) ||
+ ((node->child != NULL) && (node->expanded))) {
+ for (; node->next != NULL; node = node->next);
+
+ if ((node->child != NULL) && (node->expanded)) {
+ node = node->child;
+ }
+ }
+ return node->box.y + node->box.height - y1;
}
/**
- * Recalculate the node data and redraw the relevant section of the tree.
+ * Calculates the width of a node including any children
*
- * \param tree the tree to redraw
- * \param node the node to update
- * \param recalculate_sizes whether the elements have changed
- * \param expansion the request is the result of a node expansion
+ * \param node the node to calculate the height of
+ * \return the total width of the node and children
*/
-void tree_handle_node_changed(struct tree *tree, struct node *node,
- bool recalculate_sizes, bool expansion) {
- int width, height;
+static int tree_get_node_width(struct node *node)
+{
+ int width = 0;
+ int child_width;
- assert(node);
+ assert(node != NULL);
- if ((expansion) && (node->expanded) && (node->child)) {
- tree_set_node_expanded(tree, node->child, false);
- tree_set_node_selected(tree, node->child, false);
- }
+ for (; node != NULL; node = node->next) {
+ if (width < (node->box.x + node->box.width)) {
+ width = node->box.x + node->box.width;
+ }
- width = node->box.width;
- height = node->box.height;
- if ((recalculate_sizes) || (expansion))
- tree_recalculate_node(tree, node, true);
- if ((node->box.height != height) || (expansion)) {
- tree_recalculate_node_positions(tree, tree->root);
- tree_redraw_area(tree, 0, node->box.y, 16384, 16384);
- } else {
- width = (width > node->box.width) ? width : node->box.width;
- tree_redraw_area(tree, node->box.x, node->box.y, width, node->box.height);
+ if ((node->child != NULL) && (node->expanded)) {
+ child_width = tree_get_node_width(node->child);
+ if (width < child_width) {
+ width = child_width;
+ }
+ }
}
- if ((recalculate_sizes) || (expansion))
- tree_recalculate_size(tree);
+ return width;
}
/**
- * Recalculate the node element and redraw the relevant section of the tree.
- * The tree size is not updated.
+ * Recalculates the position of a node, its siblings and children.
*
- * \param tree the tree to redraw
- * \param element the node element to update
+ * \param tree the tree to which 'root' belongs
+ * \param root the root node to update from
*/
-void tree_handle_node_element_changed(struct tree *tree, struct node_element *element) {
- int width, height;
+static void tree_recalculate_node_positions(struct tree *tree,
+ struct node *root)
+{
+ struct node *parent;
+ struct node *node;
+ struct node *child;
+ struct node_element *element;
+ int y;
+ bool has_icon;
- assert(element);
+ for (node = root; node != NULL; node = node->next) {
- width = element->box.width;
- height = element->box.height;
- tree_recalculate_node_element(element);
+ parent = node->parent;
+
+ if (node->previous != NULL) {
+ node->box.x = node->previous->box.x;
+ node->box.y = node->previous->box.y +
+ tree_get_node_height(node->previous);
+ } else if (parent != NULL) {
+ node->box.x = parent->box.x + NODE_INSTEP;
+ node->box.y = parent->box.y +
+ parent->box.height;
+ for (child = parent->child; child != node;
+ child = child->next)
+ node->box.y += child->box.height;
+ } else {
+ node->box.x = tree->flags & TREE_NO_FURNITURE
+ ? -NODE_INSTEP + 4 : 0;
+ node->box.y = -20;
+ }
+
+ if (!node->expanded) {
+ node->data.box.x = node->box.x;
+ node->data.box.y = node->box.y;
+ continue;
+ }
+
+ if (node->folder) {
+ node->data.box.x = node->box.x;
+ node->data.box.y = node->box.y;
+ tree_recalculate_node_positions(tree, node->child);
+ } else {
+ y = node->box.y;
+ has_icon = false;
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ if (element->type ==
+ NODE_ELEMENT_TEXT_PLUS_ICON) {
+ has_icon = true;
+ break;
+ }
+
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ element->box.x = node->box.x;
+ if (element->type !=
+ NODE_ELEMENT_TEXT_PLUS_ICON &&
+ has_icon)
+ element->box.x += NODE_INSTEP;
+ element->box.y = y;
+ y += element->box.height;
+ }
+ }
- if (element->box.height != height) {
- tree_recalculate_node(tree, element->parent, false);
- tree_redraw_area(tree, 0, element->box.y, 16384, 16384);
- } else {
- if (element->box.width != width)
- tree_recalculate_node(tree, element->parent, false);
- width = (width > element->box.width) ? width :
- element->box.width;
- tree_redraw_area(tree, element->box.x, element->box.y, width, element->box.height);
}
}
@@ -161,520 +394,1279 @@ void tree_handle_node_element_changed(struct tree *tree, struct node_element *el
/**
* Recalculates the size of a node.
*
- * \param node the node to update
- * \param recalculate_sizes whether the node elements have changed
+ * \param tree the tree to which node belongs, may be NULL
+ * \param node the node to update
+ * \param recalculate_sizes whether the node elements have changed
*/
-void tree_recalculate_node(struct tree *tree, struct node *node, bool recalculate_sizes) {
+static void tree_recalculate_node_sizes(struct tree *tree, struct node *node,
+ bool recalculate_sizes)
+{
struct node_element *element;
- int height;
+ int width, height;
- assert(node);
+ assert(node != NULL);
+ width = node->box.width;
height = node->box.height;
node->box.width = 0;
node->box.height = 0;
if (node->expanded) {
- for (element = &node->data; element; element = element->next) {
+ for (element = &node->data; element != NULL;
+ element = element->next) {
if (recalculate_sizes)
- tree_recalculate_node_element(element);
- node->box.width = (node->box.width >
- element->box.x + element->box.width - node->box.x) ?
+ tree_recalculate_node_element(tree, element);
+ node->box.width = (node->box.width > element->box.x +
+ element->box.width - node->box.x) ?
node->box.width :
- element->box.width + element->box.x - node->box.x;
+ element->box.width + element->box.x -
+ node->box.x;
node->box.height += element->box.height;
}
} else {
if (recalculate_sizes)
- for (element = &node->data; element; element = element->next)
- tree_recalculate_node_element(element);
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ tree_recalculate_node_element(tree, element);
else
- tree_recalculate_node_element(&node->data);
+ tree_recalculate_node_element(tree, &node->data);
node->box.width = node->data.box.width;
node->box.height = node->data.box.height;
}
- if (height != node->box.height) {
- for (; node->parent; node = node->parent);
- if (tree_initialising == 0)
- tree_recalculate_node_positions(tree, node);
+ if (tree != NULL && height != node->box.height)
+ tree_recalculate_node_positions(tree, tree->root);
+}
+
+
+/**
+ * Creates a folder node with the specified title, and optionally links it into
+ * the tree.
+ *
+ * \param tree the owner tree of 'parent', may be NULL
+ * \param parent the parent node, or NULL not to link
+ * \param title the node title (not copied, used directly)
+ * \param editable if true, the node title will be editable
+ * \param retain_in_memory if true, the node will stay in memory after deletion
+ * \param deleted if true, the node is created with the deleted flag
+ * \return the newly created node.
+ */
+struct node *tree_create_folder_node(struct tree *tree, struct node *parent,
+ const char *title, bool editable, bool retain_in_memory,
+ bool deleted)
+{
+ struct node *node;
+
+ assert(title != NULL);
+
+ node = calloc(sizeof(struct node), 1);
+ if (node == NULL) {
+ LOG(("calloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
}
+ node->folder = true;
+ node->retain_in_memory = retain_in_memory;
+ node->deleted = deleted;
+ node->data.parent = node;
+ node->data.type = NODE_ELEMENT_TEXT;
+ node->data.text = title;
+ node->data.flag = TREE_ELEMENT_TITLE;
+ node->data.editable = editable;
+ node->sort = NULL;
+ node->user_callback = NULL;
+
+ tree_recalculate_node_sizes(tree, node, true);
+ if (parent != NULL)
+ tree_link_node(tree, parent, node, false);
+
+ return node;
}
/**
- * Recalculates the position of a node, its siblings and children.
+ * Creates a leaf node with the specified title, and optionally links it into
+ * the tree.
*
- * \param root the root node to update from
+ * \param tree the owner tree of 'parent', may be NULL
+ * \param parent the parent node, or NULL not to link
+ * \param title the node title (not copied, used directly)
+ * \param editable if true, the node title will be editable
+ * \param retain_in_memory if true, the node will stay in memory after deletion
+ * \param deleted if true, the node is created with the deleted flag
+ * \return the newly created node.
*/
-void tree_recalculate_node_positions(struct tree *tree, struct node *root) {
- struct node *parent;
+struct node *tree_create_leaf_node(struct tree *tree, struct node *parent,
+ const char *title, bool editable, bool retain_in_memory,
+ bool deleted)
+{
struct node *node;
- struct node *child;
+
+ assert(title != NULL);
+
+ node = calloc(sizeof(struct node), 1);
+ if (node == NULL) {
+ LOG(("calloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ node->folder = false;
+ node->retain_in_memory = retain_in_memory;
+ node->deleted = deleted;
+ node->data.parent = node;
+ node->data.type = NODE_ELEMENT_TEXT;
+ node->data.text = title;
+ node->data.flag = TREE_ELEMENT_TITLE;
+ node->data.editable = editable;
+ node->sort = NULL;
+ node->user_callback = NULL;
+
+ tree_recalculate_node_sizes(tree, node, true);
+ if (parent != NULL)
+ tree_link_node(tree, parent, node, false);
+
+ return node;
+}
+
+
+/**
+ * Creates an empty text node element and links it to a node.
+ *
+ * \param parent the parent node
+ * \param type the required element type
+ * \param flag user assigned flag used for searches
+ * \return the newly created element.
+ */
+struct node_element *tree_create_node_element(struct node *parent,
+ node_element_type type, unsigned int flag, bool editable)
+{
struct node_element *element;
- int y;
- for (node = root; node; node = node->next) {
- if (node->previous) {
- node->box.x = node->previous->box.x;
- node->box.y = node->previous->box.y +
- tree_get_node_height(node->previous);
- } else if ((parent = node->parent)) {
- node->box.x = parent->box.x + NODE_INSTEP;
- node->box.y = parent->box.y +
- parent->box.height;
- for (child = parent->child; child != node;
- child = child->next)
- node->box.y += child->box.height;
+ element = calloc(sizeof(struct node_element), 1);
+ if (element == NULL)
+ return NULL;
+
+ element->parent = parent;
+ element->flag = flag;
+ element->type = type;
+ element->editable = editable;
+ element->next = parent->data.next;
+ parent->data.next = element;
+
+ return element;
+}
+
+
+/**
+ * Inserts a node into the correct place according to the parent's sort function
+ *
+ * \param parent the node whose child node 'node' becomes
+ * \param node the node to be inserted
+ */
+static void tree_sort_insert(struct node *parent, struct node *node)
+{
+ struct node *after;
+
+ assert(node != NULL);
+ assert(parent != NULL);
+ assert(parent->sort != NULL);
+
+ after = parent->last_child;
+ while ((after != NULL) &&
+ (parent->sort(node, after) == -1))
+ after = after->previous;
+
+ if (after != NULL) {
+ if (after->next != NULL)
+ after->next->previous = node;
+ node->next = after->next;
+ node->previous = after;
+ after->next = node;
+ } else {
+ node->previous = NULL;
+ node->next = parent->child;
+ if (parent->child != NULL) {
+ parent->child->previous = node;
+ }
+ parent->child = node;
+ }
+
+ if (node->next == NULL)
+ parent->last_child = node;
+
+ node->parent = parent;
+}
+
+
+/**
+ * Recalculates the size of a tree.
+ *
+ * \param tree the tree to recalculate
+ */
+static void tree_recalculate_size(struct tree *tree)
+{
+ int width, height;
+
+ assert(tree != NULL);
+
+ width = tree->width;
+ height = tree->height;
+
+ tree->width = tree_get_node_width(tree->root);
+ tree->height = tree_get_node_height(tree->root);
+
+ if ((width != tree->width) || (height != tree->height))
+ tree->callbacks->resized(tree, tree->width, tree->height,
+ tree->client_data);
+}
+
+/**
+ * Recalculate the node data and redraw the relevant section of the tree.
+ *
+ * \param tree the tree to redraw, may be NULL
+ * \param node the node to update
+ * \param recalculate_sizes whether the elements have changed
+ * \param expansion the request is the result of a node expansion
+ */
+static void tree_handle_node_changed(struct tree *tree, struct node *node,
+ bool recalculate_sizes, bool expansion)
+{
+ int width, height, tree_height;
+
+ assert(node != NULL);
+
+ width = node->box.width;
+ height = node->box.height;
+ tree_height = tree->height;
+
+ if ((recalculate_sizes) || (expansion)) {
+ tree_recalculate_node_sizes(tree, node, true);
+ }
+
+ if (tree != NULL) {
+ if ((node->box.height != height) || (expansion)) {
+ tree_recalculate_node_positions(tree, tree->root);
+ tree_recalculate_size(tree);
+ tree_height = (tree_height > tree->height) ?
+ tree_height : tree->height;
+ if (tree->redraw) {
+ tree->callbacks->redraw_request(0, node->box.y,
+ tree->width,
+ tree_height - node->box.y,
+ tree->client_data);
+ }
} else {
- node->box.x = tree->no_furniture ? -NODE_INSTEP + 4 : 0;
- node->box.y = -40;
+ width = (width > node->box.width) ?
+ width : node->box.width;
+ if (tree->redraw)
+ tree->callbacks->redraw_request(node->box.x,
+ node->box.y,
+ width, node->box.height,
+ tree->client_data);
+ if (recalculate_sizes) {
+ tree_recalculate_size(tree);
+ }
}
- if (node->expanded) {
- if (node->folder) {
- node->data.box.x = node->box.x;
- node->data.box.y = node->box.y;
- tree_recalculate_node_positions(tree, node->child);
+ }
+}
+
+
+/**
+ * Links a node to another node.
+ *
+ * \param tree the tree in which the link takes place, may be NULL
+ * \param link the node to link before/as a child (folders)
+ * or before/after (link)
+ * \param node the node to link
+ * \param before whether to link siblings before or after the supplied node
+ */
+void tree_link_node(struct tree *tree, struct node *link, struct node *node,
+ bool before)
+{
+
+ struct node *parent;
+ bool sort = false;
+
+ assert(link != NULL);
+ assert(node != NULL);
+
+ if ((link->folder == 0) || (before)) {
+ parent = node->parent = link->parent;
+ if (parent->sort) {
+ sort = true;
+ } else {
+ if (before) {
+ node->next = link;
+ node->previous = link->previous;
+ if (link->previous != NULL)
+ link->previous->next = node;
+ link->previous = node;
+ if ((parent != NULL) && (parent->child == link))
+ parent->child = node;
} else {
- y = node->box.y;
- for (element = &node->data; element;
- element = element->next) {
- if (element->type == NODE_ELEMENT_TEXT_PLUS_SPRITE) {
- element->box.x = node->box.x;
- } else {
- element->box.x = node->box.x + NODE_INSTEP;
- }
- element->box.y = y;
- y += element->box.height;
- }
+ node->previous = link;
+ node->next = link->next;
+ if (link->next != NULL)
+ link->next->previous = node;
+ link->next = node;
+ if ((parent != NULL) &&
+ (parent->last_child == link))
+ parent->last_child = node;
}
+ }
+ } else {
+ parent = node->parent = link;
+ if (parent->sort != NULL) {
+ sort = true;
} else {
- node->data.box.x = node->box.x;
- node->data.box.y = node->box.y;
+ node->next = NULL;
+ if (link->child == NULL) {
+ link->child = link->last_child = node;
+ node->previous = NULL;
+ } else {
+ link->last_child->next = node;
+ node->previous = link->last_child;
+ link->last_child = node;
+ }
}
+
}
+
+ if (sort) {
+ tree_sort_insert(parent, node);
+ }
+
+ tree_handle_node_changed(tree, link, false, true);
+
+ node->deleted = false;
}
/**
- * Calculates the width of a node including any children
+ * Recalculate the node element and redraw the relevant section of the tree.
+ * The tree size is not updated.
*
- * \param node the node to calculate the height of
- * \return the total width of the node and children
+ * \param tree the tree to redraw, may be NULL
+ * \param element the node element to update
*/
-int tree_get_node_width(struct node *node) {
- int width = 0;
- int child_width;
+static void tree_handle_node_element_changed(struct tree *tree,
+ struct node_element *element)
+{
+ int width, height;
- assert(node);
+ assert(element != NULL);
- for (; node; node = node->next) {
- if (width < (node->box.x + node->box.width))
- width = node->box.x + node->box.width;
- if ((node->child) && (node->expanded)) {
- child_width = tree_get_node_width(node->child);
- if (width < child_width)
- width = child_width;
+ width = element->box.width;
+ height = element->box.height;
+ tree_recalculate_node_element(tree, element);
+
+ if (element->box.height != height) {
+ tree_recalculate_node_sizes(tree, element->parent, false);
+ if ((tree != NULL) && (tree->redraw)) {
+ tree->callbacks->redraw_request(0, element->box.y,
+ tree->width + element->box.width -
+ width,
+ tree->height - element->box.y +
+ element->box.height - height,
+ tree->client_data);
+ }
+ } else {
+ if (element->box.width != width) {
+ tree_recalculate_node_sizes(tree, element->parent,
+ false);
+ }
+
+ if (tree != NULL) {
+ width = (width > element->box.width) ? width :
+ element->box.width;
+ if (tree->redraw) {
+ tree->callbacks->redraw_request(element->box.x,
+ element->box.y,
+ width,
+ element->box.height,
+ tree->client_data);
+ }
}
}
- return width;
}
/**
- * Calculates the height of a node including any children
+ * Stops editing a node_element
*
- * \param node the node to calculate the height of
- * \return the total height of the node and children
+ * \param tree The tree to stop editing for
+ * \param keep_changes If true the changes made to the text will be kept,
+ * if false they will be dropped
*/
-int tree_get_node_height(struct node *node) {
- int y1;
+static void tree_stop_edit(struct tree *tree, bool keep_changes)
+{
+ int text_len;
+ char *text = NULL;
+ struct node_element *element;
+ struct node_msg_data msg_data;
+ node_callback_resp response;
- assert(node);
+ assert(tree != NULL);
- if ((node->child) && (node->expanded)) {
- y1 = node->box.y;
- if (y1 < 0)
- y1 = 0;
- node = node->child;
- while ((node->next) || ((node->child) && (node->expanded))) {
- for (; node->next; node = node->next);
- if ((node->child) && (node->expanded))
- node = node->child;
+ if (tree->editing == NULL || tree->textarea == NULL)
+ return;
+
+ element = tree->editing;
+
+ if (keep_changes) {
+ text_len = textarea_get_text(tree->textarea, NULL, 0);
+ text = malloc(text_len * sizeof(char));
+ if (text == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ textarea_destroy(tree->textarea);
+ tree->textarea = NULL;
+ return;
}
- return node->box.y + node->box.height - y1;
- } else {
- return node->box.height;
+ textarea_get_text(tree->textarea, text, text_len);
+ }
+
+
+ if (keep_changes && element->parent->user_callback != NULL) {
+ msg_data.msg = NODE_ELEMENT_EDIT_FINISHING;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ msg_data.data.text = text;
+ response = element->parent->user_callback(
+ element->parent->callback_data,
+ &msg_data);
+
+ switch (response) {
+ case NODE_CALLBACK_REJECT:
+ free(text);
+ text = NULL;
+ break;
+ case NODE_CALLBACK_CONTINUE:
+ free(text);
+ text = NULL;
+ return;
+ case NODE_CALLBACK_HANDLED:
+ case NODE_CALLBACK_NOT_HANDLED:
+ text = msg_data.data.text;
+ break;
+ }
+ }
+
+ textarea_destroy(tree->textarea);
+ tree->textarea = NULL;
+ tree->editing = NULL;
+
+ if (text != NULL)
+ tree_update_node_element(tree, element, text, NULL);
+ else
+ tree_handle_node_element_changed(tree, element);
+
+
+ tree_recalculate_size(tree);
+ if (element->parent->user_callback != NULL) {
+ msg_data.msg = NODE_ELEMENT_EDIT_FINISHED;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ element->parent->user_callback(element->parent->callback_data,
+ &msg_data);
+ }
+}
+
+
+/**
+ * Delinks a node from the tree structures.
+ *
+ * \param tree the tree in which the delink takes place, may be NULL
+ * \param node the node to delink
+ */
+void tree_delink_node(struct tree *tree, struct node *node)
+{
+ struct node *parent;
+
+ assert(node != NULL);
+
+ /* do not remove the root */
+ if (tree != NULL && node == tree->root)
+ return;
+ if ((tree != NULL) && (tree->editing != NULL)) {
+ parent = tree->editing->parent;
+ while (parent != NULL) {
+ if (node == parent) {
+ tree_stop_edit(tree, false);
+ break;
+ }
+ parent = parent->parent;
+ }
+ }
+
+ if (node->parent->child == node)
+ node->parent->child = node->next;
+ if (node->parent->last_child == node)
+ node->parent->last_child = node->previous;
+ parent = node->parent;
+ node->parent = NULL;
+
+ if (node->previous != NULL)
+ node->previous->next = node->next;
+ if (node->next != NULL)
+ node->next->previous = node->previous;
+ node->previous = NULL;
+ node->next = NULL;
+
+ tree_handle_node_changed(tree, parent, false, true);
+}
+
+
+/**
+ * Deletes a node from the tree.
+ *
+ * \param tree the tree to delete from, may be NULL
+ * \param node the node to delete
+ * \param siblings whether to delete all siblings
+ */
+static void tree_delete_node_internal(struct tree *tree, struct node *node,
+ bool siblings)
+{
+ struct node *next, *child, *parent;
+ struct node_element *e, *f;
+ node_callback_resp response;
+ struct node_msg_data msg_data;
+
+ assert(node != NULL);
+
+ if (tree != NULL && tree->root == node)
+ return;
+
+ next = node->next;
+ parent = node->parent;
+ if (tree != NULL && parent == tree->root)
+ parent = NULL;
+ tree_delink_node(tree, node);
+ child = node->child;
+ node->child = NULL;
+
+ node->deleted = true;
+ if (child != NULL)
+ tree_delete_node_internal(tree, child, true);
+
+ if (!node->retain_in_memory) {
+ node->retain_in_memory = true;
+ for (e = &node->data; e != NULL; e = f) {
+ if (e->text != NULL) {
+ response = NODE_CALLBACK_NOT_HANDLED;
+ if (!e->editable &&
+ node->user_callback != NULL) {
+ msg_data.msg = NODE_DELETE_ELEMENT_TXT;
+ msg_data.flag = e->flag;
+ msg_data.node = node;
+ msg_data.data.text = (void *)e->text;
+ response = node->user_callback(
+ node->callback_data,
+ &msg_data);
+ }
+ if (response != NODE_CALLBACK_HANDLED)
+ free((void *)e->text);
+ e->text = NULL;
+ }
+ if (e->bitmap != NULL) {
+ response = NODE_CALLBACK_NOT_HANDLED;
+ if (node->user_callback != NULL) {
+ msg_data.msg = NODE_DELETE_ELEMENT_IMG;
+ msg_data.flag = e->flag;
+ msg_data.node = node;
+ msg_data.data.bitmap =
+ (void *)e->bitmap;
+ response = node->user_callback(
+ node->callback_data,
+ &msg_data);
+ }
+ /* TODO the type of this field is platform
+ dependent */
+ if (response != NODE_CALLBACK_HANDLED)
+ free(e->bitmap);
+ e->bitmap = NULL;
+ }
+ f = e->next;
+ if (e != &node->data)
+ free(e);
+ }
+ free(node);
}
+
+ if (siblings && next)
+ tree_delete_node_internal(tree, next, true);
+ if ((tree->flags & TREE_DELETE_EMPTY_DIRS) && parent != NULL &&
+ parent->child == NULL && !parent->deleted)
+ tree_delete_node_internal(tree, parent, false);
+}
+
+
+/**
+ * Deletes all nodes of a tree and the tree itself.
+ *
+ * \param tree the tree to be deleted
+ */
+void tree_delete(struct tree *tree)
+{
+ tree_set_redraw(tree, false);
+ if (tree->root->child != NULL)
+ tree_delete_node_internal(tree, tree->root->child, true);
+
+ free((void *)tree->root->data.text);
+ free(tree->root);
+ free(tree);
+}
+
+
+/**
+ * Gets the redraw property of the given tree.
+ *
+ * \param tree the tree for which to retrieve the property
+ * \return the redraw property of the tree
+ */
+bool tree_get_redraw(struct tree *tree)
+{
+ return tree->redraw;
}
/**
- * Updates all siblinds and descendants of a node to an expansion state.
+ * Deletes a node from the tree.
+ *
+ * \param tree the tree to delete from, may be NULL
+ * \param node the node to delete
+ * \param siblings whether to delete all siblings
+ */
+void tree_delete_node(struct tree *tree, struct node *node, bool siblings)
+{
+ int y = node->box.y;
+ tree_delete_node_internal(tree, node, siblings);
+ tree_recalculate_node_positions(tree, tree->root);
+ if (tree->redraw)
+ tree->callbacks->redraw_request(0, y, tree->width, tree->height,
+ tree->client_data);
+ tree_recalculate_size(tree);
+}
+
+
+/**
+ * Sets an icon for a node
+ *
+ * \param tree The tree to which node belongs, may be NULL
+ * \param node The node for which the icon is set
+ * \param icon the image to use
+ */
+void tree_set_node_icon(struct tree *tree, struct node *node,
+ hlcache_handle *icon)
+{
+ node->data.type = NODE_ELEMENT_TEXT_PLUS_ICON;
+ tree_update_node_element(tree, &(node->data), NULL, icon);
+}
+
+
+/**
+ * Updates all siblings and descendants of a node to an expansion state.
* No update is performed for the tree changes.
*
- * \param node the node to set all siblings and descendants of
- * \param expanded the expansion state to set
+ * \param tree the tree to which 'node' belongs
+ * \param node the node to set all siblings and descendants of
+ * \param expanded the expansion state to set
*/
-void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded) {
- for (; node; node = node->next) {
+static void tree_set_node_expanded_all(struct tree *tree, struct node *node,
+ bool expanded)
+{
+ for (; node != NULL; node = node->next) {
if (node->expanded != expanded) {
node->expanded = expanded;
- tree_recalculate_node(tree, node, false);
+ tree_recalculate_node_sizes(tree, node, false);
}
- if ((node->child) && (node->expanded))
- tree_set_node_expanded(tree, node->child, expanded);
+ if ((node->child != NULL) && (node->expanded))
+ tree_set_node_expanded_all(tree, node->child, expanded);
}
}
/**
- * Updates all siblinds and descendants of a node to an expansion state.
+ * Updates [all siblings and descendants of] a node to an expansion state.
*
* \param tree the tree to update
- * \param node the node to set all siblings and descendants of
+ * \param node the node to set [all siblings and descendants of]
* \param expanded the expansion state to set
- * \param folder whether to update folders
- * \param leaf whether to update leaves
- * \return whether any changes were made
+ * \param folder whether to update folders, if this together with leaf
+ * will be false only 'node' will be updated
+ * \param leaf whether to update leaves (check also description for folder)
+ * \return whether any changes were made
*/
-bool tree_handle_expansion(struct tree *tree, struct node *node, bool expanded, bool folder,
- bool leaf) {
- struct node *entry = node;
+static bool tree_set_node_expanded_internal(struct tree *tree,
+ struct node *node, bool expanded, bool folder, bool leaf)
+{
bool redraw = false;
+ struct node *end = (folder == false && leaf == false) ?
+ node->next : NULL;
+
+ if (tree->editing != NULL && node == tree->editing->parent)
+ tree_stop_edit(tree, false);
- for (; node; node = node->next) {
+ for (; node != end; node = node->next) {
if ((node->expanded != expanded) && (node != tree->root) &&
- ((folder && (node->folder)) || (leaf && (!node->folder)))) {
+ ((folder && (node->folder)) ||
+ (leaf && (!node->folder)) ||
+ (!folder && !leaf))) {
node->expanded = expanded;
- if (node->child)
- tree_set_node_expanded(tree, node->child, false);
- if ((node->data.next) && (node->data.next->box.height == 0))
- tree_recalculate_node(tree, node, true);
+ if (node->child != NULL)
+ tree_set_node_expanded_all(tree,
+ node->child, false);
+ if ((node->data.next != NULL) &&
+ (node->data.next->box.height == 0))
+ tree_recalculate_node_sizes(tree, node, true);
else
- tree_recalculate_node(tree, node, false);
+ tree_recalculate_node_sizes(tree, node, false);
redraw = true;
}
- if ((node->child) && (node->expanded))
- redraw |= tree_handle_expansion(tree, node->child, expanded, folder, leaf);
- }
- if ((entry == tree->root) && (redraw)) {
- tree_recalculate_node_positions(tree, tree->root);
- tree_redraw_area(tree, 0, 0, 16384, 16384);
- tree_recalculate_size(tree);
+ if ((folder || leaf) && (node->child != NULL) &&
+ (node->expanded))
+ redraw |= tree_set_node_expanded_internal(tree,
+ node->child, expanded, folder, leaf);
}
return redraw;
}
/**
- * Updates all siblinds and descendants of a node to an selected state.
- * The required areas of the tree are redrawn.
+ * Updates [all siblings and descendants of] a node to an expansion state.
+ *
+ * \param tree the tree to update
+ * \param node the node to set [all siblings and descendants of]
+ * \param expanded the expansion state to set
+ * \param folder whether to update folders, if this together with leaf
+ * will be false only 'node' will be updated
+ * \param leaf whether to update leaves (check also description for folder)
+ */
+void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded,
+ bool folder, bool leaf)
+{
+ if (tree_set_node_expanded_internal(tree, node, expanded, folder, leaf))
+ tree_handle_node_changed(tree, node, false, true);
+}
+
+
+/**
+ * Updates a node to an selected state. The required areas of the tree are
+ * redrawn.
*
- * \param tree the tree to update nodes for
+ * \param tree the tree to update nodes for, may be NULL
* \param node the node to set all siblings and descendants of
+ * \param all if true update node together with its siblings and
+ * descendants
* \param selected the selection state to set
*/
-void tree_set_node_selected(struct tree *tree, struct node *node, bool selected) {
- for (; node; node = node->next) {
- if ((node->selected != selected) && (node != tree->root)) {
+void tree_set_node_selected(struct tree *tree, struct node *node, bool all,
+ bool selected)
+{
+ struct node *end;
+
+ if (tree != NULL && node == tree->root)
+ node = tree->root->child;
+ if (node == NULL)
+ return;
+
+ end = all ? NULL : node->next;
+
+ for (; node != end; node = node->next) {
+ if (node->selected != selected) {
node->selected = selected;
- tree_redraw_area(tree, node->box.x, node->box.y, node->box.width,
- node->data.box.height);
+ if (tree != NULL && tree->redraw)
+ tree->callbacks->redraw_request(node->box.x,
+ node->box.y,
+ node->box.width,
+ node->data.box.height,
+ tree->client_data);
}
- if ((node->child) && (node->expanded))
- tree_set_node_selected(tree, node->child, selected);
+ if (all && (node->child != NULL) && (node->expanded))
+ tree_set_node_selected(tree, node->child, all,
+ selected);
}
}
/**
- * Finds a node at a specific location.
+ * Sets the sort function for a node
*
- * \param root the root node to check from
- * \param x the x co-ordinate
- * \param y the y co-ordinate
- * \param furniture whether the returned area was in an elements furniture
- * \return the node at the specified position, or NULL for none
+ * \param tree the tree to which 'node' belongs, may be NULL
+ * \param node the node to be inserted
+ * \param sort pointer to the sorting function
*/
-struct node *tree_get_node_at(struct node *root, int x, int y, bool *furniture) {
- struct node_element *result;
+void tree_set_node_sort_function(struct tree *tree, struct node *node,
+ int (*sort) (struct node *, struct node *))
+{
+ struct node *child;
- if ((result = tree_get_node_element_at(root, x, y, furniture)))
- return result->parent;
- return NULL;
+ node->sort = sort;
+
+ if (tree != NULL && tree->editing != NULL)
+ tree_stop_edit(tree, false);
+
+ /* the node had already some children so they must get sorted */
+ if (node->child != NULL) {
+
+ child = node->child;
+ node->child = NULL;
+
+ while (child != NULL) {
+ tree_sort_insert(node, child);
+ child = child->next;
+ }
+
+ }
+
+ if (tree != NULL)
+ tree_recalculate_node_positions(tree, node->child);
}
/**
- * Finds a node element at a specific location.
+ * Sets the delete callback for a node.
*
- * \param node the root node to check from
- * \param x the x co-ordinate
- * \param y the y co-ordinate
- * \param furniture whether the returned area was in an elements furniture
- * \return the node at the specified position, or NULL for none
+ * \param node the node for which the callback is set
+ * \param callback the callback functions to be set
+ * \param data user data to be passed to callback
*/
-struct node_element *tree_get_node_element_at(struct node *node, int x, int y,
- bool *furniture) {
- struct node_element *element;
+void tree_set_node_user_callback(struct node *node,
+ tree_node_user_callback callback, void *data)
+{
+ node->user_callback = callback;
+ node->callback_data = data;
+}
- *furniture = false;
- for (; node; node = node->next) {
- if (node->box.y > y) return NULL;
- if ((node->box.x - NODE_INSTEP < x) && (node->box.y < y) &&
- (node->box.x + node->box.width >= x) &&
- (node->box.y + node->box.height >= y)) {
- if (node->expanded) {
- for (element = &node->data; element;
- element = element->next) {
- if ((element->box.x < x) && (element->box.y < y) &&
- (element->box.x + element->box.width >= x) &&
- (element->box.y + element->box.height >= y))
- return element;
- }
- } else if ((node->data.box.x < x) &&
- (node->data.box.y < y) &&
- (node->data.box.x + node->data.box.width >= x) &&
- (node->data.box.y + node->data.box.height >= y))
- return &node->data;
- if (((node->child) || (node->data.next)) &&
- (node->data.box.x - NODE_INSTEP + 8 < x) &&
- (node->data.box.y + 8 < y) &&
- (node->data.box.x > x) &&
- (node->data.box.y + 32 > y)) {
- *furniture = true;
- return &node->data;
- }
- }
- if ((node->child) && (node->expanded) &&
- ((element = tree_get_node_element_at(node->child, x, y,
- furniture))))
- return element;
+/**
+ * Sets the redraw property to the given value. If redraw is true, the tree will
+ * be redrawn on layout/appearance changes.
+ *
+ * \param tree the tree for which the property is set
+ * \param redraw the value to set
+ */
+void tree_set_redraw(struct tree *tree, bool redraw)
+{
+ /* the tree might have no graphical representation, do not set the
+ redraw flag in such case */
+ if (tree->callbacks == NULL)
+ return;
+ tree->redraw = redraw;
+}
+
+
+/**
+ * Checks whether a node, its siblings or any children are selected.
+ *
+ * \param node the root node to check from
+ * \return whether 'node', its siblings or any children are selected.
+ */
+bool tree_node_has_selection(struct node *node)
+{
+ for (; node != NULL; node = node->next) {
+ if (node->selected)
+ return true;
+ if ((node->child != NULL) && (node->expanded) &&
+ (tree_node_has_selection(node->child)))
+ return true;
}
- return NULL;
+ return false;
}
/**
- * Finds a node element from a node with a specific user_type
+ * Returns the current value of the nodes deleted property.
*
- * \param node the node to examine
- * \param user_type the user_type to check for
- * \return the corresponding element
+ * \param node the node to be checked
+ * \return the current value of the nodes deleted property
*/
-struct node_element *tree_find_element(struct node *node, node_element_data data) {
- struct node_element *element;
- for (element = &node->data; element; element = element->next)
- if (element->data == data) return element;
- return NULL;
+bool tree_node_is_deleted(struct node *node)
+{
+ return node->deleted;
}
/**
- * Moves nodes within a tree.
+ * Returns true if the node is a folder
*
- * \param tree the tree to process
- * \param link the node to link before/as a child (folders) or before/after (link)
- * \param before whether to link siblings before or after the supplied node
+ * \param node the node to be checked
+ * \return true if the node is a folder, false otherwise
*/
-void tree_move_selected_nodes(struct tree *tree, struct node *destination, bool before) {
- struct node *link;
- struct node *test;
- bool error;
+bool tree_node_is_folder(struct node *node)
+{
+ return node->folder;
+}
- tree_clear_processing(tree->root);
- tree_selected_to_processing(tree->root);
- /* the destination node cannot be a child of any node with the processing flag set */
- error = destination->processing;
- for (test = destination; test; test = test->parent)
- error |= test->processing;
- if (error) {
- tree_clear_processing(tree->root);
- return;
- }
- if ((destination->folder) && (!destination->expanded) && (!before)) {
- destination->expanded = true;
- tree_handle_node_changed(tree, destination, false, true);
+/**
+ * Update the text of a node element if it has changed.
+ *
+ * \param element The node element to update.
+ * \param text The text to update the element with. The ownership of
+ * this string is taken by this function and must not be
+ * referred to after the function exits.
+ */
+bool tree_update_element_text(struct tree *tree,
+ struct node_element *element, char *text)
+{
+ const char *node_text; /* existing node text */
+
+ if (text == NULL)
+ return false;
+
+ if (element == NULL) {
+ free(text);
+ return false;
}
- link = tree_move_processing_node(tree->root, destination, before, true);
- while (link)
- link = tree_move_processing_node(tree->root, link, false, false);
- tree_clear_processing(tree->root);
- tree_recalculate_node_positions(tree, tree->root);
- tree_redraw_area(tree, 0, 0, 16384, 16384);
+ node_text = tree_node_element_get_text(element);
+
+ if ((node_text == NULL) || (strcmp(node_text, text) != 0)) {
+ tree_update_node_element(tree, element, text, NULL);
+ } else {
+ /* text does not need changing, free it */
+ free(text);
+ }
+ return true;
}
/**
- * Sets the processing flag to the selection state.
+ * Updates the content of a node_element.
*
- * \param node the node to process siblings and children of
+ * \param tree the tree owning element, may be NULL
+ * \param element the element to be updated
+ * \param text new text to be set, may be NULL
+ * \param bitmap new bitmap to be set, may be NULL
*/
-void tree_selected_to_processing(struct node *node) {
- for (; node; node = node->next) {
- node->processing = node->selected;
- if ((node->child) && (node->expanded))
- tree_selected_to_processing(node->child);
+void tree_update_node_element(struct tree *tree, struct node_element *element,
+ const char *text, void *bitmap)
+{
+ node_callback_resp response;
+ struct node_msg_data msg_data;
+
+ assert(element != NULL);
+
+ if (tree != NULL && element == tree->editing)
+ tree_stop_edit(tree, false);
+
+ if (text != NULL && (element->type == NODE_ELEMENT_TEXT ||
+ element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
+ if (element->text != NULL) {
+ response = NODE_CALLBACK_NOT_HANDLED;
+ if (!element->editable &&
+ element->parent->user_callback !=
+ NULL) {
+ msg_data.msg = NODE_DELETE_ELEMENT_TXT;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ msg_data.data.text = (void *)element->text;
+ response = element->parent->user_callback(
+ element->parent->callback_data,
+ &msg_data);
+ }
+ if (response != NODE_CALLBACK_HANDLED)
+ free((void *)element->text);
+ }
+ element->text = text;
+ }
+
+ if (bitmap != NULL && (element->type == NODE_ELEMENT_BITMAP ||
+ element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
+ if (element->bitmap != NULL) {
+ response = NODE_CALLBACK_NOT_HANDLED;
+ if (element->parent->user_callback != NULL) {
+ msg_data.msg = NODE_DELETE_ELEMENT_IMG;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ msg_data.data.bitmap = (void *)element->bitmap;
+ response = element->parent->user_callback(
+ element->parent->callback_data,
+ &msg_data);
+ }
+ if (response != NODE_CALLBACK_HANDLED)
+ free(element->bitmap);
+ }
+ element->bitmap = bitmap;
}
+
+ tree_handle_node_element_changed(tree, element);
}
/**
- * Clears the processing flag.
+ * Returns the node element's text
*
- * \param node the node to process siblings and children of
+ * \return the node element's text
*/
-void tree_clear_processing(struct node *node) {
- for (; node; node = node->next) {
- node->processing = false;
- if (node->child)
- tree_clear_processing(node->child);
- }
+const char *tree_node_element_get_text(struct node_element *element)
+{
+ return element->text;
}
/**
- * Moves the first node in a tree with the processing flag set.
+ * Get the root node of a tree
*
- * \param tree the node to move siblings/children of
- * \param link the node to link before/as a child (folders) or before/after (link)
- * \param before whether to link siblings before or after the supplied node
- * \param first whether to always link after the supplied node (ie not inside of folders)
- * \return the node moved
+ * \param tree the tree to get the root of
+ * \return the root of the tree
*/
-struct node *tree_move_processing_node(struct node *node, struct node *link, bool before,
- bool first) {
- struct node *result;
+struct node *tree_get_root(struct tree *tree)
+{
+ return tree->root;
+}
- bool folder = link->folder;
- for (; node; node = node->next) {
- if (node->processing) {
- node->processing = false;
- tree_delink_node(node);
- if (!first)
- link->folder = false;
- tree_link_node(link, node, before);
- if (!first)
- link->folder = folder;
- return node;
- }
- if (node->child) {
- result = tree_move_processing_node(node->child, link, before, first);
- if (result)
- return result;
- }
- }
- return NULL;
+
+/**
+ * Returns whether the current tree is being edited at this time
+ *
+ * \param tree the tree to be checked
+ * \return true if the tree is currently being edited
+ */
+bool tree_is_edited(struct tree *tree)
+{
+ return tree->editing == NULL ? false : true;
}
+
/**
- * Checks whether a node, its siblings or any children are selected.
+ * Returns the first child of a node
*
- * \param node the root node to check from
+ * \param node the node to get the child of
+ * \return the nodes first child
*/
-bool tree_has_selection(struct node *node) {
- for (; node; node = node->next) {
- if (node->selected)
- return true;
- if ((node->child) && (node->expanded) &&
- (tree_has_selection(node->child)))
- return true;
- }
- return false;
+struct node *tree_node_get_child(struct node *node)
+{
+ return node->child;
}
/**
- * Updates the selected state for a region of nodes.
+ * Returns the closest sibling a node
*
- * \param tree the tree to update
- * \param x the minimum x of the selection rectangle
- * \param y the minimum y of the selection rectangle
- * \param width the width of the selection rectangle
- * \param height the height of the selection rectangle
- * \param invert whether to invert the selected state
+ * \param node the node to get the sibling of
+ * \return the nodes sibling
*/
-void tree_handle_selection_area(struct tree *tree, int x, int y, int width, int height,
- bool invert) {
- assert(tree);
- assert(tree->root);
+struct node *tree_node_get_next(struct node *node)
+{
+ return node->next;
+}
- if (!tree->root->child) return;
- if (width < 0) {
- x += width;
- width = -width;
- }
- if (height < 0) {
- y += height;
- height = -height;
+/**
+ * Draws an elements expansion icon
+ *
+ * \param tree the tree to draw the expansion for
+ * \param element the element to draw the expansion for
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
+ */
+static void tree_draw_node_expansion(struct tree *tree, struct node *node,
+ int tree_x, int tree_y)
+{
+ int x, y;
+
+ assert(tree != NULL);
+ assert(node != NULL);
+
+ if ((node->child != NULL) || (node->data.next != NULL)) {
+ x = tree_x + node->box.x - (NODE_INSTEP / 2) - 4;
+ y = tree_y + node->box.y - (TREE_TEXT_HEIGHT / 2) + 16;
+ plot.rectangle(x, y, x + 9, y + 9, plot_style_fill_white);
+ plot.rectangle(x , y, x + 8, y + 8,
+ plot_style_stroke_darkwbasec);
+ plot.line(x + 2, y + 4, x + 7, y + 4,
+ plot_style_stroke_darkwbasec);
+ if (!node->expanded)
+ plot.line(x + 4, y + 2, x + 4, y + 7,
+ plot_style_stroke_darkwbasec);
+
}
- tree_handle_selection_area_node(tree, tree->root->child, x, y, width, height, invert);
}
/**
- * Updates the selected state for a region of nodes.
+ * Draws an element, including any expansion icons
*
- * \param tree the tree to update
- * \param node the node to update children and siblings of
- * \param x the minimum x of the selection rectangle
- * \param y the minimum y of the selection rectangle
- * \param width the width of the selection rectangle
- * \param height the height of the selection rectangle
- * \param invert whether to invert the selected state
+ * \param tree the tree to draw an element for
+ * \param element the element to draw
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
*/
-void tree_handle_selection_area_node(struct tree *tree, struct node *node, int x, int y,
- int width, int height, bool invert) {
+static void tree_draw_node_element(struct tree *tree,
+ struct node_element *element, int tree_x, int tree_y)
+{
+
+ struct bitmap *bitmap = NULL;
+ int x, y, width;
+ bool selected = false;
+ hlcache_handle *icon;
+ plot_font_style_t *fstyle;
+
+ assert(tree != NULL);
+ assert(element != NULL);
+ assert(element->parent != NULL);
+
+ x = tree_x + element->box.x;
+ y = tree_y + element->box.y;
+ width = element->box.width;
+ if (&element->parent->data == element)
+ if (element->parent->selected)
+ selected = true;
+
+ switch (element->type) {
+ case NODE_ELEMENT_TEXT_PLUS_ICON:
+ icon = element->bitmap;
+ if (icon != NULL &&
+ (content_get_status(icon) ==
+ CONTENT_STATUS_READY ||
+ content_get_status(icon) ==
+ CONTENT_STATUS_DONE)) {
+ content_redraw(icon , x, y + 3,
+ TREE_ICON_SIZE, TREE_ICON_SIZE,
+ x, y, x + TREE_ICON_SIZE,
+ y + TREE_ICON_SIZE, 1, 0);
+ }
+
+ x += NODE_INSTEP;
+ width -= NODE_INSTEP;
+
+ /* fall through */
+ case NODE_ELEMENT_TEXT:
+ if (element->text == NULL)
+ break;
+
+ if (element == tree->editing)
+ return;
+
+ if (selected) {
+ fstyle = &plot_fstyle_selected;
+ plot.rectangle(x, y, x + width,
+ y + element->box.height,
+ plot_style_fill_black);
+ } else {
+ fstyle = &plot_fstyle;
+ plot.rectangle(x, y, x + width,
+ y + element->box.height,
+ plot_style_fill_white);
+ }
+
+ plot.text(x + 4, y + TREE_TEXT_HEIGHT * 0.75,
+ element->text, strlen(element->text),
+ fstyle);
+ break;
+ case NODE_ELEMENT_BITMAP:
+ bitmap = element->bitmap;
+ if (bitmap == NULL)
+ break;
+ plot.bitmap(x, y, element->box.width - 1,
+ element->box.height - 2,
+ bitmap, 0xFFFFFF, BITMAPF_NONE);
+ if (!(tree->flags & TREE_NO_FURNITURE))
+ plot.rectangle(x, y, x + element->box.width - 1,
+ y + element->box.height - 3,
+ plot_style_stroke_darkwbasec);
+
+ break;
+ }
+
+}
+
+/**
+ * Redraws a node.
+ *
+ * \param tree the tree to draw
+ * \param node the node to draw children and siblings of
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
+ * \param clip_x the minimum x of the clipping rectangle
+ * \param clip_y the minimum y of the clipping rectangle
+ * \param clip_width the width of the clipping rectangle
+ * \param clip_height the height of the clipping rectangle
+ */
+static void tree_draw_node(struct tree *tree, struct node *node,
+ int tree_x, int tree_y,
+ int clip_x, int clip_y,
+ int clip_width, int clip_height)
+{
struct node_element *element;
- struct node *update;
+ struct node *parent;
int x_max, y_max;
+ int x0, y0, x1, y1;
- assert(tree);
- assert(node);
+ assert(tree != NULL);
+ assert(node != NULL);
- x_max = x + width;
- y_max = y + height;
- for (; node; node = node->next) {
+ x_max = clip_x + clip_width + NODE_INSTEP;
+ y_max = clip_y + clip_height;
+
+ if ((node->parent->next != NULL) &&
+ (node->parent->next->box.y < clip_y))
+ return;
+
+ for (; node != NULL; node = node->next) {
if (node->box.y > y_max) return;
+ if ((node->next != NULL) &&
+ (!(tree->flags & TREE_NO_FURNITURE))) {
+ x0 = x1 = tree_x + node->box.x - (NODE_INSTEP / 2);
+ y0 = tree_y + node->box.y + (20 / 2);
+ y1 = y0 + node->next->box.y - node->box.y;
+ plot.line(x0, y0, x1, y1, plot_style_stroke_darkwbasec);
+ }
if ((node->box.x < x_max) && (node->box.y < y_max) &&
- (node->box.x + node->box.width + NODE_INSTEP >= x) &&
- (node->box.y + node->box.height >= y)) {
- update = NULL;
- if (node->expanded) {
- for (element = &node->data; element;
- element = element->next) {
- if ((element->box.x < x_max) && (element->box.y < y_max) &&
- (element->box.x + element->box.width >= x) &&
- (element->box.y + element->box.height >= y)) {
- update = element->parent;
- break;
- }
+ (node->box.x + node->box.width
+ + NODE_INSTEP >= clip_x) &&
+ (node->box.y + node->box.height >= clip_y)) {
+ if (!(tree->flags & TREE_NO_FURNITURE)) {
+ if ((node->expanded) && (node->child != NULL)) {
+ x0 = x1 = tree_x + node->box.x +
+ (NODE_INSTEP / 2);
+ y0 = tree_y + node->data.box.y
+ + node->data.box.height;
+ y1 = y0 + (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
+
}
- } else if ((node->data.box.x < x_max) &&
- (node->data.box.y < y_max) &&
- (node->data.box.x + node->data.box.width >= x) &&
- (node->data.box.y + node->data.box.height >= y))
- update = node->data.parent;
- if ((update) && (node != tree->root)) {
- if (invert) {
- node->selected = !node->selected;
- tree_handle_node_element_changed(tree, &node->data);
- } else if (!node->selected) {
- node->selected = true;
- tree_handle_node_element_changed(tree, &node->data);
+ parent = node->parent;
+ if ((parent != NULL) &&
+ (parent != tree->root) &&
+ (parent->child == node)) {
+ x0 = x1 = tree_x + parent->box.x +
+ (NODE_INSTEP / 2);
+ y0 = tree_y + parent->data.box.y +
+ parent->data.box.height;
+ y1 = y0 + (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
}
+ x0 = tree_x + node->box.x - (NODE_INSTEP / 2);
+ x1 = x0 + (NODE_INSTEP / 2) - 2;
+ y0 = y1 = tree_y + node->data.box.y +
+ node->data.box.height -
+ (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
+ tree_draw_node_expansion(tree, node,
+ tree_x, tree_y);
}
+ if (node->expanded)
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ tree_draw_node_element(tree, element,
+ tree_x, tree_y);
+ else
+ tree_draw_node_element(tree, &node->data,
+ tree_x, tree_y);
}
- if ((node->child) && (node->expanded))
- tree_handle_selection_area_node(tree, node->child, x, y, width, height,
- invert);
+ if ((node->child != NULL) && (node->expanded))
+ tree_draw_node(tree, node->child, tree_x, tree_y,
+ clip_x, clip_y,
+ clip_width, clip_height);
}
}
@@ -682,87 +1674,214 @@ void tree_handle_selection_area_node(struct tree *tree, struct node *node, int x
/**
* Redraws a tree.
*
- * \param tree the tree to draw
- * \param clip_x the minimum x of the clipping rectangle
- * \param clip_y the minimum y of the clipping rectangle
- * \param clip_width the width of the clipping rectangle
- * \param clip_height the height of the clipping rectangle
+ * \param tree the tree to draw
+ * \param x X coordinate to draw the tree at
+ * \param y Y coordinate to draw the tree at
+ * \param clip_x the minimum x of the clipping rectangle relative to
+ * the tree origin
+ * \param clip_y the minimum y of the clipping rectangle relative to
+ * the tree origin
+ * \param clip_width the width of the clipping rectangle
+ * \param clip_height the height of the clipping rectangle
*/
-void tree_draw(struct tree *tree, int clip_x, int clip_y, int clip_width,
- int clip_height) {
- assert(tree);
- assert(tree->root);
+void tree_draw(struct tree *tree, int x, int y,
+ int clip_x, int clip_y, int clip_width, int clip_height)
+{
+ int absolute_x, absolute_y;
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+
+ /* don't draw empty trees or trees with redraw flag set to false */
+ if (tree->root->child == NULL || !tree->redraw) return;
+
+ absolute_x = x + clip_x;
+ absolute_y = y + clip_y;
+ plot.rectangle(absolute_x, absolute_y,
+ absolute_x + clip_width, absolute_y + clip_height,
+ plot_style_fill_white);
+ plot.clip(absolute_x, absolute_y,
+ absolute_x + clip_width, absolute_y + clip_height);
+ tree_draw_node(tree, tree->root->child, x, y, clip_x,
+ clip_y, clip_width, clip_height);
+ if (tree->editing != NULL) {
+ x = x + tree->editing->box.x;
+ y = y + tree->editing->box.y;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x += NODE_INSTEP;
+ textarea_redraw(tree->textarea, x, y, absolute_x, absolute_y,
+ absolute_x + clip_width,
+ absolute_y + clip_height);
+ }
+}
+
- if (!tree->root->child) return;
+/**
+ * Finds a node element from a node with a specific user_type
+ *
+ * \param node the node to examine
+ * \param flag user assinged flag used is searches
+ * \param after if this is not NULL the search will start after the given
+ * node_element
+ * \return the corresponding element
+ */
+struct node_element *tree_node_find_element(struct node *node,
+ unsigned int flag, struct node_element *after)
+{
+ struct node_element *element;
- tree_initialise_redraw(tree);
- tree_draw_node(tree, tree->root->child, clip_x,
- clip_y, clip_width, clip_height);
+ if (after == NULL)
+ element = &node->data;
+ else {
+ assert(after->parent == node);
+ element = after->next;
+ }
+
+ for (; element != NULL; element = element->next)
+ if (element->flag == flag) return element;
+
+ return NULL;
}
/**
- * Redraws a node.
+ * Deletes all selected nodes from the tree.
*
- * \param tree the tree to draw
- * \param node the node to draw children and siblings of
- * \param clip_x the minimum x of the clipping rectangle
- * \param clip_y the minimum y of the clipping rectangle
- * \param clip_width the width of the clipping rectangle
- * \param clip_height the height of the clipping rectangle
+ * \param tree the tree to delete from
+ * \param node the node to delete
*/
-void tree_draw_node(struct tree *tree, struct node *node, int clip_x, int clip_y,
- int clip_width, int clip_height) {
+void tree_delete_selected_nodes(struct tree *tree, struct node *node)
+{
+ struct node *next;
- struct node_element *element;
- int x_max, y_max;
+ if (node == tree->root) {
+ if (node->child != NULL)
+ tree_delete_selected_nodes(tree, node->child);
+ return;
+ }
- assert(tree);
- assert(node);
+ while (node != NULL) {
+ next = node->next;
+ if (node->selected)
+ tree_delete_node(tree, node, false);
+ else if (node->child != NULL)
+ tree_delete_selected_nodes(tree, node->child);
+ node = next;
+ }
+}
- x_max = clip_x + clip_width + NODE_INSTEP;
- y_max = clip_y + clip_height;
- if ((node->parent->next) && (node->parent->next->box.y < clip_y))
- return;
+/**
+ * Returns the selected node, or NULL if multiple nodes are selected.
+ *
+ * \param node the node to search sibling and children
+ * \return the selected node, or NULL if multiple nodes are selected
+ */
+struct node *tree_get_selected_node(struct node *node)
+{
+ struct node *result = NULL;
+ struct node *temp;
- for (; node; node = node->next) {
- if (node->box.y > y_max) return;
- if ((node->next) && (!tree->no_furniture))
- tree_draw_line(node->box.x - (NODE_INSTEP / 2),
- node->box.y + (40 / 2), 0,
- node->next->box.y - node->box.y);
- if ((node->box.x < x_max) && (node->box.y < y_max) &&
- (node->box.x + node->box.width + NODE_INSTEP >= clip_x) &&
- (node->box.y + node->box.height >= clip_y)) {
- if (!tree->no_furniture) {
- if ((node->expanded) && (node->child))
- tree_draw_line(node->box.x + (NODE_INSTEP / 2),
- node->data.box.y + node->data.box.height, 0,
- (40 / 2));
- if ((node->parent) && (node->parent != tree->root) &&
- (node->parent->child == node))
- tree_draw_line(node->parent->box.x + (NODE_INSTEP / 2),
- node->parent->data.box.y +
- node->parent->data.box.height, 0,
- (40 / 2));
- tree_draw_line(node->box.x - (NODE_INSTEP / 2),
- node->data.box.y +
- node->data.box.height - (40 / 2),
- (NODE_INSTEP / 2) - 4, 0);
- tree_draw_node_expansion(tree, node);
+ for (; node != NULL; node = node->next) {
+ if (node->selected) {
+ if (result != NULL)
+ return NULL;
+ result = node;
+ }
+ if ((node->child != NULL) && (node->expanded)) {
+ temp = tree_get_selected_node(node->child);
+ if (temp != NULL) {
+ if (result != NULL)
+ return NULL;
+ else
+ result = temp;
+ }
+ }
+ }
+ return result;
+}
+
+
+/**
+ * Finds a node element at a specific location.
+ *
+ * \param node the root node to check from
+ * \param x the x co-ordinate
+ * \param y the y co-ordinate
+ * \param furniture whether the returned area was in an elements furniture
+ * \return the node at the specified position, or NULL for none
+ */
+static struct node_element *tree_get_node_element_at(struct node *node,
+ int x, int y, bool *furniture)
+{
+ struct node_element *element;
+ int x0, x1, y0, y1;
+
+ *furniture = false;
+ for (; node != NULL; node = node->next) {
+ if (node->box.y > y) return NULL;
+ if ((node->box.x - NODE_INSTEP < x) && (node->box.y < y) &&
+ (node->box.x + node->box.width >= x) &&
+ (node->box.y + node->box.height >= y)) {
+ if (node->expanded) {
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ x0 = element->box.x;
+ y0 = element->box.y;
+ x1 = element->box.x +
+ element->box.width;
+ y1 = element->box.y +
+ element->box.height;
+ if ((x0 < x) && (y0 < y) && (x1 >= x)
+ && (y1 >= y))
+ return element;
+ }
+ } else {
+ x0 = node->data.box.x;
+ y0 = node->data.box.y;
+ x1 = node->data.box.x + node->data.box.width;
+ y1 = node->data.box.y + node->data.box.height;
+ if ((x0 < x) && (y0 < y) && (x1 >= x) &&
+ (y1>= y))
+ return &node->data;
+ }
+ if (((node->child != NULL) ||
+ (node->data.next != NULL)) &&
+ (node->data.box.x - NODE_INSTEP + 4 < x)
+ && (node->data.box.y + 4 < y) &&
+ (node->data.box.x > x) &&
+ (node->data.box.y + 20 > y)) {
+ *furniture = true;
+ return &node->data;
}
- if (node->expanded)
- for (element = &node->data; element;
- element = element->next)
- tree_draw_node_element(tree, element);
- else
- tree_draw_node_element(tree, &node->data);
}
- if ((node->child) && (node->expanded))
- tree_draw_node(tree, node->child, clip_x, clip_y, clip_width,
- clip_height);
+
+ element = tree_get_node_element_at(node->child, x, y,
+ furniture);
+ if ((node->child != NULL) && (node->expanded) &&
+ (element != NULL))
+ return element;
}
+ return NULL;
+}
+
+
+/**
+ * Finds a node at a specific location.
+ *
+ * \param root the root node to check from
+ * \param x the x co-ordinate
+ * \param y the y co-ordinate
+ * \param furniture whether the returned area was in an elements furniture
+ * \return the node at the specified position, or NULL for none
+ */
+static struct node *tree_get_node_at(struct node *root, int x, int y,
+ bool *furniture)
+{
+ struct node_element *result;
+
+ if ((result = tree_get_node_element_at(root, x, y, furniture)))
+ return result->parent;
+ return NULL;
}
@@ -773,24 +1892,27 @@ void tree_draw_node(struct tree *tree, struct node *node, int clip_x, int clip_y
* \param x the x co-ordinate
* \param y the y co-ordinate
* \param before set to whether the node should be linked before on exit
- * \return the node to link with
+ * \return the node to link with
*/
-struct node *tree_get_link_details(struct tree *tree, int x, int y, bool *before) {
+struct node *tree_get_link_details(struct tree *tree, int x, int y,
+ bool *before)
+{
struct node *node = NULL;
bool furniture;
- assert(tree);
- assert(tree->root);
+ assert(tree != NULL);
+ assert(tree->root != NULL);
*before = false;
- if (tree->root->child)
+ if (tree->root->child != NULL)
node = tree_get_node_at(tree->root->child, x, y, &furniture);
- if ((!node) || (furniture))
+ if ((node == NULL) || (furniture))
return tree->root;
if (y < (node->box.y + (node->box.height / 2))) {
*before = true;
- } else if ((node->folder) && (node->expanded) && (node->child)) {
+ } else if ((node->folder) && (node->expanded) &&
+ (node->child != NULL)) {
node = node->child;
*before = true;
}
@@ -799,527 +1921,687 @@ struct node *tree_get_link_details(struct tree *tree, int x, int y, bool *before
/**
- * Links a node into the tree.
+ * Launches all the selected nodes of the tree
*
- * \param link the node to link before/as a child (folders) or before/after (link)
- * \param node the node to link
- * \param before whether to link siblings before or after the supplied node
+ * \param tree the tree for which all nodes will be launched
+ * \param node the node which will be checked together with its children
*/
-void tree_link_node(struct node *link, struct node *node, bool before) {
- assert(link);
- assert(node);
-
- if ((!link->folder) || (before)) {
- node->parent = link->parent;
- if (before) {
- node->next = link;
- node->previous = link->previous;
- if (link->previous) link->previous->next = node;
- link->previous = node;
- if ((link->parent) && (link->parent->child == link))
- link->parent->child = node;
- } else {
- node->previous = link;
- node->next = link->next;
- if (link->next) link->next->previous = node;
- link->next = node;
+static void tree_launch_selected_internal(struct tree *tree, struct node *node)
+{
+ struct node_msg_data msg_data;
+
+ for (; node != NULL; node = node->next) {
+ if (node->selected && node->user_callback != NULL) {
+ msg_data.msg = NODE_LAUNCH;
+ msg_data.flag = TREE_ELEMENT_TITLE;
+ msg_data.node = node;
+ node->user_callback(node->callback_data, &msg_data);
}
- } else {
- if (!link->child) {
- link->child = link->last_child = node;
- node->previous = NULL;
- } else {
- link->last_child->next = node;
- node->previous = link->last_child;
- link->last_child = node;
- }
- node->parent = link;
- node->next = NULL;
+ if (node->child != NULL)
+ tree_launch_selected_internal(tree, node->child);
}
- node->deleted = false;
}
/**
- * Delinks a node from the tree.
+ * Launches all the selected nodes of the tree
*
- * \param node the node to delink
+ * \param tree the tree for which all nodes will be launched
*/
-void tree_delink_node(struct node *node) {
- assert(node);
-
- if (node->parent) {
- if (node->parent->child == node)
- node->parent->child = node->next;
- if (node->parent->last_child == node)
- node->parent->last_child = node->previous;
- if (node->parent->child == NULL) {
- /* don't contract top-level node */
- if (node->parent->parent)
- node->parent->expanded = false;
- }
- node->parent = NULL;
- }
- if (node->previous)
- node->previous->next = node->next;
- if (node->next)
- node->next->previous = node->previous;
- node->previous = NULL;
- node->next = NULL;
+void tree_launch_selected(struct tree *tree)
+{
+ if (tree->root->child != NULL)
+ tree_launch_selected_internal(tree, tree->root->child);
}
/**
- * Deletes all selected node from the tree.
+ * Handles a mouse action for a tree
*
- * \param tree the tree to delete from
- * \param node the node to delete
+ * \param tree the tree to handle a click for
+ * \param mouse the mouse state
+ * \param x X coordinate of mouse action
+ * \param y Y coordinate of mouse action
+ * \return whether the click was handled
*/
-void tree_delete_selected_nodes(struct tree *tree, struct node *node) {
- struct node *next;
+bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse, int x,
+ int y)
+{
+ bool furniture;
+ struct node *node;
+ struct node *last;
+ struct node_element *element;
+ struct node_msg_data msg_data;
- while (node) {
- next = node->next;
- if ((node->selected) && (node != tree->root))
- tree_delete_node(tree, node, false);
- else if (node->child)
- tree_delete_selected_nodes(tree, node->child);
- node = next;
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+
+ if (tree->root->child == NULL)
+ return true;
+
+ element = tree_get_node_element_at(tree->root->child, x, y, &furniture);
+
+ /* pass in-textarea mouse action and drags which started in it
+ to the textarea */
+ if (tree->editing != NULL) {
+ int x0, x1, y0, y1;
+ x0 = tree->editing->box.x;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x0 += NODE_INSTEP;
+ x1 = tree->editing->box.x + tree->editing->box.width;
+ y0 = tree->editing->box.y;
+ y1 = tree->editing->box.y + tree->editing->box.height;
+
+ if (tree->textarea_drag_start &&
+ (mouse & (BROWSER_MOUSE_HOLDING_1 |
+ BROWSER_MOUSE_HOLDING_2))) {
+
+ textarea_mouse_action(tree->textarea, mouse,
+ x - x0, y - y0);
+ return true;
+ }
+
+
+
+ if ((x >= x0) && (x < x1) && (y >= y0) && (y < y1)) {
+
+ if (mouse & (BROWSER_MOUSE_DRAG_1 |
+ BROWSER_MOUSE_DRAG_2))
+ tree->textarea_drag_start = true;
+ else
+ tree->textarea_drag_start = false;
+ textarea_mouse_action(tree->textarea, mouse,
+ x - x0, y - y0);
+ return true;
+
+ }
}
-}
+ tree->textarea_drag_start = false;
-/**
- * Deletes a node from the tree.
- *
- * \param tree the tree to delete from
- * \param node the node to delete
- * \param siblings whether to delete all siblings
- */
-void tree_delete_node(struct tree *tree, struct node *node, bool siblings) {
- tree_delete_node_internal(tree, node, siblings);
- if (tree->root)
- tree_recalculate_node_positions(tree, tree->root);
- tree_redraw_area(tree, 0, 0, 16384, 16384); /* \todo correct area */
- tree_recalculate_size(tree);
+ /* we are not interested in the drag path or in mouse presses, return */
+ if (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2 |
+ BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2))
+ return true;
+
+ /* cancel edit */
+ if (tree->editing != NULL)
+ tree_stop_edit(tree, false);
+
+
+
+ /* no item either means cancel selection on (select) click or a drag */
+ if (element == NULL) {
+ if (tree->flags & TREE_SINGLE_SELECT) {
+ tree_set_node_selected(tree, tree->root->child, true,
+ false);
+ return true;
+ }
+ if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_DRAG_1))
+ tree_set_node_selected(tree, tree->root->child, true,
+ false);
+ if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
+
+ /** @todo the tree window has to scroll the tree when
+ * mouse reaches border while dragging this isn't
+ * solved for the browser window too.
+ */
+ tree->drag = TREE_SELECT_DRAG;
+ }
+ return true;
+ }
+
+ node = element->parent;
+
+ /* click on furniture or double click on folder toggles node expansion
+ */
+ if (((furniture) && (mouse & (BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_CLICK_2))) ||
+ ((!furniture) && (node->child != NULL) &&
+ (mouse & BROWSER_MOUSE_DOUBLE_CLICK))) {
+
+ /* clear any selection */
+ tree_set_node_selected(tree, tree->root->child, true, false);
+
+ /* expand / contract node and redraw */
+ tree_set_node_expanded(tree, node, !node->expanded,
+ false, false);
+
+ /* find the last child node if expanded */
+ last = node;
+ if ((last->child != NULL) && (last->expanded)) {
+ last = last->child;
+ while ((last->next != NULL) ||
+ ((last->child != NULL) &&
+ (last->expanded))) {
+ if (last->next != NULL)
+ last = last->next;
+ else
+ last = last->child;
+ }
+ }
+ /* scroll to the bottom element then back to the top */
+ element = &last->data;
+ if (last->expanded)
+ for (; element->next != NULL; element = element->next);
+ tree->callbacks->scroll_visible(element->box.y,
+ element->box.height,
+ tree->client_data);
+ tree->callbacks->scroll_visible(node->data.box.y,
+ node->data.box.height,
+ tree->client_data);
+ return true;
+ }
+
+ /* no use for any other furniture click */
+ if (furniture)
+ return true;
+
+ /* single/double ctrl+click or alt+click starts editing */
+ if ((element->editable) && (!tree->editing) &&
+ ((element->type == NODE_ELEMENT_TEXT) ||
+ (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) &&
+ (mouse & (BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_DOUBLE_CLICK)) &&
+ (mouse & BROWSER_MOUSE_MOD_2 ||
+ mouse & BROWSER_MOUSE_MOD_3)) {
+ tree_set_node_selected(tree, tree->root->child, true, false);
+ tree_start_edit(tree, element);
+ return true;
+ }
+
+ /* double click launches the leaf */
+ if (mouse & BROWSER_MOUSE_DOUBLE_CLICK) {
+ if (node->user_callback == NULL)
+ return false;
+ msg_data.msg = NODE_LAUNCH;
+ msg_data.flag = TREE_ELEMENT_TITLE;
+ msg_data.node = node;
+ if (node->user_callback(node->callback_data, &msg_data) !=
+ NODE_CALLBACK_HANDLED)
+ return false;
+
+ return true;
+ }
+
+ /* single click (select) cancels current selection and selects item */
+ if (mouse & BROWSER_MOUSE_CLICK_1 || (mouse & BROWSER_MOUSE_CLICK_2 &&
+ tree->flags & TREE_SINGLE_SELECT)) {
+ if (tree->flags & TREE_NO_SELECT)
+ return true;
+ if (!node->selected) {
+ tree_set_node_selected(tree, tree->root->child, true,
+ false);
+ node->selected = true;
+ tree_handle_node_element_changed(tree, &node->data);
+ }
+ return true;
+ }
+
+ /* single click (adjust) toggles item selection */
+ if (mouse & BROWSER_MOUSE_CLICK_2) {
+ if (tree->flags & TREE_NO_SELECT)
+ return true;
+ node->selected = !node->selected;
+ tree_handle_node_element_changed(tree, &node->data);
+ return true;
+ }
+
+ /* drag starts a drag operation */
+ if ((!tree->editing) && (mouse & (BROWSER_MOUSE_DRAG_1 |
+ BROWSER_MOUSE_DRAG_2))) {
+ if (tree->flags & TREE_NO_DRAGS)
+ return true;
+
+ if (!node->selected) {
+ tree_set_node_selected(tree, tree->root->child, true,
+ false);
+ node->selected = true;
+ tree_handle_node_element_changed(tree, &node->data);
+ }
+
+ tree->drag = TREE_MOVE_DRAG;
+
+ return true;
+ }
+
+
+ return false;
}
/**
- * Deletes a node from the tree.
+ * Updates the selected state for a region of nodes.
*
- * \param tree the tree to delete from
- * \param node the node to delete
- * \param siblings whether to delete all siblings
+ * \param tree the tree to update
+ * \param node the node to update children and siblings of
+ * \param y the minimum y of the selection rectangle
+ * \param height the height of the selection rectangle
+ * \param invert whether to invert the selected state
*/
-void tree_delete_node_internal(struct tree *tree, struct node *node, bool siblings) {
- struct node *next, *child;
- struct node_element *e, *f, *domain, *path;
- const char *domain_t, *path_t, *name_t;
- char *space;
-
- assert(node);
-
- if (tree->temp_selection == node)
- tree->temp_selection = NULL;
- if (tree->root == node)
- tree->root = NULL;
+static void tree_handle_selection_area_node(struct tree *tree,
+ struct node *node, int y, int height, bool invert)
+{
+ struct node_element *element;
+ struct node *update;
+ int y_max;
+ int y0, y1;
- next = node->next;
- tree_delink_node(node);
- child = node->child;
- node->child = NULL;
- if (child)
- tree_delete_node_internal(tree, child, true);
+ assert(tree != NULL);
+ assert(node != NULL);
- if (!node->retain_in_memory) {
- node->retain_in_memory = true;
- for (e = &node->data; e; e = f) {
- if (e->text) {
- /* we don't free non-editable titles or URLs */
- if ((node->editable) || (node->folder))
- free((void *)e->text);
- else {
- /* only reset non-deleted items */
- if (!node->deleted) {
- if (e->data == TREE_ELEMENT_URL) {
- /* reset URL characteristics */
- urldb_reset_url_visit_data(e->text);
- } else if (e->data == TREE_ELEMENT_NAME) {
- /* get the rest of the cookie data */
- domain = tree_find_element(node,
- TREE_ELEMENT_DOMAIN);
- path = tree_find_element(node,
- TREE_ELEMENT_PATH);
- if (domain && path) {
- domain_t = domain->text +
- strlen(messages_get(
- "TreeDomain")) - 4;
- space = strchr(domain_t, ' ');
- if (space)
- *space = '\0';
- path_t = path->text +
- strlen(messages_get(
- "TreePath")) - 4;
- space = strchr(path_t, ' ');
- if (space)
- *space = '\0';
- name_t = e->text;
- urldb_delete_cookie(
- domain_t,
- path_t,
- name_t);
- }
- }
- }
+ y_max = y + height;
- if (e->data != TREE_ELEMENT_TITLE &&
- e->data != TREE_ELEMENT_URL) {
- free((void *)e->text);
- e->text = NULL;
+ for (; node != NULL; node = node->next) {
+ if (node->box.y > y_max) return;
+ y0 = node->box.y;
+ y1 = node->box.y + node->box.height;
+ if ((y0 < y_max) && (y1 >= y)) {
+ update = NULL;
+ if (node->expanded) {
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ y0 = element->box.y;
+ y1 = element->box.y +
+ element->box.height;
+ if ((y0 < y_max) && (y1 >= y)) {
+ update = element->parent;
+ break;
}
}
+ } else {
+ y0 = node->data.box.y;
+ y1 = node->data.box.y + node->data.box.height;
+ if ((y0 < y_max) && (y1 >= y))
+ update = node->data.parent;
}
- if (e->sprite) {
- /* TODO the type of this field is platform dependent */
- free(e->sprite); /* \todo platform specific bits */
- e->sprite = NULL;
+ if ((update) && (node != tree->root)) {
+ if (invert) {
+ node->selected = !node->selected;
+ tree_handle_node_element_changed(tree,
+ &node->data);
+ } else if (!node->selected) {
+ node->selected = true;
+ tree_handle_node_element_changed(tree,
+ &node->data);
+ }
}
- f = e->next;
- if (e != &node->data)
- free(e);
}
- free(node);
- } else {
- node->deleted = true;
+ if ((node->child != NULL) && (node->expanded))
+ tree_handle_selection_area_node(tree, node->child, y,
+ height, invert);
}
- if (siblings && next)
- tree_delete_node_internal(tree, next, true);
}
+
/**
- * Creates a folder node with the specified title, and links it into the tree.
+ * Updates the selected state for a region of nodes.
*
- * \param parent the parent node, or NULL not to link
- * \param title the node title (copied)
- * \return the newly created node.
+ * \param tree the tree to update
+ * \param y the minimum y of the selection rectangle
+ * \param height the height of the selection rectangle
+ * \param invert whether to invert the selected state
*/
-struct node *tree_create_folder_node(struct node *parent, const char *title) {
- struct node *node;
+static void tree_handle_selection_area(struct tree *tree, int y, int height,
+ bool invert)
+{
+ assert(tree != NULL);
+ assert(tree->root != NULL);
- assert(title);
+ if (tree->root->child == NULL)
+ return;
- node = calloc(sizeof(struct node), 1);
- if (!node) return NULL;
- node->editable = true;
- node->folder = true;
- node->data.parent = node;
- node->data.type = NODE_ELEMENT_TEXT;
- node->data.text = squash_whitespace(title);
- node->data.data = TREE_ELEMENT_TITLE;
- tree_set_node_sprite_folder(node);
- if (parent)
- tree_link_node(parent, node, false);
- return node;
+ if (height < 0) {
+ y += height;
+ height = -height;
+ }
+ tree_handle_selection_area_node(tree, tree->root->child, y, height,
+ invert);
}
/**
- * Creates a leaf node with the specified title, and links it into the tree.
+ * Clears the processing flag.
*
- * \param parent the parent node, or NULL not to link
- * \param title the node title (copied)
- * \return the newly created node.
+ * \param node the node to process siblings and children of
*/
-struct node *tree_create_leaf_node(struct node *parent, const char *title) {
- struct node *node;
+static void tree_clear_processing(struct node *node)
+{
+ for (; node != NULL; node = node->next) {
+ node->processing = false;
+ if (node->child != NULL)
+ tree_clear_processing(node->child);
+ }
+}
- assert(title);
- node = calloc(sizeof(struct node), 1);
- if (!node) return NULL;
- node->folder = false;
- node->data.parent = node;
- node->data.type = NODE_ELEMENT_TEXT;
- node->data.text = strdup(squash_whitespace(title));
- node->data.data = TREE_ELEMENT_TITLE;
- node->editable = true;
- if (parent)
- tree_link_node(parent, node, false);
- return node;
+/**
+ * Sets the processing flag to the selection state.
+ *
+ * \param node the node to process siblings and children of
+ */
+static void tree_selected_to_processing(struct node *node)
+{
+ for (; node != NULL; node = node->next) {
+ node->processing = node->selected;
+ if ((node->child != NULL) && (node->expanded))
+ tree_selected_to_processing(node->child);
+ }
}
/**
- * Creates a leaf node with the specified title, and links it into the tree.
+ * Moves the first node in a tree with the processing flag set.
*
- * \param parent the parent node, or NULL not to link
- * \param title the node title
- * \return the newly created node.
+ * \param tree the tree in which the move takes place
+ * \param node the node to move siblings/children of
+ * \param link the node to link before/as a child (folders) or before/after
+ * (link)
+ * \param before whether to link siblings before or after the supplied node
+ * \param first whether to always link after the supplied node (ie not
+ * inside of folders)
+ * \return the node moved
*/
-struct node *tree_create_leaf_node_shared(struct node *parent, const char *title) {
- struct node *node;
-
- assert(title);
+static struct node *tree_move_processing_node(struct tree *tree,
+ struct node *node, struct node *link, bool before, bool first)
+{
+ struct node *result;
- node = calloc(sizeof(struct node), 1);
- if (!node) return NULL;
- node->folder = false;
- node->data.parent = node;
- node->data.type = NODE_ELEMENT_TEXT;
- node->data.text = title;
- node->data.data = TREE_ELEMENT_TITLE;
- node->editable = false;
- if (parent)
- tree_link_node(parent, node, false);
- return node;
+ bool folder = link->folder;
+ for (; node != NULL; node = node->next) {
+ if (node->processing) {
+ node->processing = false;
+ tree_delink_node(tree, node);
+ if (!first)
+ link->folder = false;
+ tree_link_node(tree, link, node, before);
+ if (!first)
+ link->folder = folder;
+ return node;
+ }
+ if (node->child != NULL) {
+ result = tree_move_processing_node(tree, node->child,
+ link, before, first);
+ if (result != NULL)
+ return result;
+ }
+ }
+ return NULL;
}
/**
- * Creates a tree entry for a URL, and links it into the tree
- *
+ * Moves nodes within a tree.
*
- * \param parent the node to link to
- * \param url the URL (copied)
- * \param data the URL data to use
- * \param title the custom title to use
- * \return the node created, or NULL for failure
+ * \param tree the tree to process
+ * \param destination the node to link before/as a child (folders)
+ * or before/after (link)
+ * \param before whether to link siblings before or after the supplied
+ * node
*/
-struct node *tree_create_URL_node(struct node *parent,
- const char *url, const struct url_data *data,
- const char *title) {
- struct node *node;
- struct node_element *element;
-
- assert(data);
+static void tree_move_selected_nodes(struct tree *tree,
+ struct node *destination, bool before)
+{
+ struct node *link;
+ struct node *test;
+ bool error;
- node = tree_create_leaf_node(parent, title ? title : url);
- if (!node)
- return NULL;
+ tree_clear_processing(tree->root);
+ tree_selected_to_processing(tree->root);
- element = tree_create_node_element(node, TREE_ELEMENT_THUMBNAIL);
- if (element)
- element->type = NODE_ELEMENT_THUMBNAIL;
- tree_create_node_element(node, TREE_ELEMENT_VISITS);
- tree_create_node_element(node, TREE_ELEMENT_LAST_VISIT);
- element = tree_create_node_element(node, TREE_ELEMENT_URL);
- if (element)
- element->text = strdup(url);
+ /* the destination node cannot be a child of any node with
+ the processing flag set */
+ error = destination->processing;
+ for (test = destination; test != NULL; test = test->parent)
+ error |= test->processing;
+ if (error) {
+ tree_clear_processing(tree->root);
+ return;
+ }
+ if ((destination->folder) && (!destination->expanded) && (!before)) {
+ tree_set_node_expanded(tree, destination, true, false, false);
+ }
+ link = tree_move_processing_node(tree, tree->root, destination, before,
+ true);
+ while (link != NULL)
+ link = tree_move_processing_node(tree, tree->root, link, false,
+ false);
- tree_update_URL_node(node, url, NULL);
- return node;
+ tree_clear_processing(tree->root);
+ tree_recalculate_node_positions(tree, tree->root);
+ if (tree->redraw)
+ tree->callbacks->redraw_request(0, 0, tree->width, tree->height,
+ tree->client_data);
}
/**
- * Creates a tree entry for a URL, and links it into the tree.
- *
- * All information is used directly from the url_data, and as such cannot be
- * edited and should never be freed.
+ * Handle the end of a drag operation
*
- * \param parent the node to link to
- * \param url the URL
- * \param data the URL data to use
- * \return the node created, or NULL for failure
+ * \param tree the tree on which the drag was performed
+ * \param mouse mouse state during drag end
+ * \param x0 x coordinate of drag start
+ * \param y0 y coordinate of drag start
+ * \param x1 x coordinate of drag end
+ * \param y1 y coordinate of drag end
*/
-struct node *tree_create_URL_node_shared(struct node *parent,
- const char *url, const struct url_data *data) {
- struct node *node;
- struct node_element *element;
- const char *title;
+void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0,
+ int x1, int y1)
+{
- assert(url && data);
-
- if (data->title)
- title = data->title;
- else
- title = url;
- node = tree_create_leaf_node_shared(parent, title);
- if (!node)
- return NULL;
+ bool before;
+ struct node *node;
+ int x, y;
+
+ if (tree->textarea_drag_start) {
+ x = tree->editing->box.x;
+ y = tree->editing->box.y;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x += NODE_INSTEP;
+ textarea_drag_end(tree->textarea, mouse, x1 - x, y1 - y);
+ }
- element = tree_create_node_element(node, TREE_ELEMENT_THUMBNAIL);
- if (element)
- element->type = NODE_ELEMENT_THUMBNAIL;
- tree_create_node_element(node, TREE_ELEMENT_VISITS);
- tree_create_node_element(node, TREE_ELEMENT_LAST_VISIT);
- element = tree_create_node_element(node, TREE_ELEMENT_URL);
- if (element)
- element->text = url;
+ tree->textarea_drag_start = false;
+
+ switch (tree->drag) {
+ case TREE_NO_DRAG:
+ break;
+ case TREE_SELECT_DRAG:
+ tree_handle_selection_area(tree, y0, y1 - y0,
+ (mouse | BROWSER_MOUSE_HOLDING_2));
+ break;
+ case TREE_MOVE_DRAG:
+ if (!(tree->flags & TREE_MOVABLE))
+ return;
+ node = tree_get_link_details(tree, x1, y1, &before);
+ tree_move_selected_nodes(tree, node, before);
+ break;
+ }
- tree_update_URL_node(node, url, data);
- return node;
+ tree->drag = TREE_NO_DRAG;
}
/**
- * Creates a tree entry for a cookie, and links it into the tree.
- *
- * All information is copied from the cookie_data, and as such can
- * be edited and should be freed.
+ * Key press handling for a tree.
*
- * \param parent the node to link to
- * \param url the URL
- * \param data the cookie data to use
- * \return the node created, or NULL for failure
+ * \param tree The tree which got the keypress
+ * \param key The ucs4 character codepoint
+ * \return true if the keypress is dealt with, false otherwise.
*/
-struct node *tree_create_cookie_node(struct node *parent,
- const struct cookie_data *data) {
- struct node *node;
- struct node_element *element;
- char buffer[256];
- char buffer2[16];
-
- node = tree_create_leaf_node(parent, data->name);
- if (!node)
- return NULL;
- node->data.data = TREE_ELEMENT_NAME;
- node->editable = false;
-
+bool tree_keypress(struct tree *tree, uint32_t key)
+{
- element = tree_create_node_element(node, TREE_ELEMENT_PERSISTENT);
- if (element) {
- snprintf(buffer, 256, messages_get("TreePersistent"),
- data->no_destroy ? messages_get("Yes") : messages_get("No"));
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_VERSION);
- if (element) {
- snprintf(buffer2, 16, "TreeVersion%i", data->version);
- snprintf(buffer, 256, messages_get("TreeVersion"), messages_get(buffer2));
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_SECURE);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeSecure"),
- data->secure ? messages_get("Yes") : messages_get("No"));
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_LAST_USED);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeLastUsed"),
- (data->last_used > 0) ?
- ctime(&data->last_used) : messages_get("TreeUnknown"));
- if (data->last_used > 0)
- buffer[strlen(buffer) - 1] = '\0';
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_EXPIRES);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeExpires"),
- (data->expires > 0)
- ? (data->expires == 1)
- ? messages_get("TreeSession")
- : ctime(&data->expires)
- : messages_get("TreeUnknown"));
- if (data->expires > 0 && data->expires != 1)
- buffer[strlen(buffer) - 1] = '\0';
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_PATH);
- if (element) {
- snprintf(buffer, 256, messages_get("TreePath"), data->path,
- data->path_from_set ? messages_get("TreeHeaders") : "");
- element->text = strdup(buffer);
- }
- element = tree_create_node_element(node, TREE_ELEMENT_DOMAIN);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeDomain"), data->domain,
- data->domain_from_set ? messages_get("TreeHeaders") : "");
- element->text = strdup(buffer);
- }
- if ((data->comment) && (strcmp(data->comment, ""))) {
- element = tree_create_node_element(node, TREE_ELEMENT_COMMENT);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeComment"), data->comment);
- element->text = strdup(buffer);
+ if (tree->editing != NULL)
+ switch (key) {
+ case KEY_ESCAPE:
+ tree_stop_edit(tree, false);
+ return true;
+ case KEY_NL:
+ tree_stop_edit(tree, true);
+ return true;
+ default:
+ return textarea_keypress(tree->textarea, key);
}
- }
- element = tree_create_node_element(node, TREE_ELEMENT_VALUE);
- if (element) {
- snprintf(buffer, 256, messages_get("TreeValue"),
- data->value ? data->value : messages_get("TreeUnused"));
- element->text = strdup(buffer);
- }
- tree_set_node_sprite(node, "small_xxx", "small_xxx");
- return node;
+ return false;
}
/**
- * Creates an empty text node element and links it to a node.
+ * Alphabetical comparison function for nodes
*
- * \param parent the parent node
- * \param user_type the required user_type
- * \return the newly created element.
+ * \param n1 first node to compare
+ * \param n2 first node to compare
+ * \return 0 if equal, greater then zero if n1 > n2,
+ * less then zero if n2 < n1
*/
-struct node_element *tree_create_node_element(struct node *parent, node_element_data data) {
- struct node_element *element;
+int tree_alphabetical_sort(struct node *n1, struct node *n2)
+{
+ return strcmp(n1->data.text, n2->data.text);
+}
- element = calloc(sizeof(struct node_element), 1);
- if (!element) return NULL;
- element->parent = parent;
- element->data = data;
- element->type = NODE_ELEMENT_TEXT;
- element->next = parent->data.next;
- parent->data.next = element;
- return element;
+
+/**
+ * Redraw requests from the textarea are piped through this because we have to
+ * check the redraw flag of the tree before requesting a redraw and change the
+ * position to tree origin relative.
+ */
+static void tree_textarea_redraw_request(void *data, int x, int y,
+ int width, int height)
+{
+ struct tree *tree = data;
+ x = x + tree->editing->box.x;
+ y = y + tree->editing->box.y;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x += NODE_INSTEP;
+
+ if (tree->redraw)
+ tree->callbacks->redraw_request(x, y,
+ width, height,
+ tree->client_data);
}
/**
- * Recalculates the size of a tree.
+ * Starts editing a node_element
*
- * \param tree the tree to recalculate
+ * \param tree The tree to which element belongs
+ * \param element The element to start being edited
*/
-void tree_recalculate_size(struct tree *tree) {
+void tree_start_edit(struct tree *tree, struct node_element *element)
+{
+ struct node *parent;
int width, height;
- assert(tree);
+ assert(tree != NULL);
+ assert(element != NULL);
+
+ if (tree->editing != NULL)
+ tree_stop_edit(tree, true);
+
+ parent = element->parent;
+ if (&parent->data == element)
+ parent = parent->parent;
+ for (; parent != NULL; parent = parent->parent) {
+ if (!parent->expanded) {
+ tree_set_node_expanded(tree, parent, true,
+ false, false);
+ }
+ }
+
+ tree->editing = element;
+ tree->callbacks->get_window_dimensions(&width, NULL, tree->client_data);
+ width -= element->box.x;
+ height = element->box.height;
+ if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ width -= NODE_INSTEP;
- if (!tree->handle)
+ tree->textarea = textarea_create(width, height, 0,
+ &plot_fstyle, tree_textarea_redraw_request, tree);
+ if (tree->textarea == NULL) {
+ tree_stop_edit(tree, false);
return;
- width = tree->width;
- height = tree->height;
- if (tree->root) {
- tree->width = tree_get_node_width(tree->root);
- tree->height = tree_get_node_height(tree->root);
- } else {
- tree->width = 0;
- tree->height = 0;
}
- if ((width != tree->width) || (height != tree->height))
- tree_resized(tree);
+ textarea_set_text(tree->textarea, element->text);
+
+ tree_handle_node_element_changed(tree, element);
+ tree_recalculate_size(tree);
+ tree->callbacks->scroll_visible(element->box.y, element->box.height,
+ tree->client_data);
}
/**
- * Returns the selected node, or NULL if multiple nodes are selected.
- *
- * \param node the node to search sibling and children
- * \return the selected node, or NULL if multiple nodes are selected
+ * Callback for fetchcache(). Should be removed once bitmaps get loaded directly
+ * from disc
*/
-struct node *tree_get_selected_node(struct node *node) {
- struct node *result = NULL;
- struct node *temp;
+static nserror tree_icon_callback(hlcache_handle *handle,
+ const hlcache_event *event, void *pw)
+{
+ return NSERROR_OK;
+}
- for (; node; node = node->next) {
- if (node->selected) {
- if (result)
- return NULL;
- result = node;
- }
- if ((node->child) && (node->expanded)) {
- temp = tree_get_selected_node(node->child);
- if (temp) {
- if (result)
- return NULL;
- else
- result = temp;
- }
+
+/**
+ * Tree utility function. Placed here so that this code doesn't have to be
+ * copied by each user.
+ *
+ * \param name the name of the loaded icon, if it's not a full path the icon is
+ * looked for in the directory specified by option_tree_icons_dir
+ * \return the icon in form of a content or NULL on failure
+ */
+hlcache_handle *tree_load_icon(const char *name)
+{
+ char *url = NULL;
+ const char *icon_url = NULL;
+ int len;
+ hlcache_handle *c;
+ nserror err;
+
+ /** @todo something like bitmap_from_disc is needed here */
+
+ if (!strncmp(name, "file://", 7)) {
+ icon_url = name;
+ } else {
+ char *native_path;
+
+ if (option_tree_icons_dir == NULL)
+ return NULL;
+
+ /* path + separator + leafname + '\0' */
+ len = strlen(option_tree_icons_dir) + 1 + strlen(name) + 1;
+ native_path = malloc(len);
+ if (native_path == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
}
+
+ /* Build native path */
+ memcpy(native_path, option_tree_icons_dir,
+ strlen(option_tree_icons_dir) + 1);
+ path_add_part(native_path, len, name);
+
+ /* Convert native path to URL */
+ url = path_to_url(native_path);
+
+ free(native_path);
+ icon_url = url;
}
- return result;
+
+ /* Fetch the icon */
+ err = hlcache_handle_retrieve(icon_url, 0, 0, 0,
+ tree_icon_callback, 0, 0, 0, &c);
+
+
+ /* If we built the URL here, free it */
+ if (url != NULL)
+ free(url);
+
+ if (err != NSERROR_OK) {
+ return NULL;
+ }
+
+ return c;
}
diff --git a/desktop/tree.h b/desktop/tree.h
index d02f1726e..707f3d126 100644
--- a/desktop/tree.h
+++ b/desktop/tree.h
@@ -1,5 +1,6 @@
/*
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -26,157 +27,167 @@
#include <stdbool.h>
#include <stdint.h>
-struct url_data;
-struct cookie_data;
-
-typedef enum {
- TREE_ELEMENT_URL,
- TREE_ELEMENT_ADDED,
- TREE_ELEMENT_LAST_VISIT,
- TREE_ELEMENT_VISITS,
- TREE_ELEMENT_VISITED,
- TREE_ELEMENT_THUMBNAIL,
- TREE_ELEMENT_TITLE,
- TREE_ELEMENT_NAME,
- TREE_ELEMENT_VALUE,
- TREE_ELEMENT_COMMENT,
- TREE_ELEMENT_DOMAIN,
- TREE_ELEMENT_PATH,
- TREE_ELEMENT_EXPIRES,
- TREE_ELEMENT_LAST_USED,
- TREE_ELEMENT_SECURE,
- TREE_ELEMENT_VERSION,
- TREE_ELEMENT_PERSISTENT,
- TREE_ELEMENT_SSL
-} node_element_data;
-
-#define NODE_INSTEP 40
-
-struct node_sprite;
-struct toolbar;
-
-typedef enum {
- NODE_ELEMENT_TEXT, /* <-- Text only */
- NODE_ELEMENT_TEXT_PLUS_SPRITE, /* <-- Text and sprite */
- NODE_ELEMENT_THUMBNAIL, /* <-- Bitmap only */
-} node_element_type;
-
-
-struct node_element_box {
- int x; /* <-- X offset from origin */
- int y; /* <-- Y offset from origin */
- int width; /* <-- Element width */
- int height; /* <-- Element height */
+#include "desktop/browser.h"
+#include "image/bitmap.h"
+
+struct hlcache_handle;
+
+/* Tree flags */
+enum tree_flags {
+ TREE_NO_FLAGS = 0,
+ TREE_NO_DRAGS = 1,
+ TREE_NO_FURNITURE = 2,
+ TREE_SINGLE_SELECT = 4,
+ TREE_NO_SELECT = 8,
+ TREE_MOVABLE = 16,
+ TREE_DELETE_EMPTY_DIRS = 32, /**< if the last child of a
+ * directory is deleted the
+ * directory will be deleted
+ * too.
+ */
};
+/** A "flag" value to indicate the element data contains title
+ * text. This value should be the first node_element in every
+ * node. All other values should be different than this one. The term
+ * flag is misused as it is actually a value used by the API consumer
+ * to indicate teh type of data a node element contains.
+ */
+#define TREE_ELEMENT_TITLE 0x00
-struct node_element {
- struct node *parent; /* <-- Parent node */
- node_element_type type; /* <-- Element type */
- struct node_element_box box; /* <-- Element bounding box */
- const char *text; /* <-- Text for the element */
- struct node_sprite *sprite; /* <-- Sprite for the element */
- struct node_element *next; /* <-- Next node element */
- node_element_data data; /* <-- Data being represented */
-};
+/* these should be defined in front end code */
+extern const char tree_directory_icon_name[];
+extern const char tree_content_icon_name[];
+
+struct tree;
+struct node;
+struct node_element;
+typedef enum {
+ NODE_ELEMENT_TEXT, /**< Text only */
+ NODE_ELEMENT_TEXT_PLUS_ICON, /**< Text and icon */
+ NODE_ELEMENT_BITMAP /**< Bitmap only */
+} node_element_type;
-struct node {
- bool selected; /* <-- Whether the node is selected */
- bool expanded; /* <-- Whether the node is expanded */
- bool folder; /* <-- Whether the node is a folder */
- bool editable; /* <-- Whether the node is editable */
- bool retain_in_memory; /* <-- Whether the node remains in memory after deletion */
- bool deleted; /* <-- Whether the node is currently deleted */
- bool processing; /* <-- Internal flag used when moving */
- struct node_element_box box; /* <-- Bounding box of all elements */
- struct node_element data; /* <-- Data to display */
- struct node *parent; /* <-- Parent entry (NULL for root) */
- struct node *child; /* <-- First child */
- struct node *last_child; /* <-- Last child */
- struct node *previous; /* <-- Previous child of the parent */
- struct node *next; /* <-- Next child of the parent */
+typedef enum {
+ NODE_DELETE_ELEMENT_TXT, /**< The text of an element of the
+ * node is being deleted */
+ NODE_DELETE_ELEMENT_IMG, /**< The bitmap or icon of a node is
+ * being deleted */
+ NODE_LAUNCH, /**< The node has been launched */
+ NODE_ELEMENT_EDIT_FINISHING, /**< New text has to be accepted
+ * or rejected. */
+ NODE_ELEMENT_EDIT_FINISHED /**< Editing of a node_element has
+ * been finished. */
+} node_msg;
+typedef enum {
+ NODE_CALLBACK_HANDLED,
+ NODE_CALLBACK_NOT_HANDLED,
+ NODE_CALLBACK_REJECT, /**< reject new text for node element
+ * and leave editing mode. */
+ NODE_CALLBACK_CONTINUE /**< don't leave editig mode. */
+} node_callback_resp;
+
+/** Internal node message. */
+struct node_msg_data {
+ node_msg msg; /**< The type of message. */
+ unsigned int flag; /**< message flags. */
+ struct node *node; /**< tree node messsage concerns. */
+ union {
+ char *text; /**< textural data. */
+ void *bitmap; /**< bitmap data. */
+ } data; /**< The message data. */
};
-struct tree {
- unsigned int handle; /* <-- User assigned handle */
- int offset_x; /* <-- User assigned tree x offset */
- int offset_y; /* <-- User assigned tree y offset */
- struct node *root; /* <-- Tree root element */
- int width; /* <-- Tree width */
- int height; /* <-- Tree height */
- int window_width; /* <-- Tree window width */
- int window_height; /* <-- Tree window height */
- bool no_drag; /* <-- Tree items can't be dragged out */
- bool no_vscroll; /* <-- Tree has a vertical scroll only when needed */
- bool no_furniture; /* <-- Tree does not have connecting lines */
- bool single_selection; /* <-- There can only be one item selected */
- int edit_handle; /* <-- Handle for editing information */
- uintptr_t textarea_handle; /* <-- Handle for UTF-8 textarea */
- bool movable; /* <-- Whether nodes can be moved */
- struct node_element *editing; /* <-- Node element being edited */
- struct node *temp_selection; /* <-- Temporarily selected node */
- struct toolbar *toolbar; /* <-- Tree toolbar */
+/** callbacks to perform necessary operations on treeview. */
+struct treeview_table {
+ void (*redraw_request)(int x, int y, int width, int height,
+ void *data); /**< request a redraw. */
+ void (*resized)(struct tree *tree, int width, int height,
+ void *data); /**< resize treeview area. */
+ void (*scroll_visible)(int y, int height, void *data); /**< scroll visible treeview area. */
+ void (*get_window_dimensions)(int *width, int *height, void *data); /**< get dimensions of window */
};
+/**
+ * Informs the client about any events requiring his action
+ *
+ * \param user_data the user data which was passed at tree creation
+ * \param msg_data structure containing all the message information
+ * \return the appropriate node_callback_resp response
+ */
+typedef node_callback_resp (*tree_node_user_callback)(void *user_data,
+ struct node_msg_data *msg_data);
/* Non-platform specific code */
-void tree_initialise(struct tree *tree);
-void tree_initialise_nodes(struct tree *tree, struct node *root);
-void tree_handle_node_changed(struct tree *tree, struct node *node,
- bool recalculate_sizes, bool expansion);
-void tree_handle_node_element_changed(struct tree *tree,
- struct node_element *element);
-void tree_recalculate_node(struct tree *tree, struct node *node, bool recalculate_sizes);
-void tree_recalculate_node_positions(struct tree *tree, struct node *root);
-struct node *tree_get_node_at(struct node *root, int x, int y, bool *furniture);
-struct node_element *tree_get_node_element_at(struct node *node, int x, int y,
- bool *furniture);
-struct node_element *tree_find_element(struct node *node, node_element_data data);
-void tree_move_selected_nodes(struct tree *tree, struct node *destination,
+
+/* Functions for creating/deleting tree primitives and for tree structure
+ manipulation */
+struct tree *tree_create(unsigned int flags,
+ const struct treeview_table *callbacks,
+ void *client_data);
+struct node *tree_create_folder_node(struct tree *tree, struct node *parent,
+ const char *title, bool editable, bool retain_in_memory,
+ bool deleted);
+struct node *tree_create_leaf_node(struct tree *tree, struct node *parent,
+ const char *title, bool editable, bool retain_in_memory,
+ bool deleted);
+struct node_element *tree_create_node_element(struct node *parent,
+ node_element_type type, unsigned int flag, bool editable);
+void tree_link_node(struct tree *tree, struct node *link, struct node *node,
bool before);
-bool tree_has_selection(struct node *node);
-void tree_draw(struct tree *tree, int clip_x, int clip_y, int clip_width,
- int clip_height);
-void tree_link_node(struct node *link, struct node *node, bool before);
-void tree_delink_node(struct node *node);
-struct node *tree_create_folder_node(struct node *parent, const char *title);
-struct node *tree_create_leaf_node(struct node *parent, const char *title);
-struct node *tree_create_URL_node(struct node *parent,
- const char *url, const struct url_data *data,
- const char *title);
-struct node *tree_create_URL_node_shared(struct node *parent,
- const char *url, const struct url_data *data);
-struct node *tree_create_cookie_node(struct node *parent,
- const struct cookie_data *data);
-void tree_set_node_sprite(struct node *node, const char *sprite,
- const char *expanded);
-void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded);
-void tree_set_node_selected(struct tree *tree, struct node *node,
- bool selected);
-void tree_handle_selection_area(struct tree *tree, int x, int y, int width,
- int height, bool invert);
-void tree_delete_selected_nodes(struct tree *tree, struct node *node);
+void tree_delink_node(struct tree *tree, struct node *node);
+void tree_delete(struct tree *tree);
void tree_delete_node(struct tree *tree, struct node *node, bool siblings);
-void tree_recalculate_size(struct tree *tree);
-bool tree_handle_expansion(struct tree *tree, struct node *node, bool expanded,
+
+/* setters and getters for properties and data */
+void tree_set_node_icon(struct tree *tree, struct node *node,
+ struct hlcache_handle *icon);
+void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded,
bool folder, bool leaf);
+void tree_set_node_selected(struct tree *tree, struct node *node, bool all,
+ bool selected);
+void tree_set_node_sort_function(struct tree *tree, struct node *node,
+ int (*sort) (struct node *, struct node *));
+void tree_set_node_user_callback(struct node *node,
+ tree_node_user_callback callback, void *data);
+void tree_set_redraw(struct tree *tree, bool redraw);
+bool tree_get_redraw(struct tree *tree);
+bool tree_node_has_selection(struct node *node);
+bool tree_node_is_deleted(struct node *node);
+bool tree_node_is_folder(struct node *node);
+void tree_update_node_element(struct tree *tree, struct node_element *element,
+ const char *text, void *bitmap);
+bool tree_update_element_text(struct tree *tree, struct node_element *element, char *text);
+const char *tree_node_element_get_text(struct node_element *element);
+struct node *tree_get_root(struct tree *tree);
+bool tree_is_edited(struct tree *tree);
+
+
+/* functions for traversing the tree */
+struct node *tree_node_get_child(struct node *node);
+struct node *tree_node_get_next(struct node *node);
+
+void tree_draw(struct tree *tree, int x, int y,
+ int clip_x, int clip_y, int clip_width, int clip_height);
+
+struct node_element *tree_node_find_element(struct node *node,
+ unsigned int flag, struct node_element *after);
+void tree_delete_selected_nodes(struct tree *tree, struct node *node);
struct node *tree_get_selected_node(struct node *node);
struct node *tree_get_link_details(struct tree *tree, int x, int y,
bool *before);
-
-
-/* Platform specific code */
-void tree_initialise_redraw(struct tree *tree);
-void tree_redraw_area(struct tree *tree, int x, int y, int width, int height);
-void tree_draw_line(int x, int y, int width, int height);
-void tree_draw_node_element(struct tree *tree, struct node_element *element);
-void tree_draw_node_expansion(struct tree *tree, struct node *node);
-void tree_recalculate_node_element(struct node_element *element);
-void tree_update_URL_node(struct node *node, const char *url,
- const struct url_data *data);
-void tree_resized(struct tree *tree);
-void tree_set_node_sprite_folder(struct node *node);
-
+void tree_launch_selected(struct tree *tree);
+
+bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse,
+ int x, int y);
+void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0,
+ int x1, int y1);
+bool tree_keypress(struct tree *tree, uint32_t key);
+
+int tree_alphabetical_sort(struct node *, struct node *);
+void tree_start_edit(struct tree *tree, struct node_element *element);
+struct hlcache_handle *tree_load_icon(const char *name);
+
#endif
diff --git a/desktop/tree_url_node.c b/desktop/tree_url_node.c
new file mode 100644
index 000000000..3bc9f90fc
--- /dev/null
+++ b/desktop/tree_url_node.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Creation of URL nodes with use of trees (implementation)
+ */
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "desktop/options.h"
+#include "desktop/tree_url_node.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+
+/** Flags for each type of url tree node. */
+enum tree_element_url {
+ TREE_ELEMENT_URL = 0x01,
+ TREE_ELEMENT_LAST_VISIT = 0x02,
+ TREE_ELEMENT_VISITS = 0x03,
+ TREE_ELEMENT_THUMBNAIL = 0x04,
+};
+
+#define MAX_ICON_NAME_LEN 256
+
+static bool initialised = false;
+
+static hlcache_handle *folder_icon;
+
+struct icon_entry {
+ content_type type;
+ hlcache_handle *icon;
+};
+
+struct icon_entry icon_table[] = {
+ {CONTENT_HTML, NULL},
+ {CONTENT_TEXTPLAIN, NULL},
+ {CONTENT_CSS, NULL},
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ {CONTENT_PNG, NULL},
+#endif
+#ifdef WITH_MNG
+ {CONTENT_JNG, NULL},
+ {CONTENT_MNG, NULL},
+#endif
+#ifdef WITH_JPEG
+ {CONTENT_JPEG, NULL},
+#endif
+#ifdef WITH_GIF
+ {CONTENT_GIF, NULL},
+#endif
+#ifdef WITH_BMP
+ {CONTENT_BMP, NULL},
+ {CONTENT_ICO, NULL},
+#endif
+#ifdef WITH_SPRITE
+ {CONTENT_SPRITE, NULL},
+#endif
+#ifdef WITH_DRAW
+ {CONTENT_DRAW, NULL},
+#endif
+#ifdef WITH_ARTWORKS
+ {CONTENT_ARTWORKS, NULL},
+#endif
+#ifdef WITH_NS_SVG
+ {CONTENT_SVG, NULL},
+#endif
+ {CONTENT_UNKNOWN, NULL},
+
+ /* this serves as a sentinel */
+ {CONTENT_HTML, NULL}
+};
+
+
+void tree_url_node_init(void)
+{
+ struct icon_entry *entry;
+ char icon_name[MAX_ICON_NAME_LEN];
+
+ if (initialised || option_tree_icons_dir == NULL)
+ return;
+ initialised = true;
+
+ folder_icon = tree_load_icon(tree_directory_icon_name);
+
+ entry = icon_table;
+ do {
+
+ tree_icon_name_from_content_type(icon_name, entry->type);
+ entry->icon = tree_load_icon(icon_name);
+
+ ++entry;
+ } while (entry->type != CONTENT_HTML);
+
+}
+
+
+/**
+ * Creates a tree entry for a URL, and links it into the tree
+ *
+ * \param parent the node to link to
+ * \param url the URL (copied)
+ * \param data the URL data to use
+ * \param title the custom title to use
+ * \return the node created, or NULL for failure
+ */
+struct node *tree_create_URL_node(struct tree *tree, struct node *parent,
+ const char *url, const char *title,
+ tree_node_user_callback user_callback, void *callback_data)
+{
+ struct node *node;
+ struct node_element *element;
+ char *text_cp, *squashed;
+
+ squashed = squash_whitespace(title ? title : url);
+ text_cp = strdup(squashed);
+ if (text_cp == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+ free(squashed);
+ node = tree_create_leaf_node(tree, parent, text_cp, true, false,
+ false);
+ if (node == NULL) {
+ free(text_cp);
+ return NULL;
+ }
+
+ if (user_callback != NULL)
+ tree_set_node_user_callback(node, user_callback,
+ callback_data);
+
+ tree_create_node_element(node, NODE_ELEMENT_BITMAP,
+ TREE_ELEMENT_THUMBNAIL, false);
+ tree_create_node_element(node, NODE_ELEMENT_TEXT, TREE_ELEMENT_VISITS,
+ false);
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_LAST_VISIT, false);
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_URL, true);
+ if (element != NULL) {
+ text_cp = strdup(url);
+ if (text_cp == NULL) {
+ tree_delete_node(tree, node, false);
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+ tree_update_node_element(tree, element, text_cp, NULL);
+ }
+
+ return node;
+}
+
+
+/**
+ * Creates a tree entry for a URL, and links it into the tree.
+ *
+ * All information is used directly from the url_data, and as such cannot be
+ * edited and should never be freed.
+ *
+ * \param parent the node to link to
+ * \param url the URL
+ * \param data the URL data to use
+ * \return the node created, or NULL for failure
+ */
+struct node *tree_create_URL_node_shared(struct tree *tree, struct node *parent,
+ const char *url, const struct url_data *data,
+ tree_node_user_callback user_callback, void *callback_data)
+{
+ struct node *node;
+ struct node_element *element;
+ const char *title;
+
+ assert(url && data);
+
+ if (data->title != NULL) {
+ title = data->title;
+ } else {
+ title = url;
+ }
+
+ node = tree_create_leaf_node(tree, parent, title, false, false, false);
+ if (node == NULL)
+ return NULL;
+
+ if (user_callback != NULL) {
+ tree_set_node_user_callback(node, user_callback,
+ callback_data);
+ }
+
+ tree_create_node_element(node, NODE_ELEMENT_BITMAP,
+ TREE_ELEMENT_THUMBNAIL, false);
+ tree_create_node_element(node, NODE_ELEMENT_TEXT, TREE_ELEMENT_VISITS,
+ false);
+ tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_LAST_VISIT, false);
+ element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
+ TREE_ELEMENT_URL, false);
+ if (element != NULL) {
+ tree_update_node_element(tree, element, url, NULL);
+ }
+
+ tree_update_URL_node(tree, node, url, data, true);
+ return node;
+}
+
+
+/**
+ * Updates the node details for a URL node.
+ *
+ * \param node the node to update
+ */
+void tree_update_URL_node(struct tree *tree, struct node *node,
+ const char *url, const struct url_data *data, bool shared)
+{
+ struct node_element *element;
+ struct bitmap *bitmap = NULL;
+ struct icon_entry *entry;
+ char *text_cp;
+
+ assert(node != NULL);
+
+ element = tree_node_find_element(node, TREE_ELEMENT_URL, NULL);
+ if (element == NULL)
+ return;
+
+ if (data != NULL) {
+ if (data->title == NULL)
+ urldb_set_url_title(url, url);
+
+ if (data->title == NULL)
+ return;
+
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE,
+ NULL);
+ if (shared)
+ tree_update_node_element(tree, element, data->title,
+ NULL);
+ else {
+ text_cp = strdup(data->title);
+ if (text_cp == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return;
+ }
+ tree_update_node_element(tree, element, text_cp, NULL);
+ }
+ } else {
+ data = urldb_get_url_data(url);
+ if (data == NULL)
+ return;
+ }
+
+ entry = icon_table;
+ do {
+ if (entry->type == data->type) {
+ if (entry->icon != NULL)
+ tree_set_node_icon(tree, node, entry->icon);
+ break;
+ }
+ ++entry;
+ } while (entry->type != CONTENT_HTML);
+
+ /* update last visit text */
+ element = tree_node_find_element(node, TREE_ELEMENT_LAST_VISIT, element);
+ tree_update_element_text(tree,
+ element,
+ messages_get_buff("TreeLast",
+ (data->last_visit > 0) ?
+ ctime((time_t *)&data->last_visit) :
+ messages_get("TreeUnknown")));
+
+
+ /* update number of visits text */
+ element = tree_node_find_element(node, TREE_ELEMENT_VISITS, element);
+ tree_update_element_text(tree,
+ element,
+ messages_get_buff("TreeVisits", data->visits));
+
+
+ /* update thumbnail */
+ element = tree_node_find_element(node, TREE_ELEMENT_THUMBNAIL, element);
+ if (element != NULL) {
+ bitmap = urldb_get_thumbnail(url);
+
+ if (bitmap != NULL) {
+ tree_update_node_element(tree, element, NULL, bitmap);
+ }
+ }
+}
+
+
+const char *tree_url_node_get_title(struct node *node)
+{
+ struct node_element *element;
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ if (element == NULL)
+ return NULL;
+ return tree_node_element_get_text(element);
+}
+
+
+const char *tree_url_node_get_url(struct node *node)
+{
+ struct node_element *element;
+ element = tree_node_find_element(node, TREE_ELEMENT_URL, NULL);
+ if (element == NULL)
+ return NULL;
+ return tree_node_element_get_text(element);
+}
+
+void tree_url_node_edit_title(struct tree *tree, struct node *node)
+{
+ struct node_element *element;
+ element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL);
+ tree_start_edit(tree, element);
+}
+
+void tree_url_node_edit_url(struct tree *tree, struct node *node)
+{
+ struct node_element *element;
+ element = tree_node_find_element(node, TREE_ELEMENT_URL, NULL);
+ tree_start_edit(tree, element);
+}
+
+node_callback_resp tree_url_node_callback(void *user_data,
+ struct node_msg_data *msg_data)
+{
+ struct tree *tree;
+ struct node_element *element;
+ url_func_result res;
+ const char *text;
+ char *norm_text, *escaped_text;
+ const struct url_data *data;
+
+ /** @todo memory leaks on non-shared folder deletion. */
+ switch (msg_data->msg) {
+ case NODE_DELETE_ELEMENT_TXT:
+ switch (msg_data->flag) {
+ /* only history is using non-editable url
+ * elements so only history deletion will run
+ * this code
+ */
+ case TREE_ELEMENT_URL:
+ /* reset URL characteristics */
+ urldb_reset_url_visit_data(
+ msg_data->data.text);
+ return NODE_CALLBACK_HANDLED;
+ case TREE_ELEMENT_TITLE:
+ return NODE_CALLBACK_HANDLED;
+ }
+ break;
+ case NODE_DELETE_ELEMENT_IMG:
+ if (msg_data->flag == TREE_ELEMENT_THUMBNAIL ||
+ msg_data->flag == TREE_ELEMENT_TITLE)
+ return NODE_CALLBACK_HANDLED;
+ break;
+ case NODE_LAUNCH:
+ element = tree_node_find_element(msg_data->node,
+ TREE_ELEMENT_URL, NULL);
+ if (element != NULL) {
+ text = tree_node_element_get_text(element);
+ browser_window_create(text, NULL, 0,
+ true, false);
+ return NODE_CALLBACK_HANDLED;
+ }
+ break;
+ case NODE_ELEMENT_EDIT_FINISHING:
+
+ text = msg_data->data.text;
+
+ if (msg_data->flag == TREE_ELEMENT_URL) {
+ res = url_escape(text, 0, false, NULL,
+ &escaped_text);
+ if (res == URL_FUNC_OK)
+ res = url_normalize(escaped_text,
+ &norm_text);
+ if (res != URL_FUNC_OK) {
+ if (res == URL_FUNC_FAILED) {
+ warn_user("NoURLError", 0);
+ return NODE_CALLBACK_CONTINUE;
+ }
+ else {
+ warn_user("NoMemory", 0);
+ return NODE_CALLBACK_REJECT;
+ }
+
+ }
+ msg_data->data.text = norm_text;
+
+ data = urldb_get_url_data(norm_text);
+ if (data == NULL) {
+ urldb_add_url(norm_text);
+ urldb_set_url_persistence(norm_text,
+ true);
+ data = urldb_get_url_data(norm_text);
+ if (data == NULL)
+ return NODE_CALLBACK_REJECT;
+ }
+ tree = user_data;
+ tree_update_URL_node(tree, msg_data->node,
+ norm_text, NULL, false);
+ }
+ else if (msg_data->flag == TREE_ELEMENT_TITLE) {
+ while (isspace(*text))
+ text++;
+ norm_text = strdup(text);
+ if (norm_text == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NODE_CALLBACK_REJECT;
+ }
+ /* don't allow zero length entry text, return
+ false */
+ if (norm_text[0] == '\0') {
+ warn_user("NoNameError", 0);
+ msg_data->data.text = NULL;
+ return NODE_CALLBACK_CONTINUE;
+ }
+ msg_data->data.text = norm_text;
+ }
+
+ return NODE_CALLBACK_HANDLED;
+ default:
+ break;
+ }
+ return NODE_CALLBACK_NOT_HANDLED;
+}
+
+/**
+ * Search the children of an xmlNode for an element.
+ *
+ * \param node xmlNode to search children of, or 0
+ * \param name name of element to find
+ * \return first child of node which is an element and matches name, or
+ * 0 if not found or parameter node is 0
+ */
+static xmlNode *tree_url_find_xml_element(xmlNode *node, const char *name)
+{
+ xmlNode *xmlnode;
+ if (node == NULL)
+ return NULL;
+
+ for (xmlnode = node->children;
+ xmlnode && !(xmlnode->type == XML_ELEMENT_NODE &&
+ strcmp((const char *) xmlnode->name, name) == 0);
+ xmlnode = xmlnode->next)
+ ;
+
+ return xmlnode;
+}
+
+/**
+ * Parse an entry represented as a li.
+ *
+ * \param li xmlNode for parsed li
+ * \param directory directory to add this entry to
+ */
+static void tree_url_load_entry(xmlNode *li, struct tree *tree,
+ struct node *directory, tree_node_user_callback callback,
+ void *callback_data)
+{
+ char *url = NULL, *url1 = NULL;
+ char *title = NULL;
+ struct node *entry;
+ xmlNode *xmlnode;
+ const struct url_data *data;
+ url_func_result res;
+
+ for (xmlnode = li->children; xmlnode; xmlnode = xmlnode->next) {
+ /* The li must contain an "a" element */
+ if (xmlnode->type == XML_ELEMENT_NODE &&
+ strcmp((const char *)xmlnode->name, "a") == 0) {
+ url1 = (char *)xmlGetProp(xmlnode, (const xmlChar *) "href");
+ title = (char *)xmlNodeGetContent(xmlnode);
+ }
+ }
+
+ if ((url1 == NULL) || (title == NULL)) {
+ warn_user("TreeLoadError", "(Missing <a> in <li> or "
+ "memory exhausted.)");
+ return;
+ }
+
+ /* We're loading external input.
+ * This may be garbage, so attempt to normalise
+ */
+ res = url_normalize(url1, &url);
+ if (res != URL_FUNC_OK) {
+ LOG(("Failed normalising '%s'", url1));
+
+ if (res == URL_FUNC_NOMEM)
+ warn_user("NoMemory", NULL);
+
+ xmlFree(url1);
+ xmlFree(title);
+
+ return;
+ }
+
+ /* No longer need this */
+ xmlFree(url1);
+
+ data = urldb_get_url_data(url);
+ if (data == NULL) {
+ /* No entry in database, so add one */
+ urldb_add_url(url);
+ /* now attempt to get url data */
+ data = urldb_get_url_data(url);
+ }
+ if (data == NULL) {
+ xmlFree(title);
+ free(url);
+
+ return;
+ }
+
+ /* Make this URL persistent */
+ urldb_set_url_persistence(url, true);
+
+ if (data->title == NULL)
+ urldb_set_url_title(url, title);
+
+ entry = tree_create_URL_node(tree, directory, url, title,
+ callback, callback_data);
+
+ if (entry == NULL) {
+ /** \todo why isn't this fatal? */
+ warn_user("NoMemory", 0);
+ } else {
+ tree_update_URL_node(tree, entry, url, data, false);
+ }
+
+
+ xmlFree(title);
+ free(url);
+}
+
+/**
+ * Parse a directory represented as a ul.
+ *
+ * \param ul xmlNode for parsed ul
+ * \param directory directory to add this directory to
+ */
+static void tree_url_load_directory(xmlNode *ul, struct tree *tree,
+ struct node *directory, tree_node_user_callback callback,
+ void *callback_data)
+{
+ char *title;
+ struct node *dir;
+ xmlNode *xmlnode;
+
+ assert(ul != NULL);
+ assert(directory != NULL);
+
+ for (xmlnode = ul->children; xmlnode; xmlnode = xmlnode->next) {
+ /* The ul may contain entries as a li, or directories as
+ * an h4 followed by a ul. Non-element nodes may be present
+ * (eg. text, comments), and are ignored. */
+
+ if (xmlnode->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (strcmp((const char *)xmlnode->name, "li") == 0) {
+ /* entry */
+ tree_url_load_entry(xmlnode, tree, directory, callback,
+ callback_data);
+
+ } else if (strcmp((const char *)xmlnode->name, "h4") == 0) {
+ /* directory */
+ title = (char *) xmlNodeGetContent(xmlnode );
+ if (!title) {
+ warn_user("TreeLoadError", "(Empty <h4> "
+ "or memory exhausted.)");
+ return;
+ }
+
+ for (xmlnode = xmlnode->next;
+ xmlnode && xmlnode->type != XML_ELEMENT_NODE;
+ xmlnode = xmlnode->next)
+ ;
+ if ((xmlnode == NULL) ||
+ strcmp((const char *)xmlnode->name, "ul") != 0) {
+ /* next element isn't expected ul */
+ free(title);
+ warn_user("TreeLoadError", "(Expected "
+ "<ul> not present.)");
+ return;
+ }
+
+ dir = tree_create_folder_node(tree, directory, title,
+ true, false, false);
+ if (dir == NULL) {
+ free(title);
+ return;
+ }
+
+ if (callback != NULL)
+ tree_set_node_user_callback(dir, callback,
+ callback_data);
+
+ if (folder_icon != NULL)
+ tree_set_node_icon(tree, dir, folder_icon);
+
+ tree_url_load_directory(xmlnode, tree, dir, callback,
+ callback_data);
+ }
+ }
+}
+
+/**
+ * Loads an url tree from a specified file.
+ *
+ * \param filename name of file to read
+ * \param tree empty tree which data will be read into
+ * \return the file represented as a tree, or NULL on failure
+ */
+bool tree_urlfile_load(const char *filename, struct tree *tree,
+ tree_node_user_callback callback, void *callback_data)
+{
+ xmlDoc *doc;
+ xmlNode *html, *body, *ul;
+ struct node *root;
+ FILE *fp = NULL;
+
+ if (filename == NULL) {
+ return false;
+ }
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ return false;
+ }
+ fclose(fp);
+
+ doc = htmlParseFile(filename, "iso-8859-1");
+ if (doc == NULL) {
+ warn_user("TreeLoadError", messages_get("ParsingFail"));
+ return false;
+ }
+
+ html = tree_url_find_xml_element((xmlNode *) doc, "html");
+ body = tree_url_find_xml_element(html, "body");
+ ul = tree_url_find_xml_element(body, "ul");
+ if (ul == NULL) {
+ xmlFreeDoc(doc);
+ warn_user("TreeLoadError",
+ "(<html>...<body>...<ul> not found.)");
+ return false;
+ }
+
+ root = tree_get_root(tree);
+ tree_url_load_directory(ul, tree, root, callback, callback_data);
+ tree_set_node_expanded(tree, root, true, false, false);
+
+ xmlFreeDoc(doc);
+ return true;
+}
+
+/**
+ * Add an entry to the HTML tree for saving.
+ *
+ * The node must contain a sequence of node_elements in the following order:
+ *
+ * \param entry hotlist entry to add
+ * \param node node to add li to
+ * \return true on success, false on memory exhaustion
+ */
+static bool tree_url_save_entry(struct node *entry, xmlNode *node)
+{
+ xmlNode *li, *a;
+ xmlAttr *href;
+ const char *text;
+
+ li = xmlNewChild(node, NULL, (const xmlChar *) "li", NULL);
+ if (li == NULL)
+ return false;
+
+
+ text = tree_url_node_get_title(entry);
+ if (text == NULL)
+ return false;
+ a = xmlNewTextChild(li, NULL, (const xmlChar *) "a",
+ (const xmlChar *) text);
+ if (a == NULL)
+ return false;
+
+ text = tree_url_node_get_url(entry);
+ if (text == NULL)
+ return false;
+
+ href = xmlNewProp(a, (const xmlChar *) "href", (const xmlChar *) text);
+ if (href == NULL)
+ return false;
+ return true;
+}
+
+/**
+ * Add a directory to the HTML tree for saving.
+ *
+ * \param directory hotlist directory to add
+ * \param node node to add ul to
+ * \return true on success, false on memory exhaustion
+ */
+static bool tree_url_save_directory(struct node *directory, xmlNode *node)
+{
+ struct node *child;
+ xmlNode *ul, *h4;
+ const char *text;
+
+ ul = xmlNewChild(node, NULL, (const xmlChar *)"ul", NULL);
+ if (ul == NULL)
+ return false;
+
+ for (child = tree_node_get_child(directory); child;
+ child = tree_node_get_next(child)) {
+ if (!tree_node_is_folder(child)) {
+ /* entry */
+ if (!tree_url_save_entry(child, ul))
+ return false;
+ } else {
+ /* directory */
+ /* invalid HTML */
+
+ text = tree_url_node_get_title(child);
+ if (text == NULL)
+ return false;
+
+ h4 = xmlNewTextChild(ul, NULL,
+ (const xmlChar *) "h4",
+ (const xmlChar *) text);
+ if (h4 == NULL)
+ return false;
+
+ if (!tree_url_save_directory(child, ul))
+ return false;
+ } }
+
+ return true;
+}
+
+
+
+
+
+
+
+
+/**
+ * Perform a save to a specified file in the form of a html page
+ *
+ * \param filename the file to save to
+ * \param page_title title of the page
+ */
+bool tree_urlfile_save(struct tree *tree, const char *filename,
+ const char *page_title)
+{
+ int res;
+ xmlDoc *doc;
+ xmlNode *html, *head, *title, *body;
+
+ /* Unfortunately the Browse Hotlist format is invalid HTML,
+ * so this is a lie.
+ */
+ doc = htmlNewDoc(
+ (const xmlChar *) "http://www.w3.org/TR/html4/strict.dtd",
+ (const xmlChar *) "-//W3C//DTD HTML 4.01//EN");
+ if (doc == NULL) {
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
+ html = xmlNewNode(NULL, (const xmlChar *) "html");
+ if (html == NULL) {
+ warn_user("NoMemory", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+ xmlDocSetRootElement(doc, html);
+
+ head = xmlNewChild(html, NULL, (const xmlChar *) "head", NULL);
+ if (head == NULL) {
+ warn_user("NoMemory", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+
+ title = xmlNewTextChild(head, NULL, (const xmlChar *) "title",
+ (const xmlChar *) page_title);
+ if (title == NULL) {
+ warn_user("NoMemory", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+
+ body = xmlNewChild(html, NULL, (const xmlChar *) "body", NULL);
+ if (body == NULL) {
+ warn_user("NoMemory", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+
+ if (!tree_url_save_directory(tree_get_root(tree), body)) {
+ warn_user("NoMemory", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+
+ doc->charset = XML_CHAR_ENCODING_UTF8;
+ res = htmlSaveFileEnc(filename, doc, "iso-8859-1");
+ if (res == -1) {
+ warn_user("HotlistSaveError", 0);
+ xmlFreeDoc(doc);
+ return false;
+ }
+
+ xmlFreeDoc(doc);
+ return true;
+}
diff --git a/desktop/tree_url_node.h b/desktop/tree_url_node.h
new file mode 100644
index 000000000..4bee73ebc
--- /dev/null
+++ b/desktop/tree_url_node.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Creation of URL nodes with use of trees public API
+ */
+
+#ifndef _NETSURF_DESKTOP_TREE_URL_NODE_H_
+#define _NETSURF_DESKTOP_TREE_URL_NODE_H_
+
+
+#include "desktop/tree.h"
+
+void tree_url_node_init(void);
+struct node *tree_create_URL_node(struct tree *tree,
+ struct node *parent, const char *url, const char *title,
+ tree_node_user_callback, void *callback_data);
+struct node *tree_create_URL_node_shared(struct tree *tree,
+ struct node *parent, const char *url,
+ const struct url_data *data,
+ tree_node_user_callback, void *callback_data);
+void tree_update_URL_node(struct tree *tree,struct node *node,
+ const char *url, const struct url_data *data, bool shared);
+const char *tree_url_node_get_title(struct node *node);
+const char *tree_url_node_get_url(struct node *node);
+void tree_url_node_edit_title(struct tree *tree, struct node *node);
+void tree_url_node_edit_url(struct tree *tree, struct node *node);
+
+node_callback_resp tree_url_node_callback(void *user_data,
+ struct node_msg_data *msg_data);
+
+bool tree_urlfile_load(const char *filename, struct tree *tree,
+ tree_node_user_callback, void *callback_data);
+bool tree_urlfile_save(struct tree *tree, const char *filename,
+ const char *page_title);
+
+/* front end specific */
+void tree_icon_name_from_content_type(char *buffer, content_type type);
+
+#endif
diff --git a/framebuffer/misc.c b/framebuffer/misc.c
index 889e3ec3f..ac15c5293 100644
--- a/framebuffer/misc.c
+++ b/framebuffer/misc.c
@@ -35,12 +35,6 @@ void die(const char *error)
exit(1);
}
-bool cookies_update(const char *domain, const struct cookie_data *data)
-{
- return true;
-}
-
-
/**
* Return the filename part of a full path
*
diff --git a/framebuffer/tree.c b/framebuffer/tree.c
index e5cb390b5..61e32e0a5 100644
--- a/framebuffer/tree.c
+++ b/framebuffer/tree.c
@@ -18,45 +18,56 @@
#include "desktop/tree.h"
-void tree_initialise_redraw(struct tree *tree)
-{
-}
-
-void tree_redraw_area(struct tree *tree, int x, int y, int width, int height)
-{
-}
-
-void tree_draw_line(int x, int y, int width, int height)
-{
-}
-
-void tree_draw_node_element(struct tree *tree, struct node_element *element)
-{
-}
-
-void tree_draw_node_expansion(struct tree *tree, struct node *node)
-{
-}
+const char tree_directory_icon_name[] = "directory.png";
+const char tree_content_icon_name[] = "content.png";
-void tree_recalculate_node_element(struct node_element *element)
-{
-}
-void tree_update_URL_node(struct node *node, const char *url,
- const struct url_data *data)
-{
-}
-void tree_resized(struct tree *tree)
-{
-}
-void tree_set_node_sprite_folder(struct node *node)
-{
-}
-
-void tree_set_node_sprite(struct node *node, const char *sprite,
- const char *expanded)
+/**
+ * Translates a content_type to the name of a respective icon
+ *
+ * \param content_type content type
+ * \param buffer buffer for the icon name
+ */
+void tree_icon_name_from_content_type(char *buffer, content_type type)
{
+ // TODO: design/acquire icons
+ switch (type) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ case CONTENT_CSS:
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ case CONTENT_PNG:
+#endif
+#ifdef WITH_MNG
+ case CONTENT_JNG:
+ case CONTENT_MNG:
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+#endif
+#ifdef WITH_BMP
+ case CONTENT_BMP:
+ case CONTENT_ICO:
+#endif
+#ifdef WITH_SPRITE
+ case CONTENT_SPRITE:
+#endif
+#ifdef WITH_DRAW
+ case CONTENT_DRAW:
+#endif
+#ifdef WITH_ARTWORKS
+ case CONTENT_ARTWORKS:
+#endif
+#ifdef WITH_NS_SVG
+ case CONTENT_SVG:
+#endif
+ default:
+ sprintf(buffer, tree_content_icon_name);
+ break;
+ }
}
-
diff --git a/gtk/gtk_cookies.c b/gtk/gtk_cookies.c
new file mode 100644
index 000000000..1576290ad
--- /dev/null
+++ b/gtk/gtk_cookies.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Cookies (implementation).
+ */
+
+
+#include "desktop/cookies.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "gtk/gtk_gui.h"
+#include "gtk/gtk_cookies.h"
+#include "gtk/gtk_plotters.h"
+#include "gtk/gtk_scaffolding.h"
+#include "gtk/gtk_treeview.h"
+
+#define GLADE_NAME "cookies.glade"
+
+#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \
+ GtkMenuItem *widget, gpointer g)
+#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) }
+#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \
+ gpointer g)
+
+struct menu_events {
+ const char *widget;
+ GCallback handler;
+};
+
+static void nsgtk_cookies_init_menu(void);
+
+/* edit menu */
+MENUPROTO(delete_selected);
+MENUPROTO(delete_all);
+MENUPROTO(select_all);
+MENUPROTO(clear_selection);
+
+/* view menu*/
+MENUPROTO(expand_all);
+MENUPROTO(expand_domains);
+MENUPROTO(expand_cookies);
+MENUPROTO(collapse_all);
+MENUPROTO(collapse_domains);
+MENUPROTO(collapse_cookies);
+
+
+static struct menu_events menu_events[] = {
+
+ /* edit menu */
+ MENUEVENT(delete_selected),
+ MENUEVENT(delete_all),
+ MENUEVENT(select_all),
+ MENUEVENT(clear_selection),
+
+ /* view menu*/
+ MENUEVENT(expand_all),
+ MENUEVENT(expand_domains),
+ MENUEVENT(expand_cookies),
+ MENUEVENT(collapse_all),
+ MENUEVENT(collapse_domains),
+ MENUEVENT(collapse_cookies),
+
+ {NULL, NULL}
+};
+
+static struct nsgtk_treeview *cookies_window;
+static GladeXML *gladeFile;
+GtkWindow *wndCookies;
+
+/**
+ * Creates the window for the cookies tree.
+ */
+void nsgtk_cookies_init(void)
+{
+ gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL);
+ gladeFile = glade_xml_new(glade_location, NULL, NULL);
+ g_free(glade_location);
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
+
+ glade_xml_signal_autoconnect(gladeFile);
+
+ wndCookies = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndCookies"));
+ window = wndCookies;
+
+ scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile,
+ "cookiesScrolled"));
+
+ drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile,
+ "cookiesDrawingArea"));
+
+ cookies_window = nsgtk_treeview_create(cookies_get_tree_flags(), window,
+ scrolled, drawing_area);
+
+ if (cookies_window == NULL)
+ return;
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+
+ CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL);
+ CONNECT(window, "hide", nsgtk_tree_window_hide, cookies_window);
+
+ cookies_initialise(nsgtk_treeview_get_tree(cookies_window));
+
+ nsgtk_cookies_init_menu();
+}
+
+/**
+ * Connects menu events in the cookies window.
+ */
+void nsgtk_cookies_init_menu()
+{
+ struct menu_events *event = menu_events;
+
+ while (event->widget != NULL)
+ {
+ GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget);
+ g_signal_connect(G_OBJECT(w), "activate", event->handler,
+ cookies_window);
+ event++;
+ }
+}
+
+/**
+ * Destroys the cookies window and performs any other necessary cleanup actions.
+ */
+void nsgtk_cookies_destroy(void)
+{
+ /* TODO: what about gladeFile? */
+ cookies_cleanup();
+ nsgtk_treeview_destroy(cookies_window);
+}
+
+
+/* edit menu */
+MENUHANDLER(delete_selected)
+{
+ cookies_delete_selected();
+ return TRUE;
+}
+
+MENUHANDLER(delete_all)
+{
+ cookies_delete_all();
+ return TRUE;
+}
+
+MENUHANDLER(select_all)
+{
+ cookies_select_all();
+ return TRUE;
+}
+
+MENUHANDLER(clear_selection)
+{
+ cookies_clear_selection();
+ return TRUE;
+}
+
+/* view menu*/
+MENUHANDLER(expand_all)
+{
+ cookies_expand_all();
+ return TRUE;
+}
+
+MENUHANDLER(expand_domains)
+{
+ cookies_expand_domains();
+ return TRUE;
+}
+
+MENUHANDLER(expand_cookies)
+{
+ cookies_expand_cookies();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_all)
+{
+ cookies_collapse_all();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_domains)
+{
+ cookies_collapse_domains();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_cookies)
+{
+ cookies_collapse_cookies();
+ return TRUE;
+}
diff --git a/framebuffer/hotlist.c b/gtk/gtk_cookies.h
index 727200fe3..7048e2da9 100644
--- a/framebuffer/hotlist.c
+++ b/gtk/gtk_cookies.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,8 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "desktop/browser.h"
+/** \file
+ * Cookies (interface).
+ */
+
+#ifndef __NSGTK_COOKIES_H__
+#define __NSGTK_COOKIES_H__
+
+#include <gtk/gtk.h>
+
+extern GtkWindow *wndCookies;
+
+void nsgtk_cookies_init(void);
+void nsgtk_cookies_destroy(void);
-void hotlist_visited(struct hlcache_handle *content)
-{
-}
+#endif /* __NSGTK_COOKIES_H__ */
diff --git a/gtk/gtk_gui.c b/gtk/gtk_gui.c
index 1ca8ce533..a41789a41 100644
--- a/gtk/gtk_gui.c
+++ b/gtk/gtk_gui.c
@@ -49,20 +49,25 @@
#include "desktop/browser.h"
#include "desktop/cookies.h"
#include "desktop/gui.h"
+#include "desktop/history_global_core.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "desktop/save_pdf/pdf_plotters.h"
#include "desktop/searchweb.h"
+#include "desktop/sslcert.h"
#include "desktop/textinput.h"
-#include "gtk/gtk_gui.h"
#include "gtk/dialogs/gtk_options.h"
#include "gtk/gtk_completion.h"
+#include "gtk/gtk_cookies.h"
+#include "gtk/gtk_download.h"
+#include "gtk/gtk_filetype.h"
+#include "gtk/gtk_gui.h"
+#include "gtk/gtk_history.h"
+#include "gtk/gtk_hotlist.h"
+#include "gtk/gtk_throbber.h"
+#include "gtk/gtk_treeview.h"
#include "gtk/gtk_window.h"
#include "gtk/options.h"
-#include "gtk/gtk_throbber.h"
-#include "gtk/gtk_history.h"
-#include "gtk/gtk_filetype.h"
-#include "gtk/gtk_download.h"
#include "gtk/gtk_schedule.h"
#include "render/box.h"
@@ -101,7 +106,9 @@ static struct browser_window *select_menu_bw;
static struct form_control *select_menu_control;
static void nsgtk_ssl_accept(GtkButton *w, gpointer data);
-static void nsgtk_ssl_reject(GtkButton *w, gpointer data);
+static void nsgtk_ssl_reject(GtkWidget *w, gpointer data);
+static gboolean nsgtk_ssl_delete_event(GtkWidget *w, GdkEvent *event,
+ gpointer data);
static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
gpointer user_data);
#ifdef WITH_PDF_EXPORT
@@ -377,6 +384,24 @@ static void check_options(char **respath)
LOG(("Using '%s' as download directory", hdir));
option_downloads_directory = hdir;
}
+
+ if (!option_tree_icons_dir) {
+ sfindresourcedef(respath, buf, "icons/", "~/.netsurf/");
+ LOG(("Using '%s' as Tree icons dir", buf));
+ option_tree_icons_dir = strdup(buf);
+ }
+ if (!option_tree_icons_dir)
+ die("Failed initialising tree icons option");
+
+
+ if (!option_hotlist_path) {
+ sfindresourcedef(respath, buf, "Hotlist", "~/.netsurf/");
+ LOG(("Using '%s' as Hotlist file", buf));
+ option_hotlist_path = strdup(buf);
+ }
+ if (!option_hotlist_path)
+ die("Failed initialising hotlist option");
+
sfindresourcedef(respath, buf, "Print", "~/.netsurf/");
LOG(("Using '%s' as Print Settings file", buf));
@@ -483,6 +508,10 @@ static void gui_init(int argc, char** argv, char **respath)
if (nsgtk_download_init() == false)
die("Unable to initialise download window.\n");
+ nsgtk_cookies_init();
+ nsgtk_hotlist_init();
+ sslcert_init();
+
if (option_homepage_url != NULL && option_homepage_url[0] != '\0')
addr = option_homepage_url;
@@ -642,11 +671,16 @@ void gui_quit(void)
nsgtk_download_destroy();
urldb_save_cookies(option_cookie_jar);
urldb_save(option_url_file);
+ nsgtk_cookies_destroy();
+ nsgtk_history_destroy();
+ nsgtk_hotlist_destroy();
+ sslcert_cleanup();
free(default_stylesheet_url);
free(quirks_stylesheet_url);
free(adblock_stylesheet_url);
free(option_cookie_file);
free(option_cookie_jar);
+ free(option_tree_icons_dir);
free(print_options_file_location);
free(search_engines_file_location);
free(search_default_ico_location);
@@ -744,73 +778,88 @@ void die(const char * const error)
}
-void hotlist_visited(hlcache_handle *content)
-{
-}
-
void gui_cert_verify(const char *url, const struct ssl_cert_info *certs,
unsigned long num, nserror (*cb)(bool proceed, void *pw),
void *cbpw)
-{
+{
+ static struct nsgtk_treeview *ssl_window;
+ struct sslcert_session_data *data;
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 *), 5);
+ void **session = calloc(sizeof(void *), 3);
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
- session[0] = strdup(url);
- session[1] = cb;
- session[2] = cbpw;
- session[3] = x;
- session[4] = wnd;
+ data = sslcert_create_session_data(num, url, cb, cbpw);
+
+ window = GTK_WINDOW(
+ glade_xml_get_widget(x,"wndSSLProblem"));
+ scrolled = GTK_SCROLLED_WINDOW(
+ glade_xml_get_widget(x,"SSLScrolled"));
+ drawing_area = GTK_DRAWING_AREA(
+ glade_xml_get_widget(x,"SSLDrawingArea"));
- accept = GTK_BUTTON(glade_xml_get_widget(x, "sslaccept"));
- reject = GTK_BUTTON(glade_xml_get_widget(x, "sslreject"));
- g_signal_connect(G_OBJECT(accept), "clicked",
- G_CALLBACK(nsgtk_ssl_accept), (gpointer)session);
- g_signal_connect(G_OBJECT(reject), "clicked",
- G_CALLBACK(nsgtk_ssl_reject), (gpointer)session);
+ ssl_window = nsgtk_treeview_create(sslcert_get_tree_flags(),
+ window, scrolled, drawing_area);
+
+ if (ssl_window == NULL)
+ return;
+
+ sslcert_load_tree(nsgtk_treeview_get_tree(ssl_window), certs, data);
+
+ accept = GTK_BUTTON(glade_xml_get_widget(x, "sslaccept"));
+ reject = GTK_BUTTON(glade_xml_get_widget(x, "sslreject"));
- gtk_widget_show(GTK_WIDGET(wnd));
+ session[0] = x;
+ session[1] = ssl_window;
+ session[2] = data;
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+
+ CONNECT(accept, "clicked", nsgtk_ssl_accept, session);
+ CONNECT(reject, "clicked", nsgtk_ssl_reject, session);
+ CONNECT(window, "delete_event", G_CALLBACK(nsgtk_ssl_delete_event),
+ (gpointer)session);
+
+ gtk_widget_show(GTK_WIDGET(window));
}
-
void nsgtk_ssl_accept(GtkButton *w, gpointer data)
{
void **session = data;
- char *url = session[0];
- nserror (*cb)(bool proceed, void *pw) = session[1];
- void *cbpw = session[2];
- GladeXML *x = session[3];
- GtkWindow *wnd = session[4];
+ GladeXML *x = session[0];
+ struct nsgtk_treeview *wnd = session[1];
+ struct sslcert_session_data *ssl_data = session[2];
- urldb_set_cert_permissions(url, true);
-
- cb(true, cbpw);
-
- gtk_widget_destroy(GTK_WIDGET(wnd));
+ sslcert_accept(ssl_data);
+
+ nsgtk_treeview_destroy(wnd);
g_object_unref(G_OBJECT(x));
- free(url);
free(session);
}
-
-void nsgtk_ssl_reject(GtkButton *w, gpointer data)
+void nsgtk_ssl_reject(GtkWidget *w, gpointer data)
{
void **session = data;
- nserror (*cb)(bool proceed, void *pw) = session[1];
- void *cbpw = session[2];
- GladeXML *x = session[3];
- GtkWindow *wnd = session[4];
-
- cb(false, cbpw);
+ GladeXML *x = session[0];
+ struct nsgtk_treeview *wnd = session[1];
+ struct sslcert_session_data *ssl_data = session[2];
- gtk_widget_destroy(GTK_WIDGET(wnd));
+ sslcert_reject(ssl_data);
+
+ nsgtk_treeview_destroy(wnd);
g_object_unref(G_OBJECT(x));
- free(session[0]);
free(session);
}
+gboolean nsgtk_ssl_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
+{
+ nsgtk_ssl_reject(w, data);
+ return FALSE;
+}
utf8_convert_ret utf8_to_local_encoding(const char *string, size_t len,
char **result)
@@ -883,12 +932,6 @@ char *url_to_path(const char *url)
return respath;
}
-
-bool cookies_update(const char *domain, const struct cookie_data *data)
-{
- return true;
-}
-
#ifdef WITH_PDF_EXPORT
void PDF_Password(char **owner_pass, char **user_pass, char *path)
diff --git a/gtk/gtk_history.c b/gtk/gtk_history.c
index ed0c912f6..75b392fb3 100644
--- a/gtk/gtk_history.c
+++ b/gtk/gtk_history.c
@@ -1,5 +1,6 @@
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,612 +17,248 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
+#include "desktop/history_global_core.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "gtk/gtk_gui.h"
+#include "gtk/gtk_history.h"
+#include "gtk/gtk_plotters.h"
+#include "gtk/gtk_scaffolding.h"
+#include "gtk/gtk_treeview.h"
#include "utils/log.h"
#include "utils/utils.h"
-#include "utils/url.h"
-#include "utils/messages.h"
-#include "content/urldb.h"
-#include "gtk/gtk_history.h"
-#include "gtk/gtk_gui.h"
-#include "gtk/gtk_window.h"
-#include "gtk/gtk_bitmap.h"
-enum
-{
- SITE_TITLE = 0,
- SITE_DOMAIN,
- SITE_ADDRESS,
- SITE_LASTVISIT,
- SITE_TOTALVISITS,
- SITE_THUMBNAIL,
- SITE_NCOLS
+#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \
+ GtkMenuItem *widget, gpointer g)
+#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) }
+#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \
+ gpointer g)
+
+struct menu_events {
+ const char *widget;
+ GCallback handler;
};
-enum
-{
- DOM_DOMAIN,
- DOM_LASTVISIT,
- DOM_TOTALVISITS,
- DOM_HAS_SITES,
- DOM_NCOLS
+static void nsgtk_history_init_menu(void);
+
+/* file menu*/
+MENUPROTO(export);
+
+/* edit menu */
+MENUPROTO(delete_selected);
+MENUPROTO(delete_all);
+MENUPROTO(select_all);
+MENUPROTO(clear_selection);
+
+/* view menu*/
+MENUPROTO(expand_all);
+MENUPROTO(expand_directories);
+MENUPROTO(expand_addresses);
+MENUPROTO(collapse_all);
+MENUPROTO(collapse_directories);
+MENUPROTO(collapse_addresses);
+
+MENUPROTO(launch);
+
+static struct menu_events menu_events[] = {
+
+ /* file menu*/
+ MENUEVENT(export),
+
+ /* edit menu */
+ MENUEVENT(delete_selected),
+ MENUEVENT(delete_all),
+ MENUEVENT(select_all),
+ MENUEVENT(clear_selection),
+
+ /* view menu*/
+ MENUEVENT(expand_all),
+ MENUEVENT(expand_directories),
+ MENUEVENT(expand_addresses),
+ MENUEVENT(collapse_all),
+ MENUEVENT(collapse_directories),
+ MENUEVENT(collapse_addresses),
+
+ MENUEVENT(launch),
+ {NULL, NULL}
};
-GtkWindow *wndHistory;
+static struct nsgtk_treeview *global_history_window;
static GladeXML *gladeFile;
+GtkWindow *wndHistory;
-static const gchar* dateToday;
-static const gchar* dateYesterday;
-static const gchar* dateAt;
-static const gchar* domainAll;
-
-static struct history_model *history;
-
-static void nsgtk_history_init_model(void);
-static void nsgtk_history_init_filters(void);
-static void nsgtk_history_init_sort(void);
-static void nsgtk_history_init_treeviews(void);
-static void nsgtk_history_init_list(void);
-
-static bool nsgtk_history_add_internal(const char *, const struct url_data *);
-
-static void nsgtk_history_show_domain(GtkTreeSelection *treesel,
- GString *domain_filter);
-
-static void nsgtk_history_show_all(void);
-
-static gboolean nsgtk_history_filter_search(GtkTreeModel *model,
- GtkTreeIter *iter, GtkWidget *search_entry);
-static gboolean nsgtk_history_filter_sites(GtkTreeModel *model,
- GtkTreeIter *iter, GString *domain_filter);
-
-static gchar *nsgtk_history_parent_get(gchar *domain);
-static void nsgtk_history_parent_update(gchar *path, const struct url_data *data);
-
-static void nsgtk_history_domain_sort_changed(GtkComboBox *combo);
-static gint nsgtk_history_domain_sort_compare(GtkTreeModel *model, GtkTreeIter *a,
- GtkTreeIter *b, gint sort_column);
-static void nsgtk_history_domain_set_visible (GtkTreeModel *model,
- GtkTreePath *path, GtkTreeIter *iter, gboolean has_sites);
-
-static void nsgtk_history_search(void);
-static void nsgtk_history_search_clear (GtkEntry *entry);
-
-static gchar *nsgtk_history_date_parse(time_t visit_time);
-static void nsgtk_history_row_activated(GtkTreeView *, GtkTreePath *,
- GtkTreeViewColumn *);
-static void nsgtk_history_update_info(GtkTreeSelection *treesel,
- gboolean domain);
-static void nsgtk_history_scroll_top (GtkScrolledWindow *scrolled_window);
+/**
+ * Creates the window for the global history tree.
+ */
bool nsgtk_history_init(void)
{
- dateToday = messages_get("DateToday");
- dateYesterday = messages_get("DateYesterday");
- dateAt = messages_get("DateAt");
- domainAll = messages_get("DomainAll");
-
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
+
gladeFile = glade_xml_new(glade_history_file_location, NULL, NULL);
if (gladeFile == NULL)
return false;
glade_xml_signal_autoconnect(gladeFile);
- wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndHistory"));
-
- nsgtk_history_init_model();
- nsgtk_history_init_list();
- nsgtk_history_init_filters();
- nsgtk_history_init_sort();
- nsgtk_history_init_treeviews();
-
- nsgtk_history_show_all();
-
- return true;
-}
-
-void nsgtk_history_init_model(void)
-{
- history = malloc(sizeof(struct history_model));
- history->history_list = gtk_list_store_new(SITE_NCOLS,
- G_TYPE_STRING, /* title */
- G_TYPE_STRING, /* domain */
- G_TYPE_STRING, /* address */
- G_TYPE_INT, /* last visit */
- G_TYPE_INT, /* num visits */
- G_TYPE_POINTER); /* thumbnail */
- history->history_filter = gtk_tree_model_filter_new(
- GTK_TREE_MODEL(history->history_list), NULL);
+ wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndHistory"));
- history->site_filter = gtk_tree_model_filter_new(
- history->history_filter,NULL);
- history->site_sort = gtk_tree_model_sort_new_with_model(history->site_filter);
- history->site_treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeFile,
- "treeHistory"));
- history->site_selection =
- gtk_tree_view_get_selection(history->site_treeview);
+ window = wndHistory;
- history->domain_list = gtk_list_store_new(DOM_NCOLS,
- G_TYPE_STRING, /* domain */
- G_TYPE_INT, /* last visit */
- G_TYPE_INT, /* num visits */
- G_TYPE_BOOLEAN); /* has sites */
- history->domain_filter = gtk_tree_model_filter_new(
- GTK_TREE_MODEL(history->domain_list), NULL);
- history->domain_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, g_free);
- history->domain_sort = gtk_tree_model_sort_new_with_model(
- history->domain_filter);
- history->domain_treeview = GTK_TREE_VIEW(glade_xml_get_widget(
- gladeFile,"treeDomain"));
- history->domain_selection =
- gtk_tree_view_get_selection(history->domain_treeview);
-}
+ scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile,
+ "globalHistoryScrolled"));
-void nsgtk_history_init_list(void)
-{
- GtkTreeIter iter;
+ drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile,
+ "globalHistoryDrawingArea"));
+
+ global_history_window = nsgtk_treeview_create(
+ history_global_get_tree_flags(), window, scrolled,
+ drawing_area);
- gtk_list_store_clear(history->history_list);
- gtk_list_store_clear(history->domain_list);
+ if (global_history_window == NULL)
+ return false;
- gtk_list_store_append(history->domain_list, &iter);
- gtk_list_store_set(history->domain_list, &iter,
- DOM_DOMAIN, domainAll,
- DOM_LASTVISIT, -2,
- DOM_TOTALVISITS, -2,
- DOM_HAS_SITES, TRUE,
- -1);
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
- urldb_iterate_entries(nsgtk_history_add_internal);
-}
-
-void nsgtk_history_init_filters(void)
-{
- GtkWidget *search_entry, *clear_button;
- GString *filter_string = g_string_new(NULL);
-
- search_entry = glade_xml_get_widget(gladeFile,"entrySearch");
- clear_button = glade_xml_get_widget(gladeFile,"buttonClearSearch");
+ CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL);
+ CONNECT(window, "hide", nsgtk_tree_window_hide, global_history_window);
- g_signal_connect(G_OBJECT(search_entry), "changed",
- G_CALLBACK(nsgtk_history_search), NULL);
- g_signal_connect_swapped(G_OBJECT(clear_button), "clicked",
- G_CALLBACK(nsgtk_history_search_clear),
- GTK_ENTRY(search_entry));
+ history_global_initialise(
+ nsgtk_treeview_get_tree(global_history_window));
- gtk_tree_model_filter_set_visible_func(
- GTK_TREE_MODEL_FILTER(history->history_filter),
- (GtkTreeModelFilterVisibleFunc)
- nsgtk_history_filter_search, search_entry, NULL);
- gtk_tree_model_filter_set_visible_func(
- GTK_TREE_MODEL_FILTER(history->site_filter),
- (GtkTreeModelFilterVisibleFunc)
- nsgtk_history_filter_sites, filter_string, NULL);
- gtk_tree_model_filter_set_visible_column(
- GTK_TREE_MODEL_FILTER(history->domain_filter),
- DOM_HAS_SITES);
-
- g_signal_connect(G_OBJECT(history->site_selection), "changed",
- G_CALLBACK(nsgtk_history_update_info), FALSE);
- g_signal_connect(G_OBJECT(history->domain_selection), "changed",
- G_CALLBACK(nsgtk_history_show_domain), filter_string);
+ nsgtk_history_init_menu();
+
+ return true;
}
-void nsgtk_history_init_sort(void)
-{
- GtkWidget *domain_window = glade_xml_get_widget(gladeFile,
- "windowDomain");
- GtkComboBox *sort_combo_box =
- GTK_COMBO_BOX(glade_xml_get_widget(
- gladeFile, "comboSort"));
- gtk_combo_box_set_active(sort_combo_box, 0);
-
- g_signal_connect(G_OBJECT(sort_combo_box), "changed",
- G_CALLBACK(nsgtk_history_domain_sort_changed), NULL);
- g_signal_connect_swapped(G_OBJECT(sort_combo_box), "changed",
- G_CALLBACK(nsgtk_history_scroll_top), domain_window);
-
- gtk_tree_sortable_set_sort_func(
- GTK_TREE_SORTABLE(history->domain_sort),
- DOM_LASTVISIT, (GtkTreeIterCompareFunc)
- nsgtk_history_domain_sort_compare,
- GUINT_TO_POINTER(DOM_LASTVISIT), NULL);
- gtk_tree_sortable_set_sort_func(
- GTK_TREE_SORTABLE(history->domain_sort),
- DOM_TOTALVISITS, (GtkTreeIterCompareFunc)
- nsgtk_history_domain_sort_compare,
- GUINT_TO_POINTER(DOM_TOTALVISITS), NULL);
- gtk_tree_sortable_set_sort_func(
- GTK_TREE_SORTABLE(history->site_sort),
- SITE_LASTVISIT, (GtkTreeIterCompareFunc)
- nsgtk_history_domain_sort_compare,
- GUINT_TO_POINTER(SITE_LASTVISIT), NULL);
- gtk_tree_sortable_set_sort_func(
- GTK_TREE_SORTABLE(history->site_sort),
- SITE_TOTALVISITS, (GtkTreeIterCompareFunc)
- nsgtk_history_domain_sort_compare,
- GUINT_TO_POINTER(SITE_TOTALVISITS), NULL);
-}
-
-void nsgtk_history_init_treeviews(void)
-{
- GtkCellRenderer *renderer;
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(history->site_treeview, -1,
- messages_get("Title"), renderer,
- "text", SITE_TITLE,
- NULL);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(history->domain_treeview,
- -1, messages_get("Domain"), renderer,
- "markup", DOM_DOMAIN,
- NULL);
-
- gtk_tree_view_set_model(history->site_treeview, history->site_sort);
- gtk_tree_view_set_model(history->domain_treeview, history->domain_sort);
-
- g_signal_connect(history->site_treeview, "row-activated",
- G_CALLBACK(nsgtk_history_row_activated), NULL);
-}
-bool nsgtk_history_add_internal(const char *url, const struct url_data *data)
+/**
+ * Connects menu events in the global history window.
+ */
+void nsgtk_history_init_menu(void)
{
- GtkTreeIter iter;
- gchar *domain, *path;
- if (url_host(url, &domain) != URL_FUNC_OK)
- strcpy(domain, messages_get("gtkUnknownHost"));
+ struct menu_events *event = menu_events;
- if (data->visits > 0)
+ while (event->widget != NULL)
{
- path = nsgtk_history_parent_get(domain);
- nsgtk_history_parent_update(path, data);
-
- gtk_list_store_append(history->history_list, &iter);
- gtk_list_store_set(history->history_list, &iter,
- SITE_TITLE, data->title ? data->title :
- url,
- SITE_DOMAIN, domain,
- SITE_ADDRESS, url,
- SITE_LASTVISIT, data->last_visit,
- SITE_TOTALVISITS, data->visits,
- SITE_THUMBNAIL,
- gtk_bitmap_get_primary(
- urldb_get_thumbnail(url)),
- -1);
+ GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget);
+ g_signal_connect(G_OBJECT(w), "activate", event->handler,
+ global_history_window);
+ event++;
}
- return true;
}
-gchar *nsgtk_history_parent_get(gchar *domain)
-{
- GtkTreeIter iter;
- gchar *path;
-
- /* Adds an extra entry in the list to act as the root domain
- * (which will keep track of things like visits to all sites
- * in the domain), This does not work as a tree because the
- * children cannot be displayed if the root is hidden
- * (which would conflict with the site view) */
- path = g_hash_table_lookup(history->domain_hash, domain);
-
- if (path == NULL){
- gtk_list_store_append(history->domain_list, &iter);
- gtk_list_store_set(history->domain_list, &iter,
- DOM_DOMAIN, domain,
- DOM_LASTVISIT, messages_get("gtkUnknownHost"),
- DOM_TOTALVISITS, 0,
- -1);
-
- path = gtk_tree_model_get_string_from_iter(
- GTK_TREE_MODEL(history->domain_list), &iter);
- g_hash_table_insert(history->domain_hash, domain,
- path);
- }
- return path;
+/**
+ * Destroys the global history window and performs any other necessary cleanup
+ * actions.
+ */
+void nsgtk_history_destroy(void)
+{
+ /* TODO: what about gladeFile? */
+ history_global_cleanup();
+ nsgtk_treeview_destroy(global_history_window);
}
-void nsgtk_history_parent_update(gchar *path, const struct url_data *data)
-{
- GtkTreeIter iter;
- gint num_visits, last_visit;
-
- gtk_tree_model_get_iter_from_string(
- GTK_TREE_MODEL(history->domain_list), &iter, path);
- gtk_tree_model_get(GTK_TREE_MODEL(history->domain_list), &iter,
- DOM_TOTALVISITS, &num_visits,
- DOM_LASTVISIT, &last_visit,
- -1);
-
- gtk_list_store_set(history->domain_list, &iter,
- DOM_TOTALVISITS, num_visits + data->visits,
- DOM_LASTVISIT, max(last_visit,data->last_visit),
- -1);
-
- /* Handle "All" */
- gtk_tree_model_get_iter_from_string(
- GTK_TREE_MODEL(history->domain_list), &iter, "0");
- gtk_tree_model_get(GTK_TREE_MODEL(history->domain_list), &iter,
- DOM_TOTALVISITS, &num_visits,
- DOM_LASTVISIT, &last_visit,
- -1);
-
- gtk_list_store_set(history->domain_list, &iter,
- DOM_TOTALVISITS, num_visits + data->visits,
- DOM_LASTVISIT, max(last_visit,data->last_visit),
- -1);
-}
-void nsgtk_history_show_domain(GtkTreeSelection *treesel,
- GString *domain_filter)
+/* file menu*/
+MENUHANDLER(export)
{
- GtkTreeIter iter;
- GtkTreeModel *model;
-
- if (gtk_tree_selection_get_selected(treesel, &model, &iter)) {
- gtk_tree_model_get(model, &iter, DOM_DOMAIN,
- &domain_filter->str, -1);
- gtk_tree_model_filter_refilter(
- GTK_TREE_MODEL_FILTER(history->site_filter));
+ GtkWidget *save_dialog;
+ save_dialog = gtk_file_chooser_dialog_new("Save File",
+ wndHistory,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog),
+ getenv("HOME") ? getenv("HOME") : "/");
+
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog),
+ "history.html");
+
+ if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) {
+ gchar *filename = gtk_file_chooser_get_filename(
+ GTK_FILE_CHOOSER(save_dialog));
+
+ history_global_export(filename);
+ g_free(filename);
}
- nsgtk_history_update_info(treesel, TRUE);
-}
+ gtk_widget_destroy(save_dialog);
-static void nsgtk_history_show_all(void)
-{
- GtkTreePath *path = gtk_tree_path_new_from_string("0");
-
- gtk_tree_selection_select_path(history->domain_selection, path);
-
- gtk_tree_path_free(path);
+ return TRUE;
}
-gboolean nsgtk_history_filter_search(GtkTreeModel *model, GtkTreeIter *iter,
- GtkWidget *search_entry)
+/* edit menu */
+MENUHANDLER(delete_selected)
{
- gchar *title, *address, *domain, *path;
- gint result;
- GtkTreeIter new_iter;
- const gchar *search = gtk_entry_get_text(GTK_ENTRY(search_entry));
-
- gtk_tree_model_get(model, iter, SITE_TITLE, &title,
- SITE_ADDRESS, &address,
- SITE_DOMAIN, &domain,
- -1);
-
- if (title)
- result = (strstr(title, search) || strstr(address, search));
- else
- result = FALSE;
-
- if (result) {
- path = g_hash_table_lookup(history->domain_hash, domain);
- gtk_tree_model_get_iter_from_string(
- GTK_TREE_MODEL(history->domain_list),&new_iter,
- path);
-
- nsgtk_history_domain_set_visible(
- GTK_TREE_MODEL(history->domain_list), NULL,
- &new_iter, result);
- }
-
- g_free(title);
- g_free(address);
- g_free(domain);
-
- return result;
+ history_global_delete_selected();
+ return TRUE;
}
-gboolean nsgtk_history_filter_sites(GtkTreeModel *model, GtkTreeIter *iter,
- GString *domain_filter)
+MENUHANDLER(delete_all)
{
- gchar *domain;
- gboolean domain_match;
-
- gtk_tree_model_get(model, iter, SITE_DOMAIN, &domain, -1);
-
- if (domain && domain_filter->str)
- domain_match = g_str_equal(domain, domain_filter->str) ||
- g_str_equal(domain_filter->str,
- domainAll);
- else
- domain_match = FALSE;
-
- g_free(domain);
- return domain_match;
+ history_global_delete_all();
+ return TRUE;
}
-void nsgtk_history_domain_sort_changed(GtkComboBox *combo)
+MENUHANDLER(select_all)
{
- gint domain_options[] = { DOM_DOMAIN, DOM_LASTVISIT, DOM_TOTALVISITS };
- gint site_options[] = { SITE_TITLE, SITE_LASTVISIT, SITE_TOTALVISITS };
- gint sort = gtk_combo_box_get_active(combo);
-
- gtk_tree_sortable_set_sort_column_id(
- GTK_TREE_SORTABLE(history->domain_sort),
- domain_options[sort], GTK_SORT_ASCENDING);
- gtk_tree_sortable_set_sort_column_id(
- GTK_TREE_SORTABLE(history->site_sort),
- site_options[sort], GTK_SORT_ASCENDING);
+ history_global_select_all();
+ return TRUE;
}
-gint nsgtk_history_domain_sort_compare(GtkTreeModel *model, GtkTreeIter *a,
- GtkTreeIter *b, gint sort_column)
+MENUHANDLER(clear_selection)
{
- gint comparable_a;
- gint comparable_b;
-
- gtk_tree_model_get(model, a, sort_column, &comparable_a, -1);
- gtk_tree_model_get(model, b, sort_column, &comparable_b, -1);
-
- /* Make sure "All" stays at the top */
- if (comparable_a < 0 || comparable_b < 0)
- return comparable_a - comparable_b;
- else
- return comparable_b - comparable_a;
+ history_global_clear_selection();
+ return TRUE;
}
-void nsgtk_history_domain_set_visible (GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gboolean has_sites)
+/* view menu*/
+MENUHANDLER(expand_all)
{
- gchar *string = gtk_tree_model_get_string_from_iter(model, iter);
-
- if (!g_str_equal(string, "0")) /* "All" */
- gtk_list_store_set(GTK_LIST_STORE(model), iter,
- DOM_HAS_SITES, has_sites, -1);
-
- g_free(string);
+ history_global_expand_all();
+ return TRUE;
}
-void nsgtk_history_search()
+MENUHANDLER(expand_directories)
{
- gtk_tree_model_foreach(GTK_TREE_MODEL(history->domain_list),
- (GtkTreeModelForeachFunc)
- nsgtk_history_domain_set_visible, FALSE);
-
- nsgtk_history_show_all();
- gtk_tree_model_filter_refilter(
- GTK_TREE_MODEL_FILTER(history->history_filter));
+ history_global_expand_directories();
+ return TRUE;
}
-void nsgtk_history_search_clear (GtkEntry *entry)
+MENUHANDLER(expand_addresses)
{
- gtk_entry_set_text(entry, "");
-}
-
-gchar *nsgtk_history_date_parse(time_t visit_time)
-{
- char *date_string = malloc(30);
- char format[30];
- time_t current_time = time(NULL);
- int current_day = localtime(&current_time)->tm_yday;
- struct tm *visit_date = localtime(&visit_time);
-
- if (visit_date->tm_yday == current_day)
- snprintf(format, 30, "%s %s %%I:%%M %%p",
- dateToday, dateAt);
- else if (current_day - visit_date->tm_yday == 1)
- snprintf(format, 30, "%s %s %%I:%%M %%p",
- dateYesterday, dateAt);
- else if (current_day - visit_date->tm_yday < 7)
- snprintf(format, 30, "%%A %s %%I:%%M %%p",
- dateAt);
- else
- snprintf(format, 30, "%%B %%d, %%Y");
-
- strftime(date_string, 30, format, visit_date);
-
- return date_string;
+ history_global_expand_addresses();
+ return TRUE;
}
-
-
-void nsgtk_history_row_activated(GtkTreeView *tv, GtkTreePath *path,
- GtkTreeViewColumn *column)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model(tv);
- if (gtk_tree_model_get_iter(model, &iter, path))
- {
- gchar *address;
- gtk_tree_model_get(model, &iter, SITE_ADDRESS, &address, -1);
-
- browser_window_create(address, NULL, NULL, true, false);
- }
+MENUHANDLER(collapse_all)
+{
+ history_global_collapse_all();
+ return TRUE;
}
-void nsgtk_history_update_info(GtkTreeSelection *treesel, gboolean domain)
+MENUHANDLER(collapse_directories)
{
- GtkTreeIter iter;
- GtkTreeModel *model;
- gboolean has_selection;
-
- has_selection = gtk_tree_selection_get_selected(treesel, &model, &iter);
-
- if (has_selection && domain) {
- gchar *b;
- gint i;
- char buf[20];
- gboolean all = g_str_equal(gtk_tree_model_get_string_from_iter(
- model, &iter), "0");
-
- /* Address */
- gtk_tree_model_get(model, &iter, DOM_DOMAIN, &b, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryAddress")),
- all ? "-" : b);
- g_free(b);
- /* Last Visit */
- gtk_tree_model_get(model, &iter, DOM_LASTVISIT, &i, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryLastVisit")),
- nsgtk_history_date_parse(i));
-
- /* Total Visits */
- gtk_tree_model_get(model, &iter, DOM_TOTALVISITS, &i, -1);
- snprintf(buf, 20, "%d", i);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryVisits")),
- buf);
- } else if (has_selection){
- GdkPixbuf *thumb;
- gchar *b;
- gint i;
- char buf[20];
- /* Address */
- gtk_tree_model_get(model, &iter, SITE_ADDRESS, &b, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryAddress")), b);
- g_free(b);
- /* Last Visit */
- gtk_tree_model_get(model, &iter, SITE_LASTVISIT, &i, -1);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryLastVisit")),
- nsgtk_history_date_parse(i));
-
- /* Total Visits */
- gtk_tree_model_get(model, &iter, SITE_TOTALVISITS, &i, -1);
- snprintf(buf, 20, "%d", i);
- gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeFile,
- "labelHistoryVisits")), buf);
-
- gtk_tree_model_get(model, &iter, SITE_THUMBNAIL, &thumb, -1);
- gtk_image_set_from_pixbuf(GTK_IMAGE(
- glade_xml_get_widget(gladeFile,
- "imageThumbnail")), thumb);
- g_object_set(G_OBJECT(glade_xml_get_widget(
- gladeFile, "imageFrame")),
- "visible", (bool)thumb, NULL);
- }
+ history_global_collapse_directories();
+ return TRUE;
}
-void nsgtk_history_scroll_top (GtkScrolledWindow *scrolled_window)
+MENUHANDLER(collapse_addresses)
{
- GtkAdjustment *adjustment =
- gtk_scrolled_window_get_vadjustment(scrolled_window);
-
- gtk_adjustment_set_value(adjustment, 0);
-
- gtk_scrolled_window_set_vadjustment(scrolled_window, adjustment);
+ history_global_collapse_addresses();
+ return TRUE;
}
-
-void global_history_add(const char *url)
-{
- const struct url_data *data;
- data = urldb_get_url_data(url);
- if (!data)
- return;
-
- nsgtk_history_add_internal(url, data);
+MENUHANDLER(launch)
+{
+ history_global_launch_selected();
+ return TRUE;
}
diff --git a/gtk/gtk_history.h b/gtk/gtk_history.h
index 02cb7f920..93d57b2b7 100644
--- a/gtk/gtk_history.h
+++ b/gtk/gtk_history.h
@@ -1,5 +1,6 @@
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -23,22 +24,7 @@
extern GtkWindow *wndHistory;
-
-struct history_model {
- GtkListStore *history_list;
- GtkTreeModel *history_filter;
- GtkTreeModel *site_filter;
- GtkTreeModel *site_sort;
- GtkTreeView *site_treeview;
- GtkTreeSelection *site_selection;
- GtkListStore *domain_list;
- GtkTreeModel *domain_filter;
- GHashTable *domain_hash;
- GtkTreeModel *domain_sort;
- GtkTreeView *domain_treeview;
- GtkTreeSelection *domain_selection;
-};
-
bool nsgtk_history_init(void);
+void nsgtk_history_destroy(void);
#endif /* __NSGTK_HISTORY_H__ */
diff --git a/gtk/gtk_hotlist.c b/gtk/gtk_hotlist.c
new file mode 100644
index 000000000..905050260
--- /dev/null
+++ b/gtk/gtk_hotlist.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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 "desktop/hotlist.h"
+#include "desktop/options.h"
+#include "desktop/plotters.h"
+#include "desktop/tree.h"
+#include "gtk/gtk_gui.h"
+#include "gtk/gtk_hotlist.h"
+#include "gtk/options.h"
+#include "gtk/gtk_plotters.h"
+#include "gtk/gtk_scaffolding.h"
+#include "gtk/gtk_treeview.h"
+#include "utils/log.h"
+
+#define GLADE_NAME "hotlist.glade"
+
+#define MENUPROTO(x) static gboolean nsgtk_on_##x##_activate( \
+ GtkMenuItem *widget, gpointer g)
+#define MENUEVENT(x) { #x, G_CALLBACK(nsgtk_on_##x##_activate) }
+#define MENUHANDLER(x) gboolean nsgtk_on_##x##_activate(GtkMenuItem *widget, \
+ gpointer g)
+
+struct menu_events {
+ const char *widget;
+ GCallback handler;
+};
+
+static void nsgtk_hotlist_init_menu(void);
+
+/* file menu*/
+MENUPROTO(export);
+MENUPROTO(new_folder);
+MENUPROTO(new_entry);
+
+/* edit menu */
+MENUPROTO(edit_selected);
+MENUPROTO(delete_selected);
+MENUPROTO(select_all);
+MENUPROTO(clear_selection);
+
+/* view menu*/
+MENUPROTO(expand_all);
+MENUPROTO(expand_directories);
+MENUPROTO(expand_addresses);
+MENUPROTO(collapse_all);
+MENUPROTO(collapse_directories);
+MENUPROTO(collapse_addresses);
+
+MENUPROTO(launch);
+
+static struct menu_events menu_events[] = {
+
+ /* file menu*/
+ MENUEVENT(export),
+ MENUEVENT(new_folder),
+ MENUEVENT(new_entry),
+
+ /* edit menu */
+ MENUEVENT(edit_selected),
+ MENUEVENT(delete_selected),
+ MENUEVENT(select_all),
+ MENUEVENT(clear_selection),
+
+ /* view menu*/
+ MENUEVENT(expand_all),
+ MENUEVENT(expand_directories),
+ MENUEVENT(expand_addresses),
+ MENUEVENT(collapse_all),
+ MENUEVENT(collapse_directories),
+ MENUEVENT(collapse_addresses),
+
+ MENUEVENT(launch),
+ {NULL, NULL}
+};
+
+static struct nsgtk_treeview *hotlist_window;
+static GladeXML *gladeFile;
+GtkWindow *wndHotlist;
+
+
+/**
+ * Creates the window for the hotlist tree.
+ */
+void nsgtk_hotlist_init()
+{
+ gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL);
+ gladeFile = glade_xml_new(glade_location, NULL, NULL);
+ g_free(glade_location);
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
+
+ glade_xml_signal_autoconnect(gladeFile);
+
+ wndHotlist = GTK_WINDOW(glade_xml_get_widget(gladeFile, "wndHotlist"));
+ window = wndHotlist;
+
+ scrolled = GTK_SCROLLED_WINDOW(glade_xml_get_widget(gladeFile,
+ "hotlistScrolled"));
+
+ drawing_area = GTK_DRAWING_AREA(glade_xml_get_widget(gladeFile,
+ "hotlistDrawingArea"));
+
+
+ hotlist_window = nsgtk_treeview_create(hotlist_get_tree_flags(), window,
+ scrolled, drawing_area);
+
+ if (hotlist_window == NULL)
+ return;
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+
+ CONNECT(window, "delete_event", gtk_widget_hide_on_delete, NULL);
+ CONNECT(window, "hide", nsgtk_tree_window_hide, hotlist_window);
+
+ hotlist_initialise(nsgtk_treeview_get_tree(hotlist_window),
+ option_hotlist_path);
+
+ nsgtk_hotlist_init_menu();
+}
+
+
+/**
+ * Connects menu events in the hotlist window.
+ */
+void nsgtk_hotlist_init_menu(void)
+{
+ struct menu_events *event = menu_events;
+
+ while (event->widget != NULL)
+ {
+ GtkWidget *w = glade_xml_get_widget(gladeFile, event->widget);
+ g_signal_connect(G_OBJECT(w), "activate", event->handler,
+ hotlist_window);
+ event++;
+ }
+}
+
+
+/**
+ * Destroys the hotlist window and performs any other necessary cleanup actions.
+ */
+void nsgtk_hotlist_destroy(void)
+{
+ /* TODO: what about gladeFile? */
+ hotlist_cleanup(option_hotlist_path);
+ nsgtk_treeview_destroy(hotlist_window);
+}
+
+
+/* file menu*/
+MENUHANDLER(export)
+{
+ GtkWidget *save_dialog;
+ save_dialog = gtk_file_chooser_dialog_new("Save File",
+ wndHotlist,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog),
+ getenv("HOME") ? getenv("HOME") : "/");
+
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog),
+ "hotlist.html");
+
+ if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) {
+ gchar *filename = gtk_file_chooser_get_filename(
+ GTK_FILE_CHOOSER(save_dialog));
+
+ hotlist_export(filename);
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(save_dialog);
+
+ return TRUE;
+}
+
+MENUHANDLER(new_folder)
+{
+ hotlist_add_folder();
+ return TRUE;
+}
+
+MENUHANDLER(new_entry)
+{
+ hotlist_add_entry();
+ return TRUE;
+}
+
+/* edit menu */
+MENUHANDLER(edit_selected)
+{
+ hotlist_edit_selected();
+ return TRUE;
+}
+
+MENUHANDLER(delete_selected)
+{
+ hotlist_delete_selected();
+ return TRUE;
+}
+
+MENUHANDLER(select_all)
+{
+ hotlist_select_all();
+ return TRUE;
+}
+
+MENUHANDLER(clear_selection)
+{
+ hotlist_clear_selection();
+ return TRUE;
+}
+
+/* view menu*/
+MENUHANDLER(expand_all)
+{
+ hotlist_expand_all();
+ return TRUE;
+}
+
+MENUHANDLER(expand_directories)
+{
+ hotlist_expand_directories();
+ return TRUE;
+}
+
+MENUHANDLER(expand_addresses)
+{
+ hotlist_expand_addresses();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_all)
+{
+ hotlist_collapse_all();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_directories)
+{
+ hotlist_collapse_directories();
+ return TRUE;
+}
+
+MENUHANDLER(collapse_addresses)
+{
+ hotlist_collapse_addresses();
+ return TRUE;
+}
+
+MENUHANDLER(launch)
+{
+ hotlist_launch_selected();
+ return TRUE;
+}
diff --git a/framebuffer/history.c b/gtk/gtk_hotlist.h
index b0cf20495..22dc0a45f 100644
--- a/framebuffer/history.c
+++ b/gtk/gtk_hotlist.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,26 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "content/urldb.h"
-#include "desktop/browser.h"
-
-void global_history_add(const char *url)
-{
- const struct url_data *data;
-
- data = urldb_get_url_data(url);
- if (!data)
- return;
+/** \file
+ * GTK hotlist (interface).
+ */
+#ifndef __NSGTK_HOTLIST_H__
+#define __NSGTK_HOTLIST_H__
-}
+#include <gtk/gtk.h>
-void global_history_add_recent(const char *url)
-{
-}
+extern GtkWindow *wndHotlist;
-char **global_history_get_recent(int *count)
-{
- return NULL;
-}
+void nsgtk_hotlist_init(void);
+void nsgtk_hotlist_destroy(void);
+#endif /* __NSGTK_HOTLIST_H__ */
diff --git a/gtk/gtk_menu.c b/gtk/gtk_menu.c
index af9d0b67c..6fb5fc313 100644
--- a/gtk/gtk_menu.c
+++ b/gtk/gtk_menu.c
@@ -397,6 +397,7 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group,
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);
@@ -407,6 +408,8 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group,
IMAGE_ITEM(nav, addbookmarks, gtkAddBookMarks, ret, group);
IMAGE_ITEM(nav, showbookmarks, gtkShowBookMarks, ret, group);
ADD_SEP(nav, ret);
+ IMAGE_ITEM(nav, showcookies, gtkShowCookies, ret, group);
+ ADD_SEP(nav, ret);
IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group);
ATTACH_PARENT(parent, gtkNavigate, ret->nav, group);
diff --git a/gtk/gtk_menu.h b/gtk/gtk_menu.h
index 2ddacd891..434eafd1b 100644
--- a/gtk/gtk_menu.h
+++ b/gtk/gtk_menu.h
@@ -78,6 +78,7 @@ struct nsgtk_nav_menu {
GtkImageMenuItem *globalhistory_menuitem;
GtkImageMenuItem *addbookmarks_menuitem;
GtkImageMenuItem *showbookmarks_menuitem;
+ GtkImageMenuItem *showcookies_menuitem;
GtkImageMenuItem *openlocation_menuitem;
};
diff --git a/gtk/gtk_plotters.c b/gtk/gtk_plotters.c
index 9598e2022..1428710ec 100644
--- a/gtk/gtk_plotters.c
+++ b/gtk/gtk_plotters.c
@@ -89,9 +89,9 @@ void nsgtk_set_colour(colour c)
g / 255.0, b / 255.0, 1.0);
}
-/** Plot a caret.
+/** Plot a caret.
*
- * @note It is assumed that the plotters have been set up.
+ * @note It is assumed that the plotters have been set up.
*/
void nsgtk_plot_caret(int x, int y, int h)
{
@@ -234,8 +234,12 @@ static bool nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *
else
cairo_set_line_width(current_cr, style->stroke_width);
- cairo_move_to(current_cr, x0 + 0.5, y0 + 0.5);
- cairo_line_to(current_cr, x1 + 0.5, y1 + 0.5);
+ /* core expects horizontal and vertical lines to be on pixels, not
+ * between pixels */
+ cairo_move_to(current_cr, (x0 == x1) ? x0 + 0.5 : x0,
+ (y0 == y1) ? y0 + 0.5 : y0);
+ cairo_line_to(current_cr, (x0 == x1) ? x1 + 0.5 : x1,
+ (y0 == y1) ? y1 + 0.5 : y1);
cairo_stroke(current_cr);
return true;
@@ -304,7 +308,7 @@ static bool nsgtk_plot_polygon(const int *p, unsigned int n, const plot_style_t
-static bool nsgtk_plot_text(int x, int y, const char *text, size_t length,
+static bool nsgtk_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
return nsfont_paint(x, y, text, length, fstyle);
diff --git a/gtk/gtk_scaffolding.c b/gtk/gtk_scaffolding.c
index b2c7c7dba..e970a60af 100644
--- a/gtk/gtk_scaffolding.c
+++ b/gtk/gtk_scaffolding.c
@@ -34,6 +34,7 @@
#include "css/utils.h"
#include "desktop/browser.h"
#include "desktop/history_core.h"
+#include "desktop/hotlist.h"
#include "desktop/gui.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
@@ -49,6 +50,8 @@
#include "desktop/searchweb.h"
#include "desktop/selection.h"
#include "desktop/textinput.h"
+#include "desktop/tree.h"
+#include "gtk/gtk_cookies.h"
#include "gtk/gtk_completion.h"
#include "gtk/dialogs/gtk_options.h"
#include "gtk/dialogs/gtk_about.h"
@@ -57,6 +60,7 @@
#include "gtk/gtk_download.h"
#include "gtk/gtk_gui.h"
#include "gtk/gtk_history.h"
+#include "gtk/gtk_hotlist.h"
#include "gtk/gtk_menu.h"
#include "gtk/gtk_plotters.h"
#include "gtk/gtk_print.h"
@@ -66,6 +70,7 @@
#include "gtk/gtk_theme.h"
#include "gtk/gtk_throbber.h"
#include "gtk/gtk_toolbar.h"
+#include "gtk/gtk_treeview.h"
#include "gtk/gtk_window.h"
#include "gtk/options.h"
#include "gtk/sexy_icon_entry.h"
@@ -217,7 +222,7 @@ void nsgtk_window_close(struct gtk_scaffolding *g)
if ((g->history_window) && (g->history_window->window)) {
gtk_widget_destroy(GTK_WIDGET(g->history_window->window));
}
-
+
if (--open_windows == 0)
netsurf_quit = true;
@@ -1263,17 +1268,34 @@ MULTIHANDLER(globalhistory)
{
gtk_widget_show(GTK_WIDGET(wndHistory));
gdk_window_raise(GTK_WIDGET(wndHistory)->window);
-
+
return TRUE;
}
MULTIHANDLER(addbookmarks)
{
+ struct browser_window *bw = gui_window_get_browser_window(g->top_level);
+
+ if (bw == NULL || bw->current_content == NULL ||
+ content_get_url(bw->current_content) == NULL)
+ return TRUE;
+ hotlist_add_page(content_get_url(bw->current_content));
return TRUE;
}
MULTIHANDLER(showbookmarks)
{
+ gtk_widget_show(GTK_WIDGET(wndHotlist));
+ gdk_window_raise(GTK_WIDGET(wndHotlist)->window);
+
+ return TRUE;
+}
+
+MULTIHANDLER(showcookies)
+{
+ gtk_widget_show(GTK_WIDGET(wndCookies));
+ gdk_window_raise(GTK_WIDGET(wndCookies)->window);
+
return TRUE;
}
@@ -1394,6 +1416,7 @@ gboolean nsgtk_history_button_press_event(GtkWidget *widget,
return TRUE;
}
+
#define GET_WIDGET(x) glade_xml_get_widget(g->xml, (x))
nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
@@ -1582,6 +1605,7 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
gtk_scrolled_window_add_with_viewport(g->history_window->scrolled,
GTK_WIDGET(g->history_window->drawing_area));
gtk_widget_show(GTK_WIDGET(g->history_window->drawing_area));
+
/* set up URL bar completion */
g->url_bar_completion = gtk_entry_completion_new();
@@ -1613,7 +1637,7 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
nsgtk_history_button_press_event, g->history_window);
CONNECT(g->history_window->window, "delete_event",
gtk_widget_hide_on_delete, NULL);
-
+
g_signal_connect_after(g->notebook, "page-added",
G_CALLBACK(nsgtk_window_tabs_num_changed), g);
g_signal_connect_after(g->notebook, "page-removed",
@@ -2408,6 +2432,7 @@ void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g)
ITEM_MAIN(GLOBALHISTORY, nav, globalhistory);
ITEM_MAIN(ADDBOOKMARKS, nav, addbookmarks);
ITEM_MAIN(SHOWBOOKMARKS, nav, showbookmarks);
+ ITEM_MAIN(SHOWCOOKIES, nav, showcookies);
ITEM_MAIN(OPENLOCATION, nav, openlocation);
ITEM_MAIN(CONTENTS, help, contents);
ITEM_MAIN(INFO, help, info);
@@ -2437,8 +2462,6 @@ void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g)
SENSITIVITY(CONTENTS);
SENSITIVITY(DRAWFILE);
SENSITIVITY(POSTSCRIPT);
- SENSITIVITY(ADDBOOKMARKS);
- SENSITIVITY(SHOWBOOKMARKS);
SENSITIVITY(NEXTTAB);
SENSITIVITY(PREVTAB);
SENSITIVITY(CLOSETAB);
diff --git a/gtk/gtk_scaffolding.h b/gtk/gtk_scaffolding.h
index ddc9fb232..1db576ac1 100644
--- a/gtk/gtk_scaffolding.h
+++ b/gtk/gtk_scaffolding.h
@@ -73,6 +73,7 @@ typedef enum {
GLOBALHISTORY_BUTTON,
ADDBOOKMARKS_BUTTON,
SHOWBOOKMARKS_BUTTON,
+ SHOWCOOKIES_BUTTON,
OPENLOCATION_BUTTON,
NEXTTAB_BUTTON,
PREVTAB_BUTTON,
@@ -209,6 +210,7 @@ MULTIPROTO(localhistory);
MULTIPROTO(globalhistory);
MULTIPROTO(addbookmarks);
MULTIPROTO(showbookmarks);
+MULTIPROTO(showcookies);
MULTIPROTO(openlocation);
/* tabs menu */
diff --git a/gtk/gtk_theme.c b/gtk/gtk_theme.c
index 05421c3d3..98fc03410 100644
--- a/gtk/gtk_theme.c
+++ b/gtk/gtk_theme.c
@@ -447,6 +447,7 @@ struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s)
SET_BUTTON_IMAGE(cachetheme, GLOBALHISTORY, theme)
SET_BUTTON_IMAGE(cachetheme, ADDBOOKMARKS, theme)
SET_BUTTON_IMAGE(cachetheme, SHOWBOOKMARKS, theme)
+ SET_BUTTON_IMAGE(cachetheme, SHOWCOOKIES, theme)
SET_BUTTON_IMAGE(cachetheme, OPENLOCATION, theme)
SET_BUTTON_IMAGE(cachetheme, NEXTTAB, theme)
SET_BUTTON_IMAGE(cachetheme, PREVTAB, theme)
@@ -571,6 +572,7 @@ void nsgtk_theme_prepare(void)
CACHE_IMAGE(GLOBALHISTORY, globalhistory, path);
CACHE_IMAGE(ADDBOOKMARKS, addbookmarks, path);
CACHE_IMAGE(SHOWBOOKMARKS, showbookmarks, path);
+ CACHE_IMAGE(SHOWCOOKIES, showcookies, path);
CACHE_IMAGE(OPENLOCATION, openlocation, path);
CACHE_IMAGE(NEXTTAB, nexttab, path);
CACHE_IMAGE(PREVTAB, prevtab, path);
diff --git a/gtk/gtk_toolbar.c b/gtk/gtk_toolbar.c
index 92bb21f93..ab463a103 100644
--- a/gtk/gtk_toolbar.c
+++ b/gtk/gtk_toolbar.c
@@ -822,6 +822,7 @@ GtkWidget *nsgtk_toolbar_make_widget(nsgtk_scaffolding *g,
MAKE_MENUBUTTON(GLOBALHISTORY, gtkGlobalHistory)
MAKE_MENUBUTTON(ADDBOOKMARKS, gtkAddBookMarks)
MAKE_MENUBUTTON(SHOWBOOKMARKS, gtkShowBookMarks)
+ MAKE_MENUBUTTON(SHOWCOOKIES, gtkShowCookies)
MAKE_MENUBUTTON(OPENLOCATION, gtkOpenLocation)
MAKE_MENUBUTTON(NEXTTAB, gtkNextTab)
MAKE_MENUBUTTON(PREVTAB, gtkPrevTab)
@@ -986,6 +987,7 @@ DATAHANDLER(localhistory, LOCALHISTORY, window)
DATAHANDLER(globalhistory, GLOBALHISTORY, window)
DATAHANDLER(addbookmarks, ADDBOOKMARKS, window)
DATAHANDLER(showbookmarks, SHOWBOOKMARKS, window)
+DATAHANDLER(showcookies, SHOWCOOKIES, window)
DATAHANDLER(openlocation, OPENLOCATION, window)
DATAHANDLER(nexttab, NEXTTAB, window)
DATAHANDLER(prevtab, PREVTAB, window)
diff --git a/gtk/gtk_toolbar.h b/gtk/gtk_toolbar.h
index a470a4480..7d483578b 100644
--- a/gtk/gtk_toolbar.h
+++ b/gtk/gtk_toolbar.h
@@ -74,6 +74,7 @@ TOOLPROTO(localhistory);
TOOLPROTO(globalhistory);
TOOLPROTO(addbookmarks);
TOOLPROTO(showbookmarks);
+TOOLPROTO(showcookies);
TOOLPROTO(openlocation);
TOOLPROTO(nexttab);
TOOLPROTO(prevtab);
diff --git a/gtk/gtk_treeview.c b/gtk/gtk_treeview.c
index 6e5643009..20562e3d5 100644
--- a/gtk/gtk_treeview.c
+++ b/gtk/gtk_treeview.c
@@ -1,5 +1,6 @@
/*
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -20,108 +21,522 @@
* Generic tree handling (implementation).
*/
+#include <assert.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
+#include "desktop/plotters.h"
+#include "gtk/gtk_gui.h"
+#include "gtk/gtk_plotters.h"
+#include "gtk/gtk_treeview.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+struct nsgtk_treeview {
+ GtkWindow *window;
+ GtkScrolledWindow *scrolled;
+ GtkDrawingArea *drawing_area;
+ int mouse_pressed_x;
+ int mouse_pressed_y;
+ browser_mouse_state mouse_state;
+ struct tree *tree;
+};
-/**
- * Sets the origin variables to the correct values for a specified tree
- *
- * \param tree the tree to set the origin for
- */
-void tree_initialise_redraw(struct tree *tree) {
-}
+const char tree_directory_icon_name[] = "directory.png";
+const char tree_content_icon_name[] = "content.png";
+static void nsgtk_tree_redraw_request(int x, int y, int width, int height,
+ void *data);
+static void nsgtk_tree_resized(struct tree *tree, int width, int height, void *data);
+static void nsgtk_tree_scroll_visible(int y, int height, void *data);
+static void nsgtk_tree_get_window_dimensions(int *width, int *height, void *data);
-/**
- * Informs the current window manager that an area requires updating.
- *
- * \param tree the tree that is requesting a redraw
- * \param x the x co-ordinate of the redraw area
- * \param y the y co-ordinate of the redraw area
- * \param width the width of the redraw area
- * \param height the height of the redraw area
- */
-void tree_redraw_area(struct tree *tree, int x, int y, int width, int height) {
-}
+static const struct treeview_table nsgtk_tree_callbacks = {
+ .redraw_request = nsgtk_tree_redraw_request,
+ .resized = nsgtk_tree_resized,
+ .scroll_visible = nsgtk_tree_scroll_visible,
+ .get_window_dimensions = nsgtk_tree_get_window_dimensions
+};
+struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags,
+ GtkWindow *window, GtkScrolledWindow *scrolled,
+ GtkDrawingArea *drawing_area)
+{
+ struct nsgtk_treeview *tv;
+
+ tv = malloc(sizeof(struct nsgtk_treeview));
+ if (tv == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NULL;
+ }
+
+ tv->window = window;
+ tv->scrolled = scrolled;
+ tv->drawing_area = drawing_area;
+ tv->tree = tree_create(flags, &nsgtk_tree_callbacks, tv);
+ tv->mouse_state = 0;
+
+ gtk_widget_modify_bg(GTK_WIDGET(drawing_area), GTK_STATE_NORMAL,
+ &((GdkColor) { 0, 0xffff, 0xffff, 0xffff } ));
+
+#define CONNECT(obj, sig, callback, ptr) \
+ g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
+
+ CONNECT(drawing_area, "expose_event",
+ nsgtk_tree_window_expose_event,
+ tv->tree);
+ CONNECT(drawing_area, "button_press_event",
+ nsgtk_tree_window_button_press_event,
+ tv);
+ CONNECT(drawing_area, "button_release_event",
+ nsgtk_tree_window_button_release_event,
+ tv);
+ CONNECT(drawing_area, "motion_notify_event",
+ nsgtk_tree_window_motion_notify_event,
+ tv);
+ CONNECT(drawing_area, "key_press_event",
+ nsgtk_tree_window_keypress_event,
+ tv);
+ return tv;
+}
-/**
- * Draws a line.
- *
- * \param x the x co-ordinate
- * \param x the y co-ordinate
- * \param x the width of the line
- * \param x the height of the line
- */
-void tree_draw_line(int x, int y, int width, int height) {
+void nsgtk_treeview_destroy(struct nsgtk_treeview *tv)
+{
+ tree_delete(tv->tree);
+ gtk_widget_destroy(GTK_WIDGET(tv->window));
+ free(tv);
}
+struct tree *nsgtk_treeview_get_tree(struct nsgtk_treeview *tv)
+{
+ return tv->tree;
+}
-/**
- * Draws an element, including any expansion icons
- *
- * \param tree the tree to draw an element for
- * \param element the element to draw
- */
-void tree_draw_node_element(struct tree *tree, struct node_element *element) {
+void nsgtk_tree_redraw_request(int x, int y, int width, int height, void *data)
+{
+ struct nsgtk_treeview *tw = data;
+
+ gtk_widget_queue_draw_area(GTK_WIDGET(tw->drawing_area),
+ x, y, width, height);
}
/**
- * Draws an elements expansion icon
+ * Updates the tree owner following a tree resize
*
- * \param tree the tree to draw the expansion for
- * \param element the element to draw the expansion for
+ * \param tree the tree to update the owner of
*/
-void tree_draw_node_expansion(struct tree *tree, struct node *node) {
+void nsgtk_tree_resized(struct tree *tree, int width, int height, void *data)
+{
+ struct nsgtk_treeview *tw = data;
+
+ gtk_widget_set_size_request(GTK_WIDGET(tw->drawing_area),
+ width, height);
+ return;
}
-
/**
- * Recalculates the dimensions of a node element.
+ * Translates a content_type to the name of a respective icon
*
- * \param element the element to recalculate
+ * \param content_type content type
+ * \param buffer buffer for the icon name
*/
-void tree_recalculate_node_element(struct node_element *element) {
+void tree_icon_name_from_content_type(char *buffer, content_type type)
+{
+ // TODO: design/acquire icons
+ switch (type) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ case CONTENT_CSS:
+#if defined(WITH_MNG) || defined(WITH_PNG)
+ case CONTENT_PNG:
+#endif
+#ifdef WITH_MNG
+ case CONTENT_JNG:
+ case CONTENT_MNG:
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+#endif
+#ifdef WITH_BMP
+ case CONTENT_BMP:
+ case CONTENT_ICO:
+#endif
+#ifdef WITH_SPRITE
+ case CONTENT_SPRITE:
+#endif
+#ifdef WITH_DRAW
+ case CONTENT_DRAW:
+#endif
+#ifdef WITH_ARTWORKS
+ case CONTENT_ARTWORKS:
+#endif
+#ifdef WITH_NS_SVG
+ case CONTENT_SVG:
+#endif
+ default:
+ sprintf(buffer, tree_content_icon_name);
+ break;
+ }
}
/**
- * Sets a node element as having a specific sprite.
+ * Scrolls the tree to make an element visible
*
- * \param node the node to update
- * \param sprite the sprite to use
- * \param selected the expanded sprite name to use
+ * \param y Y coordinate of the element
+ * \param height height of the element
+ * \param data user data assigned to the tree on tree creation
*/
-void tree_set_node_sprite(struct node *node, const char *sprite,
- const char *expanded) {
+void nsgtk_tree_scroll_visible(int y, int height, void *data)
+{
+ int y0, y1;
+ gdouble page;
+ struct nsgtk_treeview *tw = data;
+ GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(tw->scrolled);
+ assert(vadj);
+
+ g_object_get(vadj, "page-size", &page, NULL);
+
+ y0 = (int)(gtk_adjustment_get_value(vadj));
+ y1 = y0 + page;
+
+ if ((y >= y0) && (y + height <= y1))
+ return;
+ if (y + height > y1)
+ y0 = y0 + (y + height - y1);
+ if (y < y0)
+ y0 = y;
+ gtk_adjustment_set_value(vadj, y0);
}
+
/**
- * Sets a node element as having a folder sprite
+ * Retrieves the dimensions of the window with the tree
*
- * \param node the node to update
+ * \param data user data assigned to the tree on tree creation
+ * \param width will be updated to window width if not NULL
+ * \param height will be updated to window height if not NULL
*/
-void tree_set_node_sprite_folder(struct node *node) {
+void nsgtk_tree_get_window_dimensions(int *width, int *height, void *data)
+{
+ struct nsgtk_treeview *tw = data;
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
+ gdouble page;
+
+ if (width != NULL) {
+ hadj = gtk_scrolled_window_get_hadjustment(tw->scrolled);
+ g_object_get(hadj, "page-size", &page, NULL);
+ *width = page;
+ }
+
+ if (height != NULL) {
+ vadj = gtk_scrolled_window_get_vadjustment(tw->scrolled);
+ g_object_get(vadj, "page-size", &page, NULL);
+ *height = page;
+ }
+}
+/* signal handler functions for a tree window */
+gboolean nsgtk_tree_window_expose_event(GtkWidget *widget,
+ GdkEventExpose *event, gpointer g)
+{
+ struct tree *tree = (struct tree *) g;
+ int x, y, width, height;
+
+ x = event->area.x;
+ y = event->area.y;
+ width = event->area.width;
+ height = event->area.height;
+
+ current_widget = widget;
+ current_drawable = widget->window;
+ current_gc = gdk_gc_new(current_drawable);
+#ifdef CAIRO_VERSION
+ current_cr = gdk_cairo_create(current_drawable);
+#endif
+ plot = nsgtk_plotters;
+ nsgtk_plot_set_scale(1.0);current_widget = widget;
+ current_drawable = widget->window;
+ current_gc = gdk_gc_new(current_drawable);
+#ifdef CAIRO_VERSION
+ current_cr = gdk_cairo_create(current_drawable);
+#endif
+ plot = nsgtk_plotters;
+ nsgtk_plot_set_scale(1.0);
+
+ tree_set_redraw(tree, true);
+ tree_draw(tree, 0, 0, x, y, width, height);
+
+ current_widget = NULL;
+ g_object_unref(current_gc);
+#ifdef CAIRO_VERSION
+ cairo_destroy(current_cr);
+#endif
+
+ return FALSE;
}
-/**
- * Updates the node details for a URL node.
- * The internal node dimensions are not updated.
- *
- * \param node the node to update
- */
-void tree_update_URL_node(struct node *node, const char *url,
- const struct url_data *data) {
+void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g)
+{
+ struct nsgtk_treeview *tw = g;
+ struct tree *tree = tw->tree;
+
+ if (tree != NULL)
+ tree_set_redraw(tree, false);
}
+gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g)
+{
+ struct nsgtk_treeview *tw = g;
+ struct tree *tree = tw->tree;
+
+ gtk_widget_grab_focus(GTK_WIDGET(tw->drawing_area));
+
+
+ tw->mouse_pressed_x = event->x;
+ tw->mouse_pressed_y = event->y;
-/**
- * Updates the tree owner following a tree resize
- *
- * \param tree the tree to update the owner of
- */
-void tree_resized(struct tree *tree) {
+ if (event->type == GDK_2BUTTON_PRESS)
+ tw->mouse_state = BROWSER_MOUSE_DOUBLE_CLICK;
+
+ switch (event->button) {
+ case 1: tw->mouse_state |= BROWSER_MOUSE_PRESS_1; break;
+ case 3: tw->mouse_state |= BROWSER_MOUSE_PRESS_2; break;
+ }
+ /* Handle the modifiers too */
+ if (event->state & GDK_SHIFT_MASK)
+ tw->mouse_state |= BROWSER_MOUSE_MOD_1;
+ if (event->state & GDK_CONTROL_MASK)
+ tw->mouse_state |= BROWSER_MOUSE_MOD_2;
+ if (event->state & GDK_MOD1_MASK)
+ tw->mouse_state |= BROWSER_MOUSE_MOD_3;
+
+ tree_mouse_action(tree, tw->mouse_state, event->x, event->y);
+
+ return TRUE;
}
+
+gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g)
+{
+ bool shift = event->state & GDK_SHIFT_MASK;
+ bool ctrl = event->state & GDK_CONTROL_MASK;
+ bool alt = event->state & GDK_MOD1_MASK;
+ struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g;
+ struct tree *tree = tw->tree;
+
+ /* We consider only button 1 clicks as double clicks.
+ * If the mouse state is PRESS then we are waiting for a release to emit
+ * a click event, otherwise just reset the state to nothing*/
+ if (tw->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) {
+
+ if (tw->mouse_state & BROWSER_MOUSE_PRESS_1)
+ tw->mouse_state ^= BROWSER_MOUSE_PRESS_1;
+ else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2)
+ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_DOUBLE_CLICK);
+
+ } else if (tw->mouse_state & BROWSER_MOUSE_PRESS_1)
+ tw->mouse_state ^=
+ (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1);
+ else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2)
+ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_2);
+
+ /* Handle modifiers being removed */
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_1;
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_2;
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_3;
+
+
+ if (tw->mouse_state &
+ (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2
+ | BROWSER_MOUSE_DOUBLE_CLICK))
+ tree_mouse_action(tree, tw->mouse_state,
+ event->x, event->y);
+ else
+ tree_drag_end(tree, tw->mouse_state,
+ tw->mouse_pressed_x,
+ tw->mouse_pressed_y,
+ event->x, event->y);
+
+
+ tw->mouse_state = 0;
+
+
+ return TRUE;
+}
+
+gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g)
+{
+ bool shift = event->state & GDK_SHIFT_MASK;
+ bool ctrl = event->state & GDK_CONTROL_MASK;
+ bool alt = event->state & GDK_MOD1_MASK;
+ struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g;
+ struct tree *tree = tw->tree;
+
+
+ /* Handle modifiers being removed */
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_1;
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_2;
+ if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt)
+ tw->mouse_state ^= BROWSER_MOUSE_MOD_3;
+
+ if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) {
+ /* Start button 1 drag */
+ tree_mouse_action(tree, BROWSER_MOUSE_DRAG_1,
+ tw->mouse_pressed_x, tw->mouse_pressed_y);
+ /* Replace PRESS with HOLDING and declare drag in progress */
+ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_1 |
+ BROWSER_MOUSE_HOLDING_1);
+ tw->mouse_state |= BROWSER_MOUSE_DRAG_ON;
+ return TRUE;
+ }
+ else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2){
+ /* Start button 2s drag */
+ tree_mouse_action(tree, BROWSER_MOUSE_DRAG_2,
+ tw->mouse_pressed_x, tw->mouse_pressed_y);
+ /* Replace PRESS with HOLDING and declare drag in progress */
+ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_HOLDING_2);
+ tw->mouse_state |= BROWSER_MOUSE_DRAG_ON;
+ return TRUE;
+ }
+
+ if (tw->mouse_state & (BROWSER_MOUSE_HOLDING_1 |
+ BROWSER_MOUSE_HOLDING_2))
+ tree_mouse_action(tree, tw->mouse_state, event->x,
+ event->y);
+
+ return TRUE;
+}
+
+
+gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
+ gpointer g)
+{
+ struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g;
+ struct tree *tree = tw->tree;
+ uint32_t nskey;
+ double value;
+ GtkAdjustment *vscroll;
+ GtkAdjustment *hscroll;
+ GtkAdjustment *scroll = NULL;
+ gdouble hpage, vpage;
+ bool edited;
+
+ nskey = gtk_gui_gdkkey_to_nskey(event);
+
+
+ vscroll = gtk_scrolled_window_get_vadjustment(tw->scrolled);
+ hscroll = gtk_scrolled_window_get_hadjustment(tw->scrolled);
+ g_object_get(vscroll, "page-size", &vpage, NULL);
+ g_object_get(hscroll, "page-size", &hpage, NULL);
+
+
+ edited = tree_is_edited(tree);
+
+ switch (event->keyval) {
+ case GDK_Home:
+ case GDK_KP_Home:
+ if (edited)
+ break;
+ scroll = vscroll;
+ value = scroll->lower;
+ break;
+
+ case GDK_End:
+ case GDK_KP_End:
+ if (edited)
+ break;
+ scroll = vscroll;
+ value = scroll->upper - vpage;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Left:
+ case GDK_KP_Left:
+ if (edited)
+ break;
+ scroll = hscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->step_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Up:
+ case GDK_KP_Up:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->step_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Right:
+ case GDK_KP_Right:
+ if (edited)
+ break;
+ scroll = hscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->step_increment;
+ if (value > scroll->upper - hpage)
+ value = scroll->upper - hpage;
+ break;
+
+ case GDK_Down:
+ case GDK_KP_Down:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->step_increment;
+ if (value > scroll->upper - vpage)
+ value = scroll->upper - vpage;
+ break;
+
+ case GDK_Page_Up:
+ case GDK_KP_Page_Up:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) -
+ scroll->page_increment;
+ if (value < scroll->lower)
+ value = scroll->lower;
+ break;
+
+ case GDK_Page_Down:
+ case GDK_KP_Page_Down:
+ scroll = vscroll;
+ value = gtk_adjustment_get_value(scroll) +
+ scroll->page_increment;
+ if (value > scroll->upper - vpage)
+ value = scroll->upper - vpage;
+ break;
+ default:
+ tree_keypress(tree, nskey);
+ return TRUE;
+ }
+
+ if (scroll != NULL)
+ gtk_adjustment_set_value(scroll, value);
+
+ tree_keypress(tree, nskey);
+
+ return TRUE;
+}
diff --git a/gtk/gtk_treeview.h b/gtk/gtk_treeview.h
new file mode 100644
index 000000000..655f8223d
--- /dev/null
+++ b/gtk/gtk_treeview.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.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
+ * Generic tree handling.
+ */
+
+#ifndef __NSGTK_TREEVIEW_H__
+#define __NSGTK_TREEVIEW_H__
+
+#include "desktop/browser.h"
+
+struct nsgtk_treeview;
+
+struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags,
+ GtkWindow *window, GtkScrolledWindow *scrolled,
+ GtkDrawingArea *drawing_area);
+void nsgtk_treeview_destroy(struct nsgtk_treeview *tv);
+
+struct tree *nsgtk_treeview_get_tree(struct nsgtk_treeview *tv);
+
+gboolean nsgtk_tree_window_expose_event(GtkWidget *, GdkEventExpose *,
+ gpointer g);
+void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g);
+gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g);
+gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g);
+gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
+ GdkEventButton *event, gpointer g);
+gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
+ gpointer g);
+
+#endif /*__NSGTK_TREEVIEW_H__*/
diff --git a/gtk/gtk_window.c b/gtk/gtk_window.c
index 509976519..68e636b82 100644
--- a/gtk/gtk_window.c
+++ b/gtk/gtk_window.c
@@ -606,7 +606,7 @@ gboolean nsgtk_window_scroll_event(GtkWidget *widget,
}
gboolean nsgtk_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
- gpointer data)
+ gpointer data)
{
struct gui_window *g = data;
uint32_t nskey = gtk_gui_gdkkey_to_nskey(event);
diff --git a/gtk/options.h b/gtk/options.h
index cb6f0bde2..ac14259d8 100644
--- a/gtk/options.h
+++ b/gtk/options.h
@@ -34,6 +34,7 @@ extern int option_history_age;
extern bool option_hover_urls;
extern bool option_focus_new;
extern bool option_new_blank;
+extern char *option_hotlist_path;
extern bool option_source_tab;
extern int option_current_theme;
@@ -51,6 +52,7 @@ int option_history_age = 0; \
bool option_hover_urls = false; \
bool option_focus_new = false; \
bool option_new_blank = false; \
+char *option_hotlist_path = NULL; \
bool option_source_tab = false;\
int option_current_theme = 0;
@@ -68,6 +70,7 @@ int option_current_theme = 0;
{ "hover_urls", OPTION_BOOL, &option_hover_urls}, \
{ "focus_new", OPTION_BOOL, &option_focus_new}, \
{ "new_blank", OPTION_BOOL, &option_new_blank}, \
+{ "hotlist_path", OPTION_STRING, &option_hotlist_path}, \
{ "source_tab", OPTION_BOOL, &option_source_tab},\
{ "current_theme", OPTION_INTEGER, &option_current_theme}
diff --git a/gtk/res/cookies.glade b/gtk/res/cookies.glade
new file mode 100644
index 000000000..2bb92f372
--- /dev/null
+++ b/gtk/res/cookies.glade
@@ -0,0 +1,174 @@
+<?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 Jul 28 17:12:17 2009 -->
+<glade-interface>
+ <widget class="GtkWindow" id="wndCookies">
+ <property name="title" translatable="yes">NetSurf Cookies</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</property>
+ <property name="default_width">600</property>
+ <property name="default_height">500</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property>
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="border_width">2</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu2">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="delete_selected">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Deletes selected nodes</property>
+ <property name="label" translatable="yes">_Delete</property>
+ <property name="use_underline">True</property>
+ <accelerator key="Delete" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="delete_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">D_elete all</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="select_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Select all</property>
+ <property name="use_underline">True</property>
+ <accelerator key="A" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="clear_selection">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Clear selection</property>
+ <property name="use_underline">True</property>
+ <accelerator key="U" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu4">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="expand">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Expand</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu5">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="expand_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_domains">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Domains</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_cookies">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Cookies</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Collapse</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu6">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_domains">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Domains</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_cookies">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Cookies</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkScrolledWindow" id="cookiesScrolled">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <child>
+ <widget class="GtkViewport" id="cookiesViewport">
+ <property name="visible">True</property>
+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
+ <child>
+ <widget class="GtkDrawingArea" id="cookiesDrawingArea">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
diff --git a/gtk/res/history.glade b/gtk/res/history.glade
index e44edecd5..5c6e06424 100644
--- a/gtk/res/history.glade
+++ b/gtk/res/history.glade
@@ -8,306 +8,190 @@
<property name="default_width">600</property>
<property name="default_height">500</property>
<property name="type_hint">utility</property>
- <signal name="delete_event" handler="gtk_widget_hide"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="border_width">2</property>
<property name="spacing">2</property>
<child>
- <widget class="GtkHPaned" id="hpaned2">
+ <widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="position">234</property>
<child>
- <widget class="GtkVBox" id="vbox28">
+ <widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
- <property name="spacing">2</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
<child>
- <widget class="GtkHBox" id="hbox2">
+ <widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <widget class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Sort by</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">1</property>
- <property name="position">0</property>
- </packing>
- </child>
<child>
- <widget class="GtkComboBox" id="comboSort">
+ <widget class="GtkMenuItem" id="export">
<property name="visible">True</property>
- <property name="items" translatable="yes">Name
-Last Visited
-Number of Visits</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkScrolledWindow" id="windowDomain">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">1</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <widget class="GtkTreeView" id="treeDomain">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="rules_hint">True</property>
+ <property name="label" translatable="yes">_Export</property>
+ <property name="use_underline">True</property>
+ <accelerator key="E" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget>
</child>
</widget>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
</widget>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
</child>
<child>
- <widget class="GtkVBox" id="vbox2">
+ <widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
- <property name="spacing">2</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
<child>
- <widget class="GtkHBox" id="hbox1">
+ <widget class="GtkMenu" id="menu2">
<property name="visible">True</property>
<child>
- <widget class="GtkLabel" id="label2">
+ <widget class="GtkMenuItem" id="delete_selected">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;_Search for&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="tooltip" translatable="yes">Deletes selected nodes</property>
+ <property name="label" translatable="yes">_Delete</property>
<property name="use_underline">True</property>
+ <accelerator key="Delete" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">1</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
- <widget class="GtkEntry" id="entrySearch">
+ <widget class="GtkMenuItem" id="delete_all">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">out</property>
+ <property name="label" translatable="yes">D_elete all</property>
+ <property name="use_underline">True</property>
</widget>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
<child>
- <widget class="GtkButton" id="buttonClearSearch">
+ <widget class="GtkMenuItem" id="select_all">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">True</property>
- <property name="relief">none</property>
- <property name="focus_on_click">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Clear the search entry</property>
- <property name="stock">gtk-clear</property>
- <property name="icon-size">1</property>
- </widget>
- </child>
+ <property name="label" translatable="yes">_Select all</property>
+ <property name="use_underline">True</property>
+ <accelerator key="A" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="clear_selection">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Clear selection</property>
+ <property name="use_underline">True</property>
+ <accelerator key="U" modifiers="GDK_MOD1_MASK" signal="activate"/>
</widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
</child>
</widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
</child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
<child>
- <widget class="GtkScrolledWindow" id="windowSites">
+ <widget class="GtkMenu" id="menu4">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">1</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
<child>
- <widget class="GtkTreeView" id="treeHistory">
+ <widget class="GtkMenuItem" id="expand">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="rules_hint">True</property>
- <property name="show_expanders">False</property>
+ <property name="label" translatable="yes">_Expand</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu5">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="expand_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_directories">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Directories</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_addresses">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add_resses</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Collapse</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu6">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_directories">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Directories</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_addresses">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add_resses</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
</widget>
</child>
</widget>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
</widget>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="launch">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Launches the selected addresses</property>
+ <property name="label" translatable="yes">_Launch</property>
+ <property name="use_underline">True</property>
+ </widget>
</child>
</widget>
<packing>
- <property name="position">0</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
- <widget class="GtkHBox" id="hbox3">
+ <widget class="GtkScrolledWindow" id="globalHistoryScrolled">
<property name="visible">True</property>
- <property name="spacing">5</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
- <widget class="GtkTable" id="table1">
+ <widget class="GtkViewport" id="globalHistoryViewport">
<property name="visible">True</property>
- <property name="border_width">1</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <child>
- <widget class="GtkLabel" id="labelHistoryAddress">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">http://netsurf.sf.net/</property>
- <property name="ellipsize">middle</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="GtkLabel" id="labelHistoryLastVisit">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Fri Aug 09, 2006</property>
- <property name="ellipsize">end</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="labelHistoryVisits">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">2</property>
- <property name="ellipsize">end</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>
+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
<child>
- <widget class="GtkLabel" id="label119">
+ <widget class="GtkDrawingArea" id="globalHistoryDrawingArea">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Number of visits</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_EXPAND</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label118">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Last visited</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_EXPAND</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label117">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Address</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_EXPAND</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkFrame" id="imageFrame">
- <property name="label_xalign">1</property>
- <property name="label_yalign">1</property>
- <property name="shadow_type">in</property>
- <child>
- <widget class="GtkImage" id="imageThumbnail">
- <property name="width_request">100</property>
- <property name="height_request">86</property>
- <property name="visible">True</property>
- <property name="stock">gtk-file</property>
- <property name="icon-size">6</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</widget>
</child>
- <child>
- <placeholder/>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
</widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">1</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>
</widget>
</child>
diff --git a/gtk/res/hotlist.glade b/gtk/res/hotlist.glade
new file mode 100644
index 000000000..5a3b8f1d0
--- /dev/null
+++ b/gtk/res/hotlist.glade
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Wed Jul 29 03:02:21 2009 -->
+<glade-interface>
+ <widget class="GtkWindow" id="wndHotlist">
+ <property name="title" translatable="yes">NetSurf Hotlist</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</property>
+ <property name="default_width">600</property>
+ <property name="default_height">500</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property>
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="border_width">2</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="export">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Export</property>
+ <property name="use_underline">True</property>
+ <accelerator key="E" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="new_folder">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">New _folder</property>
+ <property name="use_underline">True</property>
+ <accelerator key="M" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="new_entry">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">New _entry</property>
+ <property name="use_underline">True</property>
+ <accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu2">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="edit_selected">
+ <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="delete_selected">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Deletes selected nodes</property>
+ <property name="label" translatable="yes">_Delete</property>
+ <property name="use_underline">True</property>
+ <accelerator key="Delete" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="select_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Select all</property>
+ <property name="use_underline">True</property>
+ <accelerator key="A" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="clear_selection">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Clear selection</property>
+ <property name="use_underline">True</property>
+ <accelerator key="U" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu4">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="expand">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Expand</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu5">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="expand_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_directories">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Directories</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="expand_addresses">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add_resses</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Collapse</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menu6">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_all">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_All</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_directories">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Directories</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="collapse_addresses">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add_resses</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="launch">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Launches the selected addresses</property>
+ <property name="label" translatable="yes">_Launch</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkScrolledWindow" id="hotlistScrolled">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <child>
+ <widget class="GtkViewport" id="hotlistViewport">
+ <property name="visible">True</property>
+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
+ <child>
+ <widget class="GtkDrawingArea" id="hotlistDrawingArea">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
diff --git a/gtk/res/icons b/gtk/res/icons
new file mode 120000
index 000000000..509ccd1d2
--- /dev/null
+++ b/gtk/res/icons
@@ -0,0 +1 @@
+../../!NetSurf/Resources/Icons/ \ No newline at end of file
diff --git a/gtk/res/ssl.glade b/gtk/res/ssl.glade
index 98d9f9bf3..5d0570987 100644
--- a/gtk/res/ssl.glade
+++ b/gtk/res/ssl.glade
@@ -6,6 +6,8 @@
<property name="border_width">1</property>
<property name="title" translatable="yes">SSL certificate problem</property>
<property name="modal">True</property>
+ <property name="default_width">500</property>
+ <property name="default_height">250</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox3">
@@ -50,17 +52,22 @@
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <widget class="GtkScrolledWindow" id="SSLScrolled">
<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>
+ <widget class="GtkViewport" id="SSLViewport">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="text" translatable="yes">(not implemented)</property>
+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
+ <child>
+ <widget class="GtkDrawingArea" id="SSLDrawingArea">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
+ </widget>
+ </child>
</widget>
</child>
</widget>
diff --git a/riscos/configure/con_home.c b/riscos/configure/con_home.c
index afced9557..fbe1b7039 100644
--- a/riscos/configure/con_home.c
+++ b/riscos/configure/con_home.c
@@ -22,6 +22,7 @@
#include "riscos/gui.h"
#include "riscos/menus.h"
#include "riscos/options.h"
+#include "riscos/url_suggest.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/configure.h"
@@ -42,16 +43,13 @@ static bool ro_gui_options_home_ok(wimp_w w);
bool ro_gui_options_home_initialise(wimp_w w)
{
- int suggestions;
-
/* set the current values */
ro_gui_set_icon_string(w, HOME_URL_FIELD,
option_homepage_url ? option_homepage_url : "", true);
ro_gui_set_icon_selected_state(w, HOME_OPEN_STARTUP,
option_open_browser_at_startup);
- global_history_get_recent(&suggestions);
ro_gui_set_icon_shaded_state(w,
- HOME_URL_GRIGHT, (suggestions <= 0));
+ HOME_URL_GRIGHT, !ro_gui_url_suggest_prepare_menu());
/* initialise all functions for a newly created window */
ro_gui_wimp_event_register_menu_gright(w, HOME_URL_FIELD,
diff --git a/riscos/cookies.c b/riscos/cookies.c
index 312f2e479..b0c035adc 100644
--- a/riscos/cookies.c
+++ b/riscos/cookies.c
@@ -1,5 +1,6 @@
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -44,174 +45,243 @@
#include "utils/url.h"
#include "utils/utils.h"
-static bool ro_gui_cookies_click(wimp_pointer *pointer);
-static struct node *ro_gui_cookies_find(const char *url);
+static void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu);
+static bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
-/* The history window, toolbar and plot origins */
-static wimp_w cookies_window;
-struct tree *cookies_tree;
-static bool cookies_init;
+/* The RISC OS cookie window, toolbar and treeview data. */
+
+static struct ro_cookies_window {
+ wimp_w window;
+ struct toolbar *toolbar;
+ ro_treeview *tv;
+ wimp_menu *menu;
+} cookies_window;
/**
- * Initialise cookies tree
+ * Pre-Initialise the cookies tree. This is called for things that
+ * need to be done at the gui_init() stage, such as loading templates.
*/
-void ro_gui_cookies_initialise(void)
+
+void ro_gui_cookies_preinitialise(void)
{
- /* create our window */
- cookies_window = ro_gui_dialog_create("tree");
- ro_gui_set_window_title(cookies_window,
+ /* Create our window. */
+
+ cookies_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(cookies_window.window,
messages_get("Cookies"));
- ro_gui_wimp_event_register_redraw_window(cookies_window,
- ro_gui_tree_redraw);
- ro_gui_wimp_event_register_open_window(cookies_window,
- ro_gui_tree_open);
- ro_gui_wimp_event_register_mouse_click(cookies_window,
- ro_gui_cookies_click);
-
- /* Create an empty tree */
- cookies_tree = calloc(sizeof(struct tree), 1);
- if (!cookies_tree) {
- warn_user("NoMemory", 0);
- return;
- }
- cookies_tree->root = tree_create_folder_node(NULL, "Root");
- if (!cookies_tree->root) {
- warn_user("NoMemory", 0);
- free(cookies_tree);
- cookies_tree = NULL;
+}
+
+/**
+ * Initialise cookies tree, at the gui_init2() stage.
+ */
+
+void ro_gui_cookies_postinitialise(void)
+{
+ /* Create our toolbar. */
+
+ cookies_window.toolbar = ro_gui_theme_create_toolbar(NULL,
+ THEME_COOKIES_TOOLBAR);
+ if (cookies_window.toolbar)
+ ro_gui_theme_attach_toolbar(cookies_window.toolbar,
+ cookies_window.window);
+
+ /* Create the treeview with the window and toolbar. */
+
+ cookies_window.tv = ro_treeview_create(cookies_window.window,
+ cookies_window.toolbar, cookies_get_tree_flags());
+ if (cookies_window.tv == NULL) {
+ LOG(("Failed to allocate treeview"));
return;
}
- cookies_tree->root->expanded = true;
- cookies_tree->handle = (int)cookies_window;
- cookies_tree->movable = false;
- cookies_tree->no_drag = true;
- ro_gui_wimp_event_set_user_data(cookies_window,
- cookies_tree);
- ro_gui_wimp_event_register_keypress(cookies_window,
- ro_gui_tree_keypress);
-
- /* Create our toolbar */
- cookies_tree->toolbar = ro_gui_theme_create_toolbar(NULL,
- THEME_COOKIES_TOOLBAR);
- if (cookies_tree->toolbar)
- ro_gui_theme_attach_toolbar(cookies_tree->toolbar,
- cookies_window);
-
- cookies_init = true;
- urldb_iterate_cookies(cookies_update);
- cookies_init = false;
- tree_initialise(cookies_tree);
+
+ /* Initialise the cookies into the tree. */
+
+ cookies_initialise(ro_treeview_get_tree(cookies_window.tv));
+
+
+ /* Build the cookies window menu. */
+
+ static const struct ns_menu cookies_definition = {
+ "Cookies", {
+ { "Cookies", NO_ACTION, 0 },
+ { "Cookies.Expand", TREE_EXPAND_ALL, 0 },
+ { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "Cookies.Toolbars", NO_ACTION, 0 },
+ { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ cookies_window.menu = ro_gui_menu_define_menu(&cookies_definition);
+
+ ro_gui_wimp_event_register_window_menu(cookies_window.window,
+ cookies_window.menu, ro_gui_cookies_menu_prepare,
+ ro_gui_cookies_menu_select, NULL,
+ ro_gui_cookies_menu_warning, false);
}
+/**
+ * \TODO - Open the cookies window.
+ *
+ */
+
+void ro_gui_cookies_open(void)
+{
+ tree_set_redraw(ro_treeview_get_tree(cookies_window.tv), true);
+
+ if (!ro_gui_dialog_open_top(cookies_window.window,
+ cookies_window.toolbar, 600, 800)) {
+ ro_treeview_set_origin(cookies_window.tv, 0,
+ -(ro_gui_theme_toolbar_height(
+ cookies_window.toolbar)));
+ }
+}
/**
- * Respond to a mouse click
+ * Prepare the cookies menu for opening
*
- * \param pointer the pointer state
- * \return true to indicate click handled
+ * \param window The window owning the menu.
+ * \param *menu The menu about to be opened.
*/
-bool ro_gui_cookies_click(wimp_pointer *pointer)
+
+void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu)
{
- ro_gui_tree_click(pointer, cookies_tree);
- if (pointer->buttons == wimp_CLICK_MENU)
- ro_gui_menu_create(cookies_menu, pointer->pos.x,
- pointer->pos.y, pointer->w);
- else
- ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false);
- return true;
+ bool selection;
+
+ selection = ro_treeview_has_selection(cookies_window.tv);
+
+ ro_gui_menu_set_entry_shaded(cookies_window.menu, TREE_SELECTION,
+ !selection);
+ ro_gui_menu_set_entry_shaded(cookies_window.menu, TREE_CLEAR_SELECTION,
+ !selection);
+
+ ro_gui_menu_set_entry_shaded(cookies_window.menu, TOOLBAR_BUTTONS,
+ (cookies_window.toolbar == NULL ||
+ cookies_window.toolbar->editor));
+ ro_gui_menu_set_entry_ticked(cookies_window.menu, TOOLBAR_BUTTONS,
+ (cookies_window.toolbar != NULL &&
+ (cookies_window.toolbar->display_buttons ||
+ (cookies_window.toolbar->editor))));
+
+ ro_gui_menu_set_entry_shaded(cookies_window.menu, TOOLBAR_EDIT,
+ cookies_window.toolbar == NULL);
+ ro_gui_menu_set_entry_ticked(cookies_window.menu, TOOLBAR_EDIT,
+ (cookies_window.toolbar != NULL &&
+ cookies_window.toolbar->editor));
}
+/**
+ * Handle submenu warnings for the cookies menu
+ *
+ * \param window The window owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ */
+
+void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
+}
/**
- * Perform cookie addition
+ * Handle selections from the cookies menu
*
- * \param data Cookie data for a domain, or NULL
- * \return true (for urldb_iterate_entries)
+ * \param window The window owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
*/
-bool cookies_update(const char *domain, const struct cookie_data *data)
+
+bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
{
- struct node *parent;
- struct node *node = NULL;
- struct node *child;
- struct node *add;
- const struct cookie_data *cookie = NULL;
- bool expanded;
-
- assert(domain);
-
- /* check if we're a domain, and add get the first cookie */
- if (data)
- for (cookie = data; cookie->prev; cookie = cookie->prev);
-
- if (!cookies_init) {
- node = ro_gui_cookies_find(domain);
- if (node) {
- /* mark as deleted so we don't remove the cookies */
- expanded = node->expanded;
- for (child = node->child; child; child = child->next)
- child->deleted = true;
- if (node->child)
- tree_delete_node(cookies_tree, node->child,
- true);
- /* deleting will have contracted our node */
- node->expanded = expanded;
- }
- if (!data) {
- if (!node)
- return true;
- tree_delete_node(cookies_tree, node, false);
- tree_handle_node_changed(cookies_tree,
- cookies_tree->root, true, false);
- return true;
- }
+ switch (action) {
+ case TREE_EXPAND_ALL:
+ cookies_expand_all();
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ cookies_expand_domains();
+ return true;
+ case TREE_EXPAND_LINKS:
+ cookies_expand_cookies();
+ return true;
+ case TREE_COLLAPSE_ALL:
+ cookies_collapse_all();
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ cookies_collapse_domains();
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ cookies_collapse_cookies();
+ return true;
+ case TREE_SELECTION_DELETE:
+ cookies_delete_selected();
+ return true;
+ case TREE_SELECT_ALL:
+ cookies_select_all();
+ return true;
+ case TREE_CLEAR_SELECTION:
+ cookies_clear_selection();
+ return true;
+ default:
+ return false;
}
- if (!node) {
- for (parent = cookies_tree->root->child; parent;
- parent = parent->next) {
- if (strcmp(domain, parent->data.text) == 0)
- break;
- }
- if (!parent) {
- node = tree_create_folder_node(cookies_tree->root,
- domain);
- } else {
- node = parent;
- }
- }
- if (!node)
- return true;
- node->editable = false;
+ return false;
+}
- for (; cookie; cookie = cookie->next) {
- add = tree_create_cookie_node(node, cookie);
- if (add && !cookies_init)
- tree_handle_node_changed(cookies_tree, add,
- true, false);
- }
- if (!cookies_init) {
- tree_handle_node_changed(cookies_tree, node,
- true, false);
- tree_redraw_area(cookies_tree,
- node->box.x - NODE_INSTEP,
- 0, NODE_INSTEP, 16384);
- }
- return true;
+/**
+ * Update the theme details of the cookies window.
+ */
+
+void ro_gui_cookies_update_theme(void)
+{
+ ro_treeview_update_theme(cookies_window.tv);
}
/**
- * Find an entry in the cookie tree
+ * Check if a particular window handle is the cookies window
*
- * \param url The URL to find
- * \return Pointer to node, or NULL if not found
+ * \param window the window in question
+ * \return true if this window is the cookies
*/
-struct node *ro_gui_cookies_find(const char *url)
+
+bool ro_gui_cookies_check_window(wimp_w window)
{
- struct node *node;
+/* SF if (cookies_window.w == window)
+ return true;
+ else*/
+ return false;
+}
- for (node = cookies_tree->root->child; node; node = node->next) {
- if (!strcmp(url, node->data.text))
- return node;
- }
- return NULL;
+/**
+ * Check if a particular menu handle is the cookies menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the cookies menu
+ */
+
+bool ro_gui_cookies_check_menu(wimp_menu *menu)
+{
+ if (cookies_window.menu == menu)
+ return true;
+ else
+ return false;
}
+
diff --git a/riscos/cookies.h b/riscos/cookies.h
index b6dbe7bc6..3539ed9a0 100644
--- a/riscos/cookies.h
+++ b/riscos/cookies.h
@@ -1,5 +1,6 @@
/*
* Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -23,6 +24,13 @@
#ifndef _NETSURF_RISCOS_COOKIES_H_
#define _NETSURF_RISCOS_COOKIES_H_
-void ro_gui_cookies_initialise(void);
+void ro_gui_cookies_preinitialise(void);
+void ro_gui_cookies_postinitialise(void);
+bool ro_gui_cookies_check_window(wimp_w window);
+bool ro_gui_cookies_check_menu(wimp_menu *menu);
+
+void ro_gui_cookies_open(void);
+void ro_gui_cookies_update_theme(void);
#endif
+
diff --git a/riscos/dialog.c b/riscos/dialog.c
index f0520eb73..b4195a5b7 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -39,11 +39,14 @@
#include "riscos/dialog.h"
#include "riscos/global_history.h"
#include "riscos/gui.h"
+#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/options.h"
#include "riscos/save.h"
+#include "riscos/sslcert.h"
#include "riscos/theme.h"
#include "riscos/url_complete.h"
+#include "riscos/url_suggest.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/wimputils.h"
@@ -106,18 +109,6 @@ void ro_gui_dialog_init(void)
/* 401 login window */
ro_gui_401login_init();
- /* certificate verification window */
- ro_gui_cert_init();
-
- /* hotlist window */
- ro_gui_hotlist_initialise();
-
- /* global history window */
- ro_gui_global_history_initialise();
-
- /* cookies window */
- ro_gui_cookies_initialise();
-
/* theme installation */
dialog_theme_install = ro_gui_dialog_create("theme_inst");
ro_gui_wimp_event_register_cancel(dialog_theme_install,
@@ -150,24 +141,6 @@ void ro_gui_dialog_init(void)
dialog_objinfo = ro_gui_dialog_create("objectinfo");
ro_gui_wimp_event_set_help_prefix(dialog_objinfo, "HelpObjInfo");
- /* hotlist folder editing */
- dialog_folder = ro_gui_dialog_create("new_folder");
- ro_gui_wimp_event_register_text_field(dialog_folder, ICON_FOLDER_NAME);
- ro_gui_wimp_event_register_cancel(dialog_folder, ICON_FOLDER_CANCEL);
- ro_gui_wimp_event_register_ok(dialog_folder, ICON_FOLDER_OK,
- ro_gui_hotlist_dialog_apply);
- ro_gui_wimp_event_set_help_prefix(dialog_folder, "HelpHotFolder");
-
- /* hotlist entry editing */
- dialog_entry = ro_gui_dialog_create("new_entry");
- ro_gui_wimp_event_register_text_field(dialog_entry, ICON_ENTRY_NAME);
- ro_gui_wimp_event_register_menu_gright(dialog_entry, ICON_ENTRY_URL,
- ICON_ENTRY_RECENT, url_suggest_menu);
- ro_gui_wimp_event_register_cancel(dialog_entry, ICON_ENTRY_CANCEL);
- ro_gui_wimp_event_register_ok(dialog_entry, ICON_ENTRY_OK,
- ro_gui_hotlist_dialog_apply);
- ro_gui_wimp_event_set_help_prefix(dialog_entry, "HelpHotEntry");
-
/* save as */
dialog_saveas = ro_gui_saveas_create("saveas");
ro_gui_wimp_event_register_button(dialog_saveas, ICON_SAVE_ICON,
@@ -204,6 +177,22 @@ void ro_gui_dialog_init(void)
ro_gui_wimp_event_register_ok(dialog_zoom, ICON_ZOOM_OK,
ro_gui_dialog_zoom_apply);
ro_gui_wimp_event_set_help_prefix(dialog_zoom, "HelpScaleView");
+
+ /* Treeview initialisation has moved to the end, to allow any
+ * associated dialogues to be set up first.
+ */
+
+ /* certificate verification window */
+ ro_gui_cert_preinitialise();
+
+ /* hotlist window */
+ ro_gui_hotlist_preinitialise();
+
+ /* global history window */
+ ro_gui_global_history_preinitialise();
+
+ /* cookies window */
+ ro_gui_cookies_preinitialise();
}
@@ -638,15 +627,25 @@ void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w) {
*/
void ro_gui_dialog_close_persistent(wimp_w parent) {
- int i;
-
- /* Check our mappings
- */
+ int i;
+ wimp_w w;
+
+ /* Check our mappings.
+ *
+ * The window handle is copied into w before proceeding, as
+ * ro_gui_dialog_close() will NULL persistent_dialog[i].dialog as
+ * part of the closing process. This would mean that the subsequent
+ * event dispatch would fail. (These events are logged to allow
+ * side effects to be investigated -- this code hasn't worked before).
+ */
for (i = 0; i < MAX_PERSISTENT; i++) {
if (persistent_dialog[i].parent == parent &&
persistent_dialog[i].dialog != NULL) {
- ro_gui_dialog_close(persistent_dialog[i].dialog);
- ro_gui_wimp_event_close_window(persistent_dialog[i].dialog);
+ w = persistent_dialog[i].dialog;
+ ro_gui_dialog_close(w);
+ if (ro_gui_wimp_event_close_window(w))
+ LOG(("Persistent dialog close event: 0x%x",
+ (unsigned) w));
persistent_dialog[i].parent = NULL;
persistent_dialog[i].dialog = NULL;
}
@@ -710,7 +709,6 @@ bool ro_gui_dialog_openurl_apply(wimp_w w) {
res = url_normalize(url, &url2);
if (res == URL_FUNC_OK) {
browser_window_create(url2, 0, 0, true, false);
- global_history_add_recent(url2);
free(url2);
return true;
}
@@ -724,10 +722,8 @@ bool ro_gui_dialog_openurl_apply(wimp_w w) {
void ro_gui_dialog_prepare_open_url(void)
{
- int suggestions;
ro_gui_set_icon_string(dialog_openurl, ICON_OPENURL_URL, "", true);
- global_history_get_recent(&suggestions);
ro_gui_set_icon_shaded_state(dialog_openurl,
- ICON_OPENURL_MENU, (suggestions <= 0));
+ ICON_OPENURL_MENU, !ro_gui_url_suggest_prepare_menu());
ro_gui_wimp_event_memorise(dialog_openurl);
}
diff --git a/riscos/global_history.c b/riscos/global_history.c
index 5cccae0b4..e9f5ea6ad 100644
--- a/riscos/global_history.c
+++ b/riscos/global_history.c
@@ -1,5 +1,6 @@
/*
* Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -29,12 +30,14 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "content/urldb.h"
+#include "desktop/history_global_core.h"
#include "desktop/tree.h"
#include "riscos/dialog.h"
#include "riscos/global_history.h"
#include "riscos/gui.h"
#include "riscos/menus.h"
#include "riscos/options.h"
+#include "riscos/save.h"
#include "riscos/theme.h"
#include "riscos/treeview.h"
#include "riscos/wimp.h"
@@ -44,401 +47,260 @@
#include "utils/url.h"
#include "utils/utils.h"
-#define MAXIMUM_URL_LENGTH 1024
-#define MAXIMUM_BASE_NODES 16
+static void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu);
+static bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
-static struct node *global_history_base_node[MAXIMUM_BASE_NODES];
-static int global_history_base_node_time[MAXIMUM_BASE_NODES];
-static int global_history_base_node_count = 0;
+/* The RISC OS global history window, toolbar and treeview data */
-static char *global_history_recent_url[GLOBAL_HISTORY_RECENT_URLS];
-static int global_history_recent_count = 0;
-
-static bool global_history_init;
-
-static bool ro_gui_global_history_click(wimp_pointer *pointer);
-static void ro_gui_global_history_initialise_nodes(void);
-static void ro_gui_global_history_initialise_node(const char *title,
- time_t base, int days_back);
-static struct node *ro_gui_global_history_find(const char *url);
-static bool global_history_add_internal(const char *url,
- const struct url_data *data);
-
-/* The history window, toolbar and plot origins */
-static wimp_w global_history_window;
-struct tree *global_history_tree;
+static struct ro_global_history_window {
+ wimp_w window;
+ struct toolbar *toolbar;
+ ro_treeview *tv;
+ wimp_menu *menu;
+} global_history_window;
/**
- * Initialise global history tree
+ * Pre-Initialise the global history tree. This is called for things that
+ * need to be done at the gui_init() stage, such as loading templates.
*/
-void ro_gui_global_history_initialise(void)
+
+void ro_gui_global_history_preinitialise(void)
{
- char s[MAXIMUM_URL_LENGTH];
- FILE *fp;
+ /* Create our window. */
- /* create our window */
- global_history_window = ro_gui_dialog_create("tree");
- ro_gui_set_window_title(global_history_window,
+ global_history_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(global_history_window.window,
messages_get("GlobalHistory"));
- ro_gui_wimp_event_register_redraw_window(global_history_window,
- ro_gui_tree_redraw);
- ro_gui_wimp_event_register_open_window(global_history_window,
- ro_gui_tree_open);
- ro_gui_wimp_event_register_mouse_click(global_history_window,
- ro_gui_global_history_click);
-
- /* Create an empty tree */
- global_history_tree = calloc(sizeof(struct tree), 1);
- if (!global_history_tree) {
- warn_user("NoMemory", 0);
- return;
- }
- global_history_tree->root = tree_create_folder_node(NULL, "Root");
- if (!global_history_tree->root) {
- warn_user("NoMemory", 0);
- free(global_history_tree);
- global_history_tree = NULL;
- return;
- }
- global_history_tree->root->expanded = true;
- ro_gui_global_history_initialise_nodes();
- global_history_tree->handle = (int)global_history_window;
- global_history_tree->movable = false;
- ro_gui_wimp_event_set_user_data(global_history_window,
- global_history_tree);
- ro_gui_wimp_event_register_keypress(global_history_window,
- ro_gui_tree_keypress);
-
- /* Create our toolbar */
- global_history_tree->toolbar = ro_gui_theme_create_toolbar(NULL,
- THEME_HISTORY_TOOLBAR);
- if (global_history_tree->toolbar)
- ro_gui_theme_attach_toolbar(global_history_tree->toolbar,
- global_history_window);
-
- /* load recent URLs */
- fp = fopen(option_recent_path, "r");
- if (!fp)
- LOG(("Failed to open file '%s' for reading",
- option_recent_path));
- else {
- while (fgets(s, MAXIMUM_URL_LENGTH, fp)) {
- if (s[strlen(s) - 1] == '\n')
- s[strlen(s) - 1] = '\0';
- global_history_add_recent(s);
- }
- fclose(fp);
- }
-
- global_history_init = true;
- urldb_iterate_entries(global_history_add_internal);
- global_history_init = false;
- tree_initialise(global_history_tree);
}
/**
- * Initialises the base nodes
+ * Initialise global history tree, at the gui_init2() stage.
*/
-void ro_gui_global_history_initialise_nodes(void)
-{
- struct tm *full_time;
- time_t t;
- int weekday;
- int i;
-
- /* get the current time */
- t = time(NULL);
- if (t == -1)
- return;
- /* get the time at the start of today */
- full_time = localtime(&t);
- weekday = full_time->tm_wday;
- full_time->tm_sec = 0;
- full_time->tm_min = 0;
- full_time->tm_hour = 0;
- t = mktime(full_time);
- if (t == -1)
- return;
+void ro_gui_global_history_postinitialise(void)
+{
- ro_gui_global_history_initialise_node(messages_get("DateToday"), t, 0);
- if (weekday > 0)
- ro_gui_global_history_initialise_node(
- messages_get("DateYesterday"), t, -1);
- for (i = 2; i <= weekday; i++)
- ro_gui_global_history_initialise_node(NULL, t, -i);
- ro_gui_global_history_initialise_node(messages_get("Date1Week"),
- t, -weekday - 7);
- ro_gui_global_history_initialise_node(messages_get("Date2Week"),
- t, -weekday - 14);
- ro_gui_global_history_initialise_node(messages_get("Date3Week"),
- t, -weekday - 21);
-}
+ /* Create our toolbar. */
-/**
- * Create and initialise a node
- */
-void ro_gui_global_history_initialise_node(const char *title,
- time_t base, int days_back)
-{
- struct tm *full_time;
- char buffer[64];
- struct node *node;
-
- base += days_back * 60 * 60 * 24;
- if (!title) {
- full_time = localtime(&base);
- strftime((char *)&buffer, (size_t)64, "%A", full_time);
- node = tree_create_folder_node(NULL, buffer);
- } else
- node = tree_create_folder_node(NULL, title);
-
- if (!node)
+ global_history_window.toolbar = ro_gui_theme_create_toolbar(NULL,
+ THEME_HISTORY_TOOLBAR);
+ if (global_history_window.toolbar)
+ ro_gui_theme_attach_toolbar(global_history_window.toolbar,
+ global_history_window.window);
+
+ /* Create the treeview with the window and toolbar. */
+
+ global_history_window.tv =
+ ro_treeview_create(global_history_window.window,
+ global_history_window.toolbar,
+ history_global_get_tree_flags());
+ if (global_history_window.tv == NULL) {
+ LOG(("Failed to allocate treeview"));
return;
+ }
- node->retain_in_memory = true;
- node->deleted = true;
- node->editable = false;
- global_history_base_node[global_history_base_node_count] = node;
- global_history_base_node_time[global_history_base_node_count] = base;
- global_history_base_node_count++;
+ /* Initialise the global history into the tree. */
+
+ history_global_initialise(
+ ro_treeview_get_tree(global_history_window.tv));
+
+ /* Build the global history window menu. */
+
+ static const struct ns_menu global_history_definition = {
+ "History", {
+ { "History", NO_ACTION, 0 },
+ { "_History.Export", HISTORY_EXPORT, &dialog_saveas },
+ { "History.Expand", TREE_EXPAND_ALL, 0 },
+ { "History.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "History.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "History.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "History.Toolbars", NO_ACTION, 0 },
+ { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+ global_history_window.menu = ro_gui_menu_define_menu(
+ &global_history_definition);
+
+ ro_gui_wimp_event_register_window_menu(global_history_window.window,
+ global_history_window.menu,
+ ro_gui_global_history_menu_prepare,
+ ro_gui_global_history_menu_select, NULL,
+ ro_gui_global_history_menu_warning, false);
}
-
/**
- * Saves the global history's recent URL data.
+ * Open the global history window.
*/
-void ro_gui_global_history_save(void)
+
+void ro_gui_global_history_open(void)
{
- FILE *fp;
- int i;
-
- /* save recent URLs */
- fp = fopen(option_recent_save, "w");
- if (!fp)
- LOG(("Failed to open file '%s' for writing",
- option_recent_save));
- else {
- for (i = global_history_recent_count - 1; i >= 0; i--)
- if (strlen(global_history_recent_url[i]) <
- MAXIMUM_URL_LENGTH)
- fprintf(fp, "%s\n",
- global_history_recent_url[i]);
- fclose(fp);
+ tree_set_redraw(ro_treeview_get_tree(global_history_window.tv), true);
+
+ if (!ro_gui_dialog_open_top(global_history_window.window,
+ global_history_window.toolbar, 600, 800)) {
+ ro_treeview_set_origin(global_history_window.tv, 0,
+ -(ro_gui_theme_toolbar_height(
+ global_history_window.toolbar)));
}
}
-
/**
- * Respond to a mouse click
+ * Prepare the global history menu for opening
*
- * \param pointer the pointer state
- * \return true to indicate click handled
+ * \param window The window owning the menu.
+ * \param *menu The menu about to be opened.
*/
-bool ro_gui_global_history_click(wimp_pointer *pointer)
+
+void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu)
{
- ro_gui_tree_click(pointer, global_history_tree);
- if (pointer->buttons == wimp_CLICK_MENU)
- ro_gui_menu_create(global_history_menu, pointer->pos.x,
- pointer->pos.y, pointer->w);
- else
- ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false);
- return true;
+ bool selection;
+
+ selection = ro_treeview_has_selection(global_history_window.tv);
+
+ ro_gui_menu_set_entry_shaded(global_history_window.menu,
+ TREE_SELECTION, !selection);
+ ro_gui_menu_set_entry_shaded(global_history_window.menu,
+ TREE_CLEAR_SELECTION, !selection);
+
+ ro_gui_menu_set_entry_shaded(global_history_window.menu,
+ TOOLBAR_BUTTONS,
+ (global_history_window.toolbar == NULL ||
+ global_history_window.toolbar->editor));
+ ro_gui_menu_set_entry_ticked(global_history_window.menu,
+ TOOLBAR_BUTTONS,
+ (global_history_window.toolbar != NULL &&
+ (global_history_window.toolbar->display_buttons ||
+ (global_history_window.toolbar->editor))));
+
+ ro_gui_menu_set_entry_shaded(global_history_window.menu, TOOLBAR_EDIT,
+ global_history_window.toolbar == NULL);
+ ro_gui_menu_set_entry_ticked(global_history_window.menu, TOOLBAR_EDIT,
+ (global_history_window.toolbar != NULL &&
+ global_history_window.toolbar->editor));
+
+ ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML,
+ NULL, NULL, NULL, NULL);
}
-
/**
- * Adds to the global history
+ * Handle submenu warnings for the global_hostory menu
*
- * \param url The URL to add
+ * \param window The window owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
*/
-void global_history_add(const char *url)
-{
- const struct url_data *data;
- data = urldb_get_url_data(url);
- if (!data)
- return;
-
- global_history_add_internal(url, data);
+void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ /* Do nothing */
}
/**
- * Internal routine to actually perform global history addition
+ * Handle selections from the global history menu
*
- * \param url The URL to add
- * \param data URL data associated with URL
- * \return true (for urldb_iterate_entries)
+ * \param window The window owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
*/
-bool global_history_add_internal(const char *url,
- const struct url_data *data)
-{
- int i, j;
- struct node *parent = NULL;
- struct node *link;
- struct node *node;
- bool before = false;
- int visit_date;
-
- assert(url && data);
-
- visit_date = data->last_visit;
-
- /* find parent node */
- for (i = 0; i < global_history_base_node_count; i++) {
- if (global_history_base_node_time[i] <= visit_date) {
- parent = global_history_base_node[i];
- break;
- }
- }
- /* the entry is too old to care about */
- if (!parent)
+bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
+{
+ switch (action) {
+ case HISTORY_EXPORT:
+ ro_gui_dialog_open_persistent(window, dialog_saveas, true);
return true;
-
- if (parent->deleted) {
- /* parent was deleted, so find place to insert it */
- link = global_history_tree->root;
-
- for (j = global_history_base_node_count - 1; j >= 0; j--) {
- if (!global_history_base_node[j]->deleted &&
- global_history_base_node_time[j] >
- global_history_base_node_time[i]) {
- link = global_history_base_node[j];
- before = true;
- break;
- }
- }
-
- tree_set_node_selected(global_history_tree,
- parent, false);
- tree_set_node_expanded(global_history_tree,
- parent, false);
- tree_link_node(link, parent, before);
-
- if (!global_history_init) {
- tree_recalculate_node(global_history_tree, parent, true);
- tree_recalculate_node_positions(global_history_tree,
- global_history_tree->root);
- tree_redraw_area(global_history_tree,
- 0, 0, 16384, 16384);
- }
- }
-
- /* find any previous occurance */
- if (!global_history_init) {
- node = ro_gui_global_history_find(url);
- if (node) {
- /* \todo: calculate old/new positions and redraw
- * only the relevant portion */
- tree_redraw_area(global_history_tree,
- 0, 0, 16384, 16384);
- tree_update_URL_node(node, url, data);
- tree_delink_node(node);
- tree_link_node(parent, node, false);
- tree_handle_node_changed(global_history_tree,
- node, false, true);
-/* ro_gui_tree_scroll_visible(hotlist_tree,
- &node->data);
-*/ return true;
- }
- }
-
- /* Add the node at the bottom */
- node = tree_create_URL_node_shared(parent, url, data);
- if ((!global_history_init) && (node)) {
- tree_redraw_area(global_history_tree,
- node->box.x - NODE_INSTEP,
- 0, NODE_INSTEP, 16384);
- tree_handle_node_changed(global_history_tree, node,
- true, false);
+ case TREE_EXPAND_ALL:
+ history_global_expand_all();
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ history_global_expand_directories();
+ return true;
+ case TREE_EXPAND_LINKS:
+ history_global_expand_addresses();
+ return true;
+ case TREE_COLLAPSE_ALL:
+ history_global_collapse_all();
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ history_global_collapse_directories();
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ history_global_collapse_addresses();
+ return true;
+ case TREE_SELECTION_LAUNCH:
+ history_global_launch_selected();
+ return true;
+ case TREE_SELECTION_DELETE:
+ history_global_delete_selected();
+ return true;
+ case TREE_SELECT_ALL:
+ history_global_select_all();
+ return true;
+ case TREE_CLEAR_SELECTION:
+ history_global_clear_selection();
+ return true;
+ default:
+ return false;
}
- return true;
+ return false;
}
/**
- * Find an entry in the global history
- *
- * \param url The URL to find
- * \return Pointer to node, or NULL if not found
+ * Update the theme details of the global history window.
*/
-struct node *ro_gui_global_history_find(const char *url)
+
+void ro_gui_global_history_update_theme(void)
{
- int i;
- struct node *node;
- struct node_element *element;
-
- for (i = 0; i < global_history_base_node_count; i++) {
- if (!global_history_base_node[i]->deleted) {
- for (node = global_history_base_node[i]->child;
- node; node = node->next) {
- element = tree_find_element(node,
- TREE_ELEMENT_URL);
- if ((element) && !strcmp(url, element->text))
- return node;
- }
- }
- }
- return NULL;
+ ro_treeview_update_theme(global_history_window.tv);
}
-
/**
- * Adds an URL to the recently used list
+ * Check if a particular window handle is the global history window
*
- * \param url the URL to add (copied)
+ * \param window the window in question
+ * \return true if this window is the global history
*/
-void global_history_add_recent(const char *url)
-{
- int i;
- int j = -1;
- char *current;
-
- /* try to find a string already there */
- for (i = 0; i < global_history_recent_count; i++)
- if (global_history_recent_url[i] &&
- !strcmp(global_history_recent_url[i], url))
- j = i;
-
- /* already at head of list */
- if (j == 0)
- return;
- if (j < 0) {
- /* add to head of list */
- free(global_history_recent_url[
- GLOBAL_HISTORY_RECENT_URLS - 1]);
- memmove(&global_history_recent_url[1],
- &global_history_recent_url[0],
- (GLOBAL_HISTORY_RECENT_URLS - 1) *
- sizeof(char *));
- global_history_recent_url[0] = strdup(url);
- global_history_recent_count++;
- if (global_history_recent_count > GLOBAL_HISTORY_RECENT_URLS)
- global_history_recent_count =
- GLOBAL_HISTORY_RECENT_URLS;
- if (global_history_recent_count == 1)
- ro_gui_window_prepare_navigate_all();
- } else {
- /* move to head of list */
- current = global_history_recent_url[j];
- for (i = j; i > 0; i--)
- global_history_recent_url[i] =
- global_history_recent_url[i - 1];
- global_history_recent_url[0] = current;
- }
+bool ro_gui_global_history_check_window(wimp_w window)
+{
+/* if (global_history_window.w == window)
+ return true;
+ else*/
+ return false;
}
-
/**
- * Gets details of the currently used URL list.
+ * Check if a particular menu handle is the global history menu
*
- * \param count set to the current number of entries in the URL array on exit
- * \return the current URL array
+ * \param *menu The menu in question.
+ * \return true if this menu is the global history menu
*/
-char **global_history_get_recent(int *count)
+
+bool ro_gui_global_history_check_menu(wimp_menu *menu)
{
- *count = global_history_recent_count;
- return global_history_recent_url;
+ if (global_history_window.menu == menu)
+ return true;
+ else
+ return false;
}
+
diff --git a/riscos/global_history.h b/riscos/global_history.h
index 170cdaaca..951836d5d 100644
--- a/riscos/global_history.h
+++ b/riscos/global_history.h
@@ -1,5 +1,6 @@
/*
* Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -23,10 +24,13 @@
#ifndef _NETSURF_RISCOS_GLOBALHISTORY_H_
#define _NETSURF_RISCOS_GLOBALHISTORY_H_
-#define GLOBAL_HISTORY_RECENT_URLS 16
-
-void ro_gui_global_history_initialise(void);
+void ro_gui_global_history_preinitialise(void);
+void ro_gui_global_history_postinitialise(void);
+void ro_gui_global_history_open(void);
void ro_gui_global_history_save(void);
-
+void ro_gui_global_history_update_theme(void);
+bool ro_gui_global_history_check_window(wimp_w window);
+bool ro_gui_global_history_check_menu(wimp_menu *menu);
#endif
+
diff --git a/riscos/gui.c b/riscos/gui.c
index 18a092c80..6968bb04f 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -55,20 +55,26 @@
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
+#include "desktop/cookies.h"
#include "desktop/gui.h"
+#include "desktop/history_global_core.h"
+#include "desktop/hotlist.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "desktop/save_complete.h"
#include "desktop/tree.h"
+#include "desktop/tree_url_node.h"
#include "render/box.h"
#include "render/font.h"
#include "render/html.h"
#include "riscos/bitmap.h"
#include "riscos/buffer.h"
+#include "riscos/cookies.h"
#include "riscos/dialog.h"
#include "riscos/global_history.h"
#include "riscos/gui.h"
#include "riscos/help.h"
+#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/message.h"
#include "riscos/options.h"
@@ -78,6 +84,7 @@
#include "riscos/print.h"
#include "riscos/query.h"
#include "riscos/save.h"
+#include "riscos/sslcert.h"
#include "riscos/textselection.h"
#include "riscos/theme.h"
#include "riscos/treeview.h"
@@ -184,7 +191,7 @@ static struct {
} prev_sigs;
/** Accepted wimp user messages. */
-static ns_wimp_message_list task_messages = {
+static ns_wimp_message_list task_messages = {
message_HELP_REQUEST,
{
message_DATA_SAVE,
@@ -347,6 +354,8 @@ static void gui_init(int argc, char** argv)
option_theme_path = strdup("NetSurf:Themes");
if (!option_theme_save)
option_theme_save = strdup(CHOICES_PREFIX "Themes");
+ if (!option_tree_icons_dir)
+ option_tree_icons_dir = strdup("NetSurf:Resources.Icons");
if (!option_theme || ! option_toolbar_browser ||
!option_toolbar_hotlist || !option_toolbar_history ||
@@ -355,7 +364,7 @@ static void gui_init(int argc, char** argv)
!option_url_save || !option_hotlist_path ||
!option_hotlist_save || !option_recent_path ||
!option_recent_save || !option_theme_path ||
- !option_theme_save)
+ !option_theme_save || !option_tree_icons_dir)
die("Failed initialising string options");
/* Create our choices directories */
@@ -394,7 +403,7 @@ static void gui_init(int argc, char** argv)
default_stylesheet_url = strdup("file:///NetSurf:/Resources/CSS");
quirks_stylesheet_url = strdup("file:///NetSurf:/Resources/Quirks");
adblock_stylesheet_url = strdup("file:///NetSurf:/Resources/AdBlock");
- if (!default_stylesheet_url || !quirks_stylesheet_url ||
+ if (!default_stylesheet_url || !quirks_stylesheet_url ||
!adblock_stylesheet_url)
die("Failed initialising string constants.");
@@ -479,9 +488,6 @@ static void gui_init(int argc, char** argv)
/* Done with the templates file */
wimp_close_template();
- /* Initialise tree views (must be after UI sprites are loaded) */
- ro_gui_tree_initialise();
-
/* Create Iconbar icon */
ro_gui_icon_bar_create();
@@ -670,6 +676,21 @@ static void gui_init2(int argc, char** argv)
char *url = 0;
bool open_window = option_open_browser_at_startup;
+ /* Complete initialisation of the treeview modules. */
+
+ /* certificate verification window */
+ ro_gui_cert_postinitialise();
+
+ /* hotlist window */
+ ro_gui_hotlist_postinitialise();
+
+ /* global history window */
+ ro_gui_global_history_postinitialise();
+
+ /* cookies window */
+ ro_gui_cookies_postinitialise();
+
+
/* parse command-line arguments */
if (argc == 2) {
LOG(("parameters: '%s'", argv[1]));
@@ -781,8 +802,9 @@ void gui_quit(void)
urldb_save_cookies(option_cookie_jar);
urldb_save(option_url_save);
ro_gui_window_quit();
- ro_gui_global_history_save();
- ro_gui_hotlist_save();
+ history_global_cleanup();
+ cookies_cleanup();
+ hotlist_cleanup(option_hotlist_save);
ro_gui_saveas_quit();
rufl_quit();
free(gui_sprites);
@@ -1109,6 +1131,9 @@ void ro_gui_null_reason_code(void)
// break;
default:
+ if (ro_gui_hotlist_check_window(gui_track_wimp_w))
+ ro_treeview_mouse_at(gui_track_wimp_w,
+ &pointer);
if (gui_track_wimp_w == history_window)
ro_gui_history_mouse_at(&pointer);
if (gui_track_wimp_w == dialog_url_complete)
@@ -1203,8 +1228,10 @@ void ro_gui_pointer_entering_window(wimp_entering *entering)
default:
gui_track_wimp_w = entering->w;
gui_track_gui_window = ro_gui_window_lookup(entering->w);
- gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
- gui_track_wimp_w == dialog_url_complete;
+ gui_track = gui_track_gui_window ||
+ gui_track_wimp_w == history_window ||
+ gui_track_wimp_w == dialog_url_complete ||
+ ro_gui_hotlist_check_window(gui_track_wimp_w);
break;
}
}
@@ -1275,11 +1302,11 @@ void ro_gui_drag_end(wimp_dragged *drag)
break;
case GUI_DRAG_TREE_SELECT:
- ro_gui_tree_selection_drag_end(drag);
+// ro_gui_tree_selection_drag_end(drag);
break;
case GUI_DRAG_TREE_MOVE:
- ro_gui_tree_move_drag_end(drag);
+// ro_gui_tree_move_drag_end(drag);
break;
case GUI_DRAG_TOOLBAR_CONFIG:
@@ -1485,12 +1512,7 @@ void ro_msg_dataload(wimp_message *message)
char *url = 0;
char *title = NULL;
struct gui_window *g;
- struct node *node;
- struct node *link;
os_error *error;
- int x, y;
- bool before;
- const struct url_data *data;
g = ro_gui_window_lookup(message->data.data_xfer.w);
if (g) {
@@ -1551,28 +1573,9 @@ void ro_msg_dataload(wimp_message *message)
if (g) {
browser_window_go(g->bw, url, 0, true);
- } else if ((hotlist_tree) && ((wimp_w)hotlist_tree->handle ==
- message->data.data_xfer.w)) {
- data = urldb_get_url_data(url);
- if (!data) {
- urldb_add_url(url);
- urldb_set_url_persistence(url, true);
- data = urldb_get_url_data(url);
- }
- if (data) {
- ro_gui_tree_get_tree_coordinates(hotlist_tree,
- message->data.data_xfer.pos.x,
- message->data.data_xfer.pos.y,
- &x, &y);
- link = tree_get_link_details(hotlist_tree, x, y, &before);
- node = tree_create_URL_node(NULL, url, data, title);
- tree_link_node(link, node, before);
- tree_handle_node_changed(hotlist_tree, node, false, true);
- tree_redraw_area(hotlist_tree, node->box.x - NODE_INSTEP, 0,
- NODE_INSTEP, 16384);
- if ((!title) && (!data->title))
- ro_gui_tree_start_edit(hotlist_tree, &node->data, NULL);
- }
+// } else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) {
+// /* Drop URL into hotlist */
+// ro_gui_hotlist_url_drop(message, url);
} else {
browser_window_create(url, 0, 0, true, false);
}
diff --git a/riscos/gui.h b/riscos/gui.h
index 101eedac2..c400494f8 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -64,7 +64,6 @@ extern bool gui_redraw_debug;
extern osspriteop_area *gui_sprites;
extern bool dialog_folder_add, dialog_entry_add, hotlist_insert;
extern bool print_active, print_text_black;
-extern struct tree *hotlist_tree, *global_history_tree, *cookies_tree;
typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE,
GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE,
@@ -136,10 +135,6 @@ bool ro_gui_download_prequit(void);
/* in 401login.c */
void ro_gui_401login_init(void);
-/* in sslcert.c */
-void ro_gui_cert_init(void);
-void ro_gui_cert_open(struct tree *tree, struct node *node);
-
/* in window.c */
void ro_gui_window_quit(void);
/* void ro_gui_window_close_all(void); */
@@ -161,7 +156,10 @@ void ro_gui_window_process_reformats(void);
void ro_gui_window_default_options(struct browser_window *bw);
void ro_gui_window_redraw_all(void);
void ro_gui_window_prepare_navigate_all(void);
-browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons);
+browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons,
+ wimp_icon_flags type);
+browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons,
+ wimp_icon_flags type);
bool ro_gui_shift_pressed(void);
bool ro_gui_ctrl_pressed(void);
bool ro_gui_alt_pressed(void);
@@ -178,13 +176,6 @@ void ro_gui_history_open(struct browser_window *bw, struct history *history,
bool pointer);
void ro_gui_history_mouse_at(wimp_pointer *pointer);
-/* in hotlist.c */
-void ro_gui_hotlist_initialise(void);
-void ro_gui_hotlist_save(void);
-void ro_gui_hotlist_prepare_folder_dialog(struct node *node);
-void ro_gui_hotlist_prepare_entry_dialog(struct node *node);
-bool ro_gui_hotlist_dialog_apply(wimp_w w);
-
/* in filetype.c */
int ro_content_filetype(struct hlcache_handle *c);
int ro_content_filetype_from_type(content_type type);
diff --git a/riscos/help.c b/riscos/help.c
index 6d5efe974..968fcb7c4 100644
--- a/riscos/help.c
+++ b/riscos/help.c
@@ -28,7 +28,10 @@
#include "oslib/taskmanager.h"
#include "oslib/wimp.h"
#include "desktop/tree.h"
+#include "riscos/cookies.h"
+#include "riscos/global_history.h"
#include "riscos/gui.h"
+#include "riscos/hotlist.h"
#include "riscos/help.h"
#include "riscos/menus.h"
#include "riscos/options.h"
@@ -100,7 +103,7 @@ void ro_gui_interactive_help_request(wimp_message *message)
os_error *error;
const char *auto_text;
int i;
-
+
/* check we aren't turned off */
if (!option_interactive_help)
return;
@@ -124,18 +127,17 @@ void ro_gui_interactive_help_request(wimp_message *message)
sprintf(message_token, "%s%i", auto_text, (int)icon);
else if (window == wimp_ICON_BAR)
sprintf(message_token, "HelpIconbar");
- else if ((hotlist_tree) && (window == (wimp_w)hotlist_tree->handle)) {
- i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y);
+ else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
sprintf(message_token,
(i >= 0) ? "HelpTree%i" :"HelpHotlist%i", i);
- } else if ((global_history_tree) &&
- (window == (wimp_w)global_history_tree->handle)) {
- i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y);
+ } else if (ro_gui_global_history_check_window(
+ message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
sprintf(message_token,
(i >= 0) ? "HelpTree%i" :"HelpGHistory%i", i);
- } else if ((cookies_tree) &&
- (window == (wimp_w)cookies_tree->handle)) {
- i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y);
+ } else if (ro_gui_cookies_check_window(message->data.data_xfer.w)) {
+ i = ro_treeview_get_help(message_data);
sprintf(message_token,
(i >= 0) ? "HelpTree%i" :"HelpCookies%i", i);
} else if (ro_gui_window_lookup(window) != NULL)
@@ -173,11 +175,11 @@ void ro_gui_interactive_help_request(wimp_message *message)
sprintf(message_token, "HelpIconMenu");
else if (current_menu == browser_menu)
sprintf(message_token, "HelpBrowserMenu");
- else if (current_menu == hotlist_menu)
+ else if (ro_gui_hotlist_check_menu(current_menu))
sprintf(message_token, "HelpHotlistMenu");
- else if (current_menu == global_history_menu)
+ else if (ro_gui_global_history_check_menu(current_menu))
sprintf(message_token, "HelpGHistoryMenu");
- else if (current_menu == cookies_menu)
+ else if (ro_gui_cookies_check_menu(current_menu))
sprintf(message_token, "HelpCookiesMenu");
else
return;
@@ -323,7 +325,7 @@ void ro_gui_interactive_help_start(void)
char *help_start;
wimp_t task = 0;
os_error *error;
-
+
/* don't launch a second copy of anything */
if (ro_gui_interactive_help_available())
return;
diff --git a/riscos/hotlist.c b/riscos/hotlist.c
index dd611b691..6e2d176cc 100644
--- a/riscos/hotlist.c
+++ b/riscos/hotlist.c
@@ -1,5 +1,6 @@
/*
* Copyright 2004, 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -31,10 +32,13 @@
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
+#include "desktop/hotlist.h"
#include "desktop/tree.h"
#include "riscos/dialog.h"
+#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/options.h"
+#include "riscos/save.h"
#include "riscos/theme.h"
#include "riscos/treeview.h"
#include "riscos/wimp.h"
@@ -44,350 +48,300 @@
#include "utils/utils.h"
#include "utils/url.h"
+static void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu);
+static bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
+static void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action);
-static void ro_gui_hotlist_visited(hlcache_handle *c, struct tree *tree,
- struct node *node);
-static bool ro_gui_hotlist_click(wimp_pointer *pointer);
-
-
-/* The hotlist window, toolbar and plot origins
-*/
-static wimp_w hotlist_window;
-struct tree *hotlist_tree;
-
-/* Whether the editing facilities are for add so that we know how
- to reset the dialog boxes on a adjust-cancel and the action to
- perform on ok.
-*/
-struct node *dialog_folder_node;
-struct node *dialog_entry_node;
-
-static const struct {
- const char *url;
- const char *msg_key;
-} default_entries[] = {
- { "http://www.netsurf-browser.org/", "HotlistHomepage" },
- { "http://www.netsurf-browser.org/downloads/riscos/testbuilds", "HotlistTestBuild" },
- { "http://www.netsurf-browser.org/documentation", "HotlistDocumentation" },
- { "http://sourceforge.net/tracker/?atid=464312&group_id=51719",
- "HotlistBugTracker" },
- { "http://sourceforge.net/tracker/?atid=464315&group_id=51719",
- "HotlistFeatureRequest" }
-};
-#define ENTRIES_COUNT (sizeof(default_entries) / sizeof(default_entries[0]))
-
-void ro_gui_hotlist_initialise(void)
+/* The RISC OS hotlist window, toolbar and treeview data. */
+
+static struct ro_hotlist {
+ wimp_w window; /*< The hotlist RO window handle. */
+ struct toolbar *toolbar; /*< The hotlist toolbar handle. */
+ ro_treeview *tv; /*< The hotlist treeview handle. */
+ wimp_menu *menu; /*< The hotlist window menu. */
+} hotlist_window;
+
+/**
+ * Pre-Initialise the hotlist tree. This is called for things that need to
+ * be done at the gui_init() stage, such as loading templates.
+ */
+
+void ro_gui_hotlist_preinitialise(void)
{
- FILE *fp;
- struct node *node;
- const struct url_data *data;
+ /* Create our window. */
- /* create our window */
- hotlist_window = ro_gui_dialog_create("tree");
- ro_gui_set_window_title(hotlist_window,
+ hotlist_window.window = ro_gui_dialog_create("tree");
+ ro_gui_set_window_title(hotlist_window.window,
messages_get("Hotlist"));
- ro_gui_wimp_event_register_redraw_window(hotlist_window,
- ro_gui_tree_redraw);
- ro_gui_wimp_event_register_open_window(hotlist_window,
- ro_gui_tree_open);
- ro_gui_wimp_event_register_mouse_click(hotlist_window,
- ro_gui_hotlist_click);
-
- /* Either load or create a hotlist
- */
- fp = fopen(option_hotlist_path, "r");
- if (!fp) {
- int i;
-
- hotlist_tree = calloc(sizeof(struct tree), 1);
- if (!hotlist_tree) {
- warn_user("NoMemory", 0);
- return;
- }
- hotlist_tree->root = tree_create_folder_node(NULL, "Root");
- if (!hotlist_tree->root) {
- warn_user("NoMemory", 0);
- free(hotlist_tree);
- hotlist_tree = NULL;
- return;
- }
- hotlist_tree->root->expanded = true;
- node = tree_create_folder_node(hotlist_tree->root, "NetSurf");
- if (!node)
- node = hotlist_tree->root;
-
- for (i = 0; i != ENTRIES_COUNT; i++) {
- data = urldb_get_url_data(default_entries[i].url);
- if (!data) {
- urldb_add_url(default_entries[i].url);
- urldb_set_url_persistence(
- default_entries[i].url,
- true);
- data = urldb_get_url_data(
- default_entries[i].url);
- }
- if (data) {
- tree_create_URL_node(node,
- default_entries[i].url, data,
- messages_get(default_entries[i].msg_key));
- }
- }
- tree_initialise(hotlist_tree);
- } else {
- fclose(fp);
- hotlist_tree = options_load_tree(option_hotlist_path);
- }
- if (!hotlist_tree) return;
- hotlist_tree->handle = (int)hotlist_window;
- hotlist_tree->movable = true;
- ro_gui_wimp_event_set_user_data(hotlist_window, hotlist_tree);
- ro_gui_wimp_event_register_keypress(hotlist_window,
- ro_gui_tree_keypress);
-
- /* Create our toolbar
- */
- hotlist_tree->toolbar = ro_gui_theme_create_toolbar(NULL,
- THEME_HOTLIST_TOOLBAR);
- if (hotlist_tree->toolbar)
- ro_gui_theme_attach_toolbar(hotlist_tree->toolbar,
- hotlist_window);
}
-
/**
- * Perform a save to the default file
+ * Initialise the hotlist tree, at the gui_init2() stage.
*/
-void ro_gui_hotlist_save(void)
+
+void ro_gui_hotlist_postinitialise(void)
{
- os_error *error;
+ /* Create our toolbar. */
- if (!hotlist_tree)
+ hotlist_window.toolbar = ro_gui_theme_create_toolbar(NULL,
+ THEME_HOTLIST_TOOLBAR);
+ if (hotlist_window.toolbar)
+ ro_gui_theme_attach_toolbar(hotlist_window.toolbar,
+ hotlist_window.window);
+
+ /* Create the treeview with the window and toolbar. */
+
+ hotlist_window.tv = ro_treeview_create(hotlist_window.window,
+ hotlist_window.toolbar, hotlist_get_tree_flags());
+ if (hotlist_window.tv == NULL) {
+ LOG(("Failed to allocate treeview"));
return;
+ }
- /* Save to our file
- */
- options_save_tree(hotlist_tree, option_hotlist_save,
- "NetSurf hotlist");
- error = xosfile_set_type(option_hotlist_save, 0xfaf);
- if (error)
- LOG(("xosfile_set_type: 0x%x: %s",
- error->errnum, error->errmess));
+ /* Initialise the hotlist into the tree. */
+
+ hotlist_initialise(ro_treeview_get_tree(hotlist_window.tv),
+ option_hotlist_path);
+
+
+ /* Build the hotlist window menu. */
+
+ static const struct ns_menu hotlist_definition = {
+ "Hotlist", {
+ { "Hotlist", NO_ACTION, 0 },
+ { "Hotlist.New", NO_ACTION, 0 },
+ { "Hotlist.New.Folder", TREE_NEW_FOLDER, 0 },
+ { "Hotlist.New.Link", TREE_NEW_LINK, 0 },
+ { "_Hotlist.Export", HOTLIST_EXPORT, &dialog_saveas },
+ { "Hotlist.Expand", TREE_EXPAND_ALL, 0 },
+ { "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 },
+ { "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
+ { "Hotlist.Expand.Links", TREE_EXPAND_LINKS, 0 },
+ { "Hotlist.Collapse", TREE_COLLAPSE_ALL, 0 },
+ { "Hotlist.Collapse.All", TREE_COLLAPSE_ALL, 0 },
+ { "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
+ { "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
+ { "Hotlist.Toolbars", NO_ACTION, 0 },
+ { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
+ { "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
+ { "Selection", TREE_SELECTION, 0 },
+ { "Selection.Edit", TREE_SELECTION_EDIT, 0 },
+ { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
+ { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
+ { "SelectAll", TREE_SELECT_ALL, 0 },
+ { "Clear", TREE_CLEAR_SELECTION, 0 },
+ {NULL, 0, 0}
+ }
+ };
+
+ hotlist_window.menu = ro_gui_menu_define_menu(&hotlist_definition);
+
+ ro_gui_wimp_event_register_window_menu(hotlist_window.window,
+ hotlist_window.menu, ro_gui_hotlist_menu_prepare,
+ ro_gui_hotlist_menu_select, NULL,
+ ro_gui_hotlist_menu_warning, false);
}
/**
- * Respond to a mouse click
+ * Open the hotlist window.
*
- * \param pointer the pointer state
*/
-bool ro_gui_hotlist_click(wimp_pointer *pointer)
+
+void ro_gui_hotlist_open(void)
{
- ro_gui_tree_click(pointer, hotlist_tree);
- if (pointer->buttons == wimp_CLICK_MENU)
- ro_gui_menu_create(hotlist_menu, pointer->pos.x,
- pointer->pos.y, pointer->w);
- else
- ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false);
- return true;
+ tree_set_redraw(ro_treeview_get_tree(hotlist_window.tv), true);
+
+ if (!ro_gui_dialog_open_top(hotlist_window.window,
+ hotlist_window.toolbar, 600, 800)) {
+
+ xwimp_set_caret_position(hotlist_window.window, -1, -100, -100, 32, -1);
+// \todo ro_gui_theme_process_toolbar(hotlist_window.toolbar, -1);
+ ro_treeview_set_origin(hotlist_window.tv, 0,
+ -(ro_gui_theme_toolbar_height(
+ hotlist_window.toolbar)));
+// ro_gui_tree_stop_edit(tree);
+//
+// if (tree->root->child) {
+// tree_set_node_selected(tree, tree->root, false);
+// tree_handle_node_changed(tree, tree->root,
+// false, true);
+// }
+ }
}
-
/**
- * Informs the hotlist that some content has been visited
+ * Prepare the hotlist menu for opening
*
- * \param content the content visited
+ * \param window The window owning the menu.
+ * \param *menu The menu about to be opened.
*/
-void hotlist_visited(hlcache_handle *c)
+
+void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu)
{
- if ((!c) || (!content_get_url(c)) || (!hotlist_tree))
- return;
- ro_gui_hotlist_visited(c, hotlist_tree, hotlist_tree->root);
+ bool selection;
+
+ selection = ro_treeview_has_selection(hotlist_window.tv);
+
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu, TREE_SELECTION,
+ !selection);
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu, TREE_CLEAR_SELECTION,
+ !selection);
+
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu, TOOLBAR_BUTTONS,
+ (hotlist_window.toolbar == NULL ||
+ hotlist_window.toolbar->editor));
+ ro_gui_menu_set_entry_ticked(hotlist_window.menu, TOOLBAR_BUTTONS,
+ (hotlist_window.toolbar != NULL &&
+ (hotlist_window.toolbar->display_buttons ||
+ hotlist_window.toolbar->editor)));
+
+ ro_gui_menu_set_entry_shaded(hotlist_window.menu, TOOLBAR_EDIT,
+ hotlist_window.toolbar == NULL);
+ ro_gui_menu_set_entry_ticked(hotlist_window.menu, TOOLBAR_EDIT,
+ (hotlist_window.toolbar != NULL &&
+ hotlist_window.toolbar->editor));
+
+ ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML,
+ NULL, NULL, NULL, NULL);
}
-
/**
- * Informs the hotlist that some content has been visited
+ * Handle submenu warnings for the hotlist menu
*
- * \param content the content visited
- * \param tree the tree to find the URL data from
- * \param node the node to update siblings and children of
+ * \param window The window owning the menu.
+ * \param *menu The menu to which the warning applies.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
*/
-void ro_gui_hotlist_visited(hlcache_handle *c, struct tree *tree,
- struct node *node)
+
+void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
{
- struct node_element *element;
-
- for (; node; node = node->next) {
- if (!node->folder) {
- element = tree_find_element(node, TREE_ELEMENT_URL);
- if ((element) && (!strcmp(element->text,
- content_get_url(c)))) {
- tree_update_URL_node(node, content_get_url(c),
- NULL);
- tree_handle_node_changed(tree, node, true,
- false);
- }
- }
- if (node->child)
- ro_gui_hotlist_visited(c, tree, node->child);
- }
+ /* Do nothing */
}
-
/**
- * Prepares the folder dialog contents for a node
+ * Handle selections from the hotlist menu
*
- * \param node the node to prepare the dialogue for, or NULL
+ * \param window The window owning the menu.
+ * \param *menu The menu from which the selection was made.
+ * \param *selection The wimp menu selection data.
+ * \param action The selected menu action.
+ * \return true if action accepted; else false.
*/
-void ro_gui_hotlist_prepare_folder_dialog(struct node *node)
+
+bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu,
+ wimp_selection *selection, menu_action action)
{
- const char *name;
- const char *title;
-
- dialog_folder_node = node;
- if (node) {
- title = messages_get("EditFolder");
- name = node->data.text;
- } else {
- title = messages_get("NewFolder");
- name = messages_get("Folder");
+ switch (action) {
+ case HOTLIST_EXPORT:
+ ro_gui_dialog_open_persistent(window, dialog_saveas, true);
+ return true;
+ case TREE_NEW_FOLDER:
+ hotlist_add_folder();
+ return true;
+ case TREE_NEW_LINK:
+ hotlist_add_entry();
+ return true;
+ case TREE_EXPAND_ALL:
+ hotlist_expand_all();
+ return true;
+ case TREE_EXPAND_FOLDERS:
+ hotlist_expand_directories();
+ return true;
+ case TREE_EXPAND_LINKS:
+ hotlist_expand_addresses();
+ return true;
+ case TREE_COLLAPSE_ALL:
+ hotlist_collapse_all();
+ return true;
+ case TREE_COLLAPSE_FOLDERS:
+ hotlist_collapse_directories();
+ return true;
+ case TREE_COLLAPSE_LINKS:
+ hotlist_collapse_addresses();
+ return true;
+ case TREE_SELECTION_EDIT:
+ hotlist_edit_selected();
+ return true;
+ case TREE_SELECTION_LAUNCH:
+ hotlist_launch_selected();
+ return true;
+ case TREE_SELECTION_DELETE:
+ hotlist_delete_selected();
+ return true;
+ case TREE_SELECT_ALL:
+ hotlist_select_all();
+ return true;
+ case TREE_CLEAR_SELECTION:
+ hotlist_clear_selection();
+ return true;
+ default:
+ return false;
}
- ro_gui_set_window_title(dialog_folder, title);
- ro_gui_set_icon_string(dialog_folder, ICON_FOLDER_NAME, name, true);
- ro_gui_wimp_event_memorise(dialog_folder);
-}
+ return false;
+}
/**
- * Prepares the entry dialog contents for a node
- *
- * \param node the node to prepare the dialogue for, or NULL
+ * Update the theme details of the hotlist window.
*/
-void ro_gui_hotlist_prepare_entry_dialog(struct node *node)
+
+void ro_gui_hotlist_update_theme(void)
{
- struct node_element *element;
- const char *name;
- const char *title;
- const char *url = "";
-
- dialog_entry_node = node;
- if (node) {
- title = messages_get("EditLink");
- name = node->data.text;
- if ((element = tree_find_element(node, TREE_ELEMENT_URL)))
- url = element->text;
- } else {
- title = messages_get("NewLink");
- name = messages_get("Link");
- }
- ro_gui_set_window_title(dialog_entry, title);
- ro_gui_set_icon_string(dialog_entry, ICON_ENTRY_NAME, name, true);
- ro_gui_set_icon_string(dialog_entry, ICON_ENTRY_URL, url, true);
- ro_gui_wimp_event_memorise(dialog_entry);
+ ro_treeview_update_theme(hotlist_window.tv);
}
-
/**
- * Apply the settings of dialog window (folder/entry edit)
+ * Check if a particular window handle is the hotlist window
*
- * \param w the window to apply
+ * \param window The window in question
+ * \return true if this window is the hotlist
*/
-bool ro_gui_hotlist_dialog_apply(wimp_w w)
+bool ro_gui_hotlist_check_window(wimp_w window)
{
- struct node_element *element;
- struct node *node;
- const char *icon;
- char *title;
- char *url = NULL;
- url_func_result res;
- const struct url_data *data;
-
- /* get our data */
- if (w == dialog_entry) {
- icon = ro_gui_get_icon_string(w, ICON_ENTRY_URL);
-
- res = url_normalize(icon, &url);
- if (res != URL_FUNC_OK) {
- warn_user(res == URL_FUNC_FAILED ? "NoURLError"
- : "NoMemory", 0);
- return false;
- }
+ if (hotlist_window.window == window)
+ return true;
+ else
+ return false;
+}
- icon = ro_gui_get_icon_string(w, ICON_ENTRY_NAME);
- while (isspace(*icon))
- icon++;
- title = strdup(icon);
+/**
+ * Check if a particular menu handle is the hotlist menu
+ *
+ * \param *menu The menu in question.
+ * \return true if this menu is the hotlist menu
+ */
- node = dialog_entry_node;
- } else {
- icon = ro_gui_get_icon_string(w, ICON_FOLDER_NAME);
- while (isspace(*icon))
- icon++;
- title = strdup(icon);
+bool ro_gui_hotlist_check_menu(wimp_menu *menu)
+{
+ if (hotlist_window.menu == menu)
+ return true;
+ else
+ return false;
+}
- node = dialog_folder_node;
- }
+#if 0
+/**
+ * Handle URL dropped on hotlist
+ *
+ * \param message the wimp message we're acting on
+ * \param url the URL to add
+ */
+void ro_gui_hotlist_url_drop(wimp_message *message, const char *url)
+{
+ int x, y;
+ if (hotlist_window.window != message->data.data_xfer.w)
+ return;
- if (title != NULL)
- strip(title);
-
- /* check for lack of text */
- if (title == NULL || title[0] == '\0') {
- if (title == NULL)
- warn_user("NoMemory", 0);
- else if (title[0] == '\0')
- warn_user("NoNameError", 0);
- free(url);
- free(title);
- node = NULL;
- return false;
- }
- ro_gui_set_icon_string(w, url ? ICON_ENTRY_NAME : ICON_FOLDER_NAME,
- title, false);
-
- /* update/insert our data */
- if (!node) {
- if (url) {
- data = urldb_get_url_data(url);
- if (!data) {
- urldb_add_url(url);
- urldb_set_url_persistence(url, true);
- data = urldb_get_url_data(url);
- }
- if (!data) {
- free(url);
- free(title);
- return false;
- }
- if (!data->title)
- urldb_set_url_title(url, title);
- node = dialog_entry_node = tree_create_URL_node(
- hotlist_tree->root, url, data, title);
-
- } else {
- node = dialog_folder_node = tree_create_folder_node(
- hotlist_tree->root, title);
- }
- free(url);
- free(title);
- if (!node) {
- warn_user("NoMemory", 0);
- return false;
- }
- tree_handle_node_changed(hotlist_tree, node, true, false);
- ro_gui_tree_scroll_visible(hotlist_tree, &node->data);
- tree_redraw_area(hotlist_tree, node->box.x - NODE_INSTEP,
- 0, NODE_INSTEP, 16384);
- } else {
- element = tree_find_element(node, TREE_ELEMENT_URL);
- if (element) {
- free((void *)element->text);
- element->text = url;
- ro_gui_set_icon_string(w, ICON_ENTRY_URL, url, true);
- }
- free((void *)node->data.text);
- node->data.text = title;
- tree_handle_node_changed(hotlist_tree, node, true, false);
- }
- return true;
+ ro_gui_tree_get_tree_coordinates(hotlist_window.tree,
+ message->data.data_xfer.pos.x,
+ message->data.data_xfer.pos.y,
+ &x, &y);
+ hotlist_add_page_xy(url, x, y);
}
+#endif
+
diff --git a/beos/beos_history.h b/riscos/hotlist.h
index 71536f1ca..e416b2124 100644
--- a/beos/beos_history.h
+++ b/riscos/hotlist.h
@@ -1,6 +1,6 @@
/*
- * Copyright 2008 François Revol <mmu_man@users.sourceforge.net>
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,20 +17,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __NSBEOS_HISTORY_H__
-#define __NSBEOS_HISTORY_H__
+/** \file
+ * Hotlist (interface).
+ */
-#include <View.h>
-#include <Window.h>
+#ifndef _NETSURF_RISCOS_HOTLIST_H_
+#define _NETSURF_RISCOS_HOTLIST_H_
-extern BWindow *wndHistory;
+void ro_gui_hotlist_preinitialise(void);
+void ro_gui_hotlist_postinitialise(void);
+void ro_gui_hotlist_open(void);
+void ro_gui_hotlist_save(void);
+void ro_gui_hotlist_update_theme(void);
+bool ro_gui_hotlist_check_window(wimp_w window);
+bool ro_gui_hotlist_check_menu(wimp_menu *menu);
-void nsbeos_history_init(void);
-void nsbeos_history_update(void);
-#warning XXX
-#if 0 /* GTK */
-void nsbeos_history_row_activated(GtkTreeView *, GtkTreePath *,
- GtkTreeViewColumn *, gpointer);
#endif
-#endif /* __NSGTK_HISTORY_H__ */
diff --git a/riscos/menus.c b/riscos/menus.c
index da0a686ad..39e1a4c03 100644
--- a/riscos/menus.c
+++ b/riscos/menus.c
@@ -34,9 +34,12 @@
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
+#include "desktop/cookies.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
+#include "desktop/history_global_core.h"
#include "desktop/history_core.h"
+#include "desktop/hotlist.h"
#include "desktop/netsurf.h"
#include "desktop/selection.h"
#include "desktop/textinput.h"
@@ -49,12 +52,14 @@
#include "riscos/gui.h"
#include "riscos/global_history.h"
#include "riscos/help.h"
+#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/options.h"
#include "riscos/save.h"
#include "riscos/tinct.h"
#include "riscos/theme.h"
#include "riscos/treeview.h"
+#include "riscos/url_suggest.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "utils/log.h"
@@ -63,18 +68,6 @@
#include "utils/utils.h"
#include "utils/utf8.h"
-
-struct ns_menu_entry {
- const char *text; /**< menu text (from messages) */
- menu_action action; /**< associated action */
- wimp_w *sub_window; /**< sub-window if any */
-};
-
-struct ns_menu {
- const char *title;
- struct ns_menu_entry entries[];
-};
-
struct menu_definition_entry {
menu_action action; /**< menu action */
wimp_menu_entry *menu_entry; /**< corresponding menu entry */
@@ -91,7 +84,6 @@ struct menu_definition {
};
-static wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu);
static void ro_gui_menu_define_menu_add(struct menu_definition *definition,
const struct ns_menu *menu, int depth,
wimp_menu_entry *parent_entry,
@@ -101,15 +93,11 @@ static struct menu_definition_entry *ro_gui_menu_find_entry(wimp_menu *menu,
menu_action action);
static menu_action ro_gui_menu_find_action(wimp_menu *menu,
wimp_menu_entry *menu_entry);
-static void ro_gui_menu_set_entry_shaded(wimp_menu *menu, menu_action action,
- bool shaded);
-static void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action,
- bool ticked);
static void ro_gui_menu_get_window_details(wimp_w w, struct gui_window **g,
struct browser_window **bw, hlcache_handle **h,
- struct toolbar **toolbar, struct tree **tree);
+ struct toolbar **toolbar,
+ bool *is_cookies, bool *is_hotlist, bool *is_global_history);
static int ro_gui_menu_get_checksum(void);
-static bool ro_gui_menu_prepare_url_suggest(void);
static void ro_gui_menu_prepare_pageinfo(struct gui_window *g);
static void ro_gui_menu_prepare_objectinfo(hlcache_handle *object,
const char *href);
@@ -143,12 +131,12 @@ static wimp_i current_menu_icon;
/** The height of the iconbar menu */
int iconbar_menu_height = 5 * 44;
/** The available menus */
-wimp_menu *iconbar_menu, *browser_menu, *hotlist_menu, *global_history_menu, *cookies_menu,
- *image_quality_menu, *browser_toolbar_menu,
- *tree_toolbar_menu, *proxy_type_menu, *languages_menu;
-/** URL suggestion menu */
-static wimp_MENU(GLOBAL_HISTORY_RECENT_URLS) url_suggest;
-wimp_menu *url_suggest_menu = (wimp_menu *)&url_suggest;
+wimp_menu *iconbar_menu, *browser_menu, *image_quality_menu,
+ *browser_toolbar_menu, *tree_toolbar_menu,
+ *proxy_type_menu, *languages_menu;
+
+static wimp_MENU(URL_SUGGEST_MAX_URLS) url_suggest_menu_block;
+wimp_menu *url_suggest_menu = (wimp_menu *) &url_suggest_menu_block;
/* the values given in PRM 3-157 for how to check menus/windows are
* incorrect so we use a hack of checking if the sub-menu has bit 0
@@ -277,94 +265,6 @@ void ro_gui_menu_init(void)
};
browser_menu = ro_gui_menu_define_menu(&browser_definition);
- /* hotlist menu */
- static wimp_w one = (wimp_w) 1;
- static const struct ns_menu hotlist_definition = {
- "Hotlist", {
- { "Hotlist", NO_ACTION, 0 },
- { "Hotlist.New", NO_ACTION, 0 },
- { "Hotlist.New.Folder", TREE_NEW_FOLDER, &dialog_folder },
- { "Hotlist.New.Link", TREE_NEW_LINK, &dialog_entry },
- { "_Hotlist.Export", HOTLIST_EXPORT, &dialog_saveas },
- { "Hotlist.Expand", TREE_EXPAND_ALL, 0 },
- { "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 },
- { "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
- { "Hotlist.Expand.Links", TREE_EXPAND_LINKS, 0 },
- { "Hotlist.Collapse", TREE_COLLAPSE_ALL, 0 },
- { "Hotlist.Collapse.All", TREE_COLLAPSE_ALL, 0 },
- { "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
- { "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
- { "Hotlist.Toolbars", NO_ACTION, 0 },
- { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
- { "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 },
- { "Selection", TREE_SELECTION, 0 },
- /* We want a window, but it changes depending upon
- * context. Therefore, ensure that the structure is
- * created so that we can dynamically modify the
- * actual item presented. We do this by creating a
- * fake wimp_w with the value 1, which indicates a
- * window handle as opposed to a submenu. */
- { "Selection.Edit", TREE_SELECTION_EDIT, &one },
- { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
- { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
- { "SelectAll", TREE_SELECT_ALL, 0 },
- { "Clear", TREE_CLEAR_SELECTION, 0 },
- {NULL, 0, 0}
- }
- };
- hotlist_menu = ro_gui_menu_define_menu(&hotlist_definition);
-
- /* history menu */
- static const struct ns_menu global_history_definition = {
- "History", {
- { "History", NO_ACTION, 0 },
- { "_History.Export", HISTORY_EXPORT, &dialog_saveas },
- { "History.Expand", TREE_EXPAND_ALL, 0 },
- { "History.Expand.All", TREE_EXPAND_ALL, 0 },
- { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
- { "History.Expand.Links", TREE_EXPAND_LINKS, 0 },
- { "History.Collapse", TREE_COLLAPSE_ALL, 0 },
- { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 },
- { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
- { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
- { "History.Toolbars", NO_ACTION, 0 },
- { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
- { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
- { "Selection", TREE_SELECTION, 0 },
- { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 },
- { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
- { "SelectAll", TREE_SELECT_ALL, 0 },
- { "Clear", TREE_CLEAR_SELECTION, 0 },
- {NULL, 0, 0}
- }
- };
- global_history_menu = ro_gui_menu_define_menu(
- &global_history_definition);
-
- /* history menu */
- static const struct ns_menu cookies_definition = {
- "Cookies", {
- { "Cookies", NO_ACTION, 0 },
- { "Cookies.Expand", TREE_EXPAND_ALL, 0 },
- { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 },
- { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 },
- { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 },
- { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 },
- { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 },
- { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 },
- { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 },
- { "Cookies.Toolbars", NO_ACTION, 0 },
- { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 },
- { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 },
- { "Selection", TREE_SELECTION, 0 },
- { "Selection.Delete", TREE_SELECTION_DELETE, 0 },
- { "SelectAll", TREE_SELECT_ALL, 0 },
- { "Clear", TREE_CLEAR_SELECTION, 0 },
- {NULL, 0, 0}
- }
- };
- cookies_menu = ro_gui_menu_define_menu(&cookies_definition);
-
/* image quality menu */
static const struct ns_menu images_definition = {
"Display", {
@@ -415,9 +315,7 @@ void ro_gui_menu_init(void)
proxy_type_menu = ro_gui_menu_define_menu(&proxy_type_definition);
/* special case menus */
- url_suggest_menu->title_data.indirected_text.text =
- (char *) messages_get("URLSuggest");
- ro_gui_menu_init_structure(url_suggest_menu, GLOBAL_HISTORY_RECENT_URLS);
+ ro_gui_url_suggest_init(url_suggest_menu);
/* Note: This table *must* be kept in sync with the LangNames file */
static const struct ns_menu lang_definition = {
@@ -540,7 +438,7 @@ void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w)
/* prepare the menu state */
if (menu == url_suggest_menu) {
- if (!ro_gui_menu_prepare_url_suggest())
+ if (!ro_gui_url_suggest_prepare_menu())
return;
} else if (menu == recent_search_menu) {
if (!ro_gui_search_prepare_menu())
@@ -618,8 +516,8 @@ void ro_gui_menu_closed(bool cleanup)
struct browser_window *bw;
hlcache_handle *h;
struct toolbar *t;
- struct tree *tree;
os_error *error;
+ bool is_cookies, is_hotlist, is_global_history;
if (current_menu) {
@@ -630,15 +528,16 @@ void ro_gui_menu_closed(bool cleanup)
warn_user("MenuError", error->errmess);
}
ro_gui_menu_get_window_details(current_menu_window,
- &g, &bw, &h, &t, &tree);
- current_menu = NULL;
+ &g, &bw, &h, &t,
+ &is_cookies, &is_hotlist,
+ &is_global_history);
if (cleanup) {
- ro_gui_wimp_event_menus_closed();
-
- if (tree)
- ro_gui_tree_menu_closed(tree);
+ ro_gui_wimp_event_menus_closed(current_menu_window,
+ current_menu_icon, current_menu);
}
+
+ current_menu = NULL;
}
current_menu_window = NULL;
@@ -668,15 +567,16 @@ void ro_gui_menu_objects_moved(void)
*/
void ro_gui_menu_selection(wimp_selection *selection)
{
- int i, j;
- wimp_menu_entry *menu_entry;
- menu_action action;
- wimp_pointer pointer;
- struct gui_window *g = NULL;
- wimp_menu *menu;
- os_error *error;
- int previous_menu_icon = current_menu_icon;
- char *url;
+ int i, j;
+ bool needs_prepare;
+ wimp_menu_entry *menu_entry;
+ menu_action action;
+ wimp_pointer pointer;
+ struct gui_window *g = NULL;
+ wimp_menu *menu;
+ os_error *error;
+ int previous_menu_icon = current_menu_icon;
+ char *url;
/* if we are using gui_multitask then menu selection events
* may be delivered after the menu has been closed. As such,
@@ -686,41 +586,58 @@ void ro_gui_menu_selection(wimp_selection *selection)
assert(current_menu_window);
- /* get the menu entry and associated action */
+ /* get the menu entry and associated action and definition */
menu_entry = &current_menu->entries[selection->items[0]];
for (i = 1; selection->items[i] != -1; i++)
menu_entry = &menu_entry->sub_menu->
entries[selection->items[i]];
action = ro_gui_menu_find_action(current_menu, menu_entry);
- /* perform menu action */
- if (action != NO_ACTION)
- ro_gui_menu_handle_action(current_menu_window, action, false);
-
- /* perform non-automated actions */
- if (current_menu == url_suggest_menu) {
- g = ro_gui_toolbar_lookup(current_menu_window);
- if (g) {
- url = url_suggest_menu->entries[selection->items[0]].
- data.indirected_text.text;
- gui_window_set_url(g, url);
- browser_window_go(g->bw, url, 0, true);
- global_history_add_recent(url);
- }
- } else if (current_menu == gui_form_select_menu) {
- g = ro_gui_window_lookup(current_menu_window);
- assert(g);
-
- if (selection->items[0] >= 0) {
- form_select_process_selection(g->bw->current_content,
- gui_form_select_control,
- selection->items[0]);
+ /* Deal with the menu action. We first pass it to Wimp_Event to
+ * handle any automatic menus. If this doesn't recognise the details,
+ * it is passed on to the code in menus.c.
+ */
+
+ needs_prepare = false;
+
+ if (!ro_gui_wimp_event_menu_selection(current_menu_window,
+ current_menu_icon, current_menu, selection, action)) {
+
+ /* perform menu action */
+ if (action != NO_ACTION)
+ ro_gui_menu_handle_action(current_menu_window,
+ action, false);
+
+ /* perform non-automated actions */
+ if (current_menu == url_suggest_menu) {
+ g = ro_gui_toolbar_lookup(current_menu_window);
+ if (g) {
+ url = url_suggest_menu->entries[selection->items[0]].
+ data.indirected_text.text;
+ gui_window_set_url(g, url);
+ browser_window_go(g->bw, url, 0, true);
+ }
+ } else if (current_menu == gui_form_select_menu) {
+ g = ro_gui_window_lookup(current_menu_window);
+ assert(g);
+
+ if (selection->items[0] >= 0) {
+ form_select_process_selection(g->bw->current_content,
+ gui_form_select_control,
+ selection->items[0]);
+ }
}
- }
- /* allow automatic menus to have their data updated */
- ro_gui_wimp_event_menu_selection(current_menu_window, current_menu_icon,
- current_menu, selection);
+ /* allow automatic menus to have their data updated */
+// ro_gui_wimp_event_menu_selection(current_menu_window,
+// current_menu_icon, current_menu, selection);
+
+ /* Menus not handled by ro_gui_wimp_event_menu_selection()
+ * will need to be re-prepared before an adjust reopening.
+ */
+
+ needs_prepare = true;
+ }
/* re-open the menu for Adjust clicks */
error = xwimp_get_pointer_info(&pointer);
@@ -738,24 +655,26 @@ void ro_gui_menu_selection(wimp_selection *selection)
}
/* re-prepare all the visible entries */
- i = 0;
- menu = current_menu;
- do {
- j = 0;
+ if (needs_prepare) {
+ i = 0;
+ menu = current_menu;
do {
- action = ro_gui_menu_find_action(current_menu,
- &menu->entries[j]);
- if (action != NO_ACTION)
- ro_gui_menu_prepare_action(current_menu_window,
- action, false);
- } while (!(menu->entries[j++].menu_flags & wimp_MENU_LAST));
- j = selection->items[i++];
- if (j != -1) {
- menu = menu->entries[j].sub_menu;
- if ((!menu) || (menu == wimp_NO_SUB_MENU))
- break;
- }
- } while (j != -1);
+ j = 0;
+ do {
+ action = ro_gui_menu_find_action(current_menu,
+ &menu->entries[j]);
+ if (action != NO_ACTION)
+ ro_gui_menu_prepare_action(current_menu_window,
+ action, false);
+ } while (!(menu->entries[j++].menu_flags & wimp_MENU_LAST));
+ j = selection->items[i++];
+ if (j != -1) {
+ menu = menu->entries[j].sub_menu;
+ if ((!menu) || (menu == wimp_NO_SUB_MENU))
+ break;
+ }
+ } while (j != -1);
+ }
if (current_menu == gui_form_select_menu) {
assert(g); /* Keep scan-build happy */
@@ -788,28 +707,42 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning)
for (i = 1; warning->selection.items[i] != -1; i++)
menu_entry = &menu_entry->sub_menu->
entries[warning->selection.items[i]];
+ action = ro_gui_menu_find_action(current_menu, menu_entry);
- if (IS_MENU(menu_entry->sub_menu)) {
- ro_gui_wimp_event_register_submenu((wimp_w)0);
- sub_menu = menu_entry->sub_menu;
- i = 0;
- do {
- action = ro_gui_menu_find_action(current_menu,
- &sub_menu->entries[i]);
+ /* We only process the menu in the old way if the wimp_event module
+ * hasn't processed it for us.
+ */
+
+ if (!ro_gui_wimp_event_submenu_warning(current_menu_window,
+ current_menu_icon, current_menu, &(warning->selection),
+ action)) {
+ if (IS_MENU(menu_entry->sub_menu)) {
+ ro_gui_wimp_event_register_submenu((wimp_w)0);
+ sub_menu = menu_entry->sub_menu;
+ i = 0;
+ do {
+ action = ro_gui_menu_find_action(current_menu,
+ &sub_menu->entries[i]);
+ if (action != NO_ACTION)
+ ro_gui_menu_prepare_action(current_menu_window,
+ action, false);
+ } while (!(sub_menu->entries[i++].menu_flags &
+ wimp_MENU_LAST));
+ } else {
+ ro_gui_wimp_event_register_submenu((wimp_w)menu_entry->sub_menu);
+ action = ro_gui_menu_find_action(current_menu, menu_entry);
if (action != NO_ACTION)
ro_gui_menu_prepare_action(current_menu_window,
- action, false);
- } while (!(sub_menu->entries[i++].menu_flags & wimp_MENU_LAST));
- } else {
- ro_gui_wimp_event_register_submenu((wimp_w)menu_entry->sub_menu);
- action = ro_gui_menu_find_action(current_menu, menu_entry);
- if (action != NO_ACTION)
- ro_gui_menu_prepare_action(current_menu_window,
- action, true);
- /* remove the close icon */
+ action, true);
+ }
+ }
+
+ /* If this is a dialogue box, remove the close and back icons. */
+
+ if (!(IS_MENU(menu_entry->sub_menu)))
ro_gui_wimp_update_window_furniture((wimp_w)menu_entry->sub_menu,
wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_BACK_ICON, 0);
- }
+
/* open the sub-menu */
error = xwimp_create_sub_menu(menu_entry->sub_menu,
@@ -829,64 +762,44 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning)
*/
void ro_gui_menu_refresh_toolbar(struct toolbar *toolbar)
{
+// struct treeview_window *treeview_window;
assert(toolbar);
toolbar->reformat_buttons = true;
ro_gui_theme_process_toolbar(toolbar, -1);
if (toolbar->type == THEME_BROWSER_TOOLBAR) {
- gui_window_update_extent(ro_gui_window_lookup(current_menu_window));
- } else if (toolbar->type == THEME_HOTLIST_TOOLBAR) {
- tree_resized(hotlist_tree);
- xwimp_force_redraw((wimp_w)hotlist_tree->handle,
- 0,-16384, 16384, 16384);
- } else if (toolbar->type == THEME_HISTORY_TOOLBAR) {
- tree_resized(global_history_tree);
- xwimp_force_redraw((wimp_w)global_history_tree->handle,
- 0,-16384, 16384, 16384);
- } else if (toolbar->type == THEME_COOKIES_TOOLBAR) {
- tree_resized(cookies_tree);
- xwimp_force_redraw((wimp_w)cookies_tree->handle,
- 0,-16384, 16384, 16384);
+ gui_window_update_extent(ro_gui_window_lookup(
+ current_menu_window));
+// } else if (toolbar->type == THEME_HOTLIST_TOOLBAR) {
+// treeview_window = ro_gui_hotlist_get();
+// /* TODO: FIX THIS */
+// /* tree_resized(treeview_window->tree); */
+// xwimp_force_redraw(treeview_window->window,
+// 0,-16384, 16384, 16384);
+// } else if (toolbar->type == THEME_HISTORY_TOOLBAR) {
+// treeview_window = ro_gui_global_history_get();
+// /* TODO: FIX THIS */
+// /* tree_resized(treeview_window->tree); */
+// xwimp_force_redraw(treeview_window->window,
+// 0,-16384, 16384, 16384);
+// } else if (toolbar->type == THEME_COOKIES_TOOLBAR) {
+// treeview_window = ro_gui_cookies_get();
+// /* TODO: FIX THIS */
+// /* tree_resized(treeview_window->tree); */
+// xwimp_force_redraw(treeview_window->window,
+// 0,-16384, 16384, 16384);
}
}
/**
- * Builds the URL suggestion menu
- */
-bool ro_gui_menu_prepare_url_suggest(void) {
- char **suggest_text;
- int suggestions;
- int i;
-
- suggest_text = global_history_get_recent(&suggestions);
- if (suggestions < 1)
- return false;
-
- for (i = 0; i < suggestions; i++) {
- url_suggest_menu->entries[i].menu_flags = 0;
- url_suggest_menu->entries[i].data.indirected_text.text =
- suggest_text[i];
- url_suggest_menu->entries[i].data.indirected_text.size =
- strlen(suggest_text[i]) + 1;
- }
-
- url_suggest_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED;
- url_suggest_menu->entries[suggestions - 1].menu_flags |= wimp_MENU_LAST;
- return true;
-}
-
-
-/**
* Update navigate menu status and toolbar icons.
*
* /param gui the gui_window to update
*/
void ro_gui_prepare_navigate(struct gui_window *gui)
{
- int suggestions;
-
ro_gui_menu_prepare_action(