summaryrefslogtreecommitdiff
path: root/riscos/hotlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'riscos/hotlist.c')
-rw-r--r--riscos/hotlist.c2567
1 files changed, 245 insertions, 2322 deletions
diff --git a/riscos/hotlist.c b/riscos/hotlist.c
index 021c5c365..055b71190 100644
--- a/riscos/hotlist.c
+++ b/riscos/hotlist.c
@@ -11,6 +11,7 @@
#include <string.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <swis.h>
@@ -22,102 +23,20 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "netsurf/content/content.h"
+#include "netsurf/desktop/tree.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/theme.h"
#include "netsurf/riscos/tinct.h"
+#include "netsurf/riscos/treeview.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
#include "netsurf/utils/url.h"
-#define HOTLIST_EXPAND 0
-#define HOTLIST_COLLAPSE 1
-#define HOTLIST_ENTRY 2
-#define HOTLIST_LINE 3
-#define HOTLIST_TLINE 4
-#define HOTLIST_BLINE 5
-
-#define HOTLIST_TEXT_BUFFER 256
-
-#define HOTLIST_LEAF_INSET 32
-#define HOTLIST_ICON_WIDTH 36
-#define HOTLIST_LINE_HEIGHT 44
-#define HOTLIST_TEXT_PADDING 16
-
-struct hotlist_entry {
-
- /** The next hotlist entry at this level, or NULL for no more
- */
- struct hotlist_entry *next_entry;
-
- /** The child hotlist entry (NULL for no children).
- The children value must be set for this value to take effect.
- */
- struct hotlist_entry *child_entry;
-
- /** The hotlist entry that has this entry as its next entry
- */
- struct hotlist_entry *previous_entry;
-
- /** The hotlist entry that this is a child of
- */
- struct hotlist_entry *parent_entry;
-
- /** The number of children (-1 for non-folders, >=0 for folders)
- */
- int children;
-
- /** The title of the hotlist entry/folder, UTF-8.
- */
- char *title;
-
- /** The URL of the hotlist entry (NULL for folders)
- */
- char *url;
-
- /** Whether this entry is expanded
- */
- bool expanded;
-
- /** Whether this entry is selected
- */
- bool selected;
-
- /** The content filetype (not for folders)
- */
- int filetype;
-
- /** The number of visits
- */
- int visits;
-
- /** Add/last visit dates
- */
- time_t add_date;
- time_t last_date;
-
- /** Position on last reformat (relative to window origin)
- */
- int x0;
- int y0;
- int width;
- int height;
-
- /** Cached values
- */
- int collapsed_width;
- int expanded_width;
-
- /** The width of the various lines sub-text
- */
- int widths[4];
-
- /** Whether the item is awaiting processing
- */
- bool process;
-};
+static void ro_gui_hotlist_visited(struct content *content, struct tree *tree,
+ struct node *node);
/* A basic window for the toolbar and status
*/
@@ -129,7 +48,8 @@ static wimp_window hotlist_window_definition = {
wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON |
wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON |
wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_SIZE_ICON |
- wimp_WINDOW_VSCROLL,
+ wimp_WINDOW_VSCROLL | wimp_WINDOW_IGNORE_XEXTENT |
+ wimp_WINDOW_IGNORE_YEXTENT,
wimp_COLOUR_BLACK,
wimp_COLOUR_LIGHT_GREY,
wimp_COLOUR_LIGHT_GREY,
@@ -138,158 +58,42 @@ static wimp_window hotlist_window_definition = {
wimp_COLOUR_MID_LIGHT_GREY,
wimp_COLOUR_CREAM,
0,
- {0, -800, 16384, 0},
+ {0, -16384, 16384, 0},
wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
wimp_ICON_VCENTRED,
wimp_BUTTON_DOUBLE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT,
wimpspriteop_AREA,
1,
- 256,
+ 100,
{""},
- 0
+ 0,
+ {}
};
-/* An icon to plot text with
-*/
-static wimp_icon text_icon;
-static wimp_icon sprite_icon;
-
-/* Temporary workspace for plotting
-*/
-static char drag_name[12];
-static char icon_name[12];
-static char extended_text[HOTLIST_TEXT_BUFFER];
-
-/* Whether a reformat is pending
-*/
-static bool reformat_pending = false;
-static int max_width = 0;
-static int max_height = 0;
/* The hotlist window, toolbar and plot origins
*/
-wimp_w hotlist_window;
-struct toolbar *hotlist_toolbar = NULL;
-static int origin_x, origin_y;
-
-/* The current redraw rectangle
-*/
-static int clip_x0, clip_y0, clip_x1, clip_y1;
-
-/* The root entry
-*/
-static struct hotlist_entry root;
-
-/* The sprite header addresses for Tinct
-*/
-static char *sprite[6];
-
-/* The drag buttons
-*/
-bool dragging;
-wimp_mouse_state drag_buttons;
-
-/* Whether the current selection was from a menu click
-*/
-bool menu_selection = false;
-bool menu_open = false;
+static wimp_w hotlist_window;
+struct toolbar *hotlist_toolbar;
+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.
*/
-bool dialog_folder_add = false;
-bool dialog_entry_add = false;
-bool hotlist_insert = false;
-
+struct node *dialog_folder_node;
+struct node *dialog_entry_node;
-static bool ro_gui_hotlist_initialise_sprite(const char *name, int number);
-static bool ro_gui_hotlist_load(void);
-static void ro_gui_hotlist_load_file(const char *filename);
-static void ro_gui_hotlist_load_directory(xmlNode *ul,
- struct hotlist_entry *directory);
-static void ro_gui_hotlist_load_entry(xmlNode *li,
- struct hotlist_entry *directory);
-xmlNode *ro_gui_hotlist_find_element(xmlNode *node, const char *name);
-bool ro_gui_hotlist_save_directory(struct hotlist_entry *directory,
- xmlNode *node);
-bool ro_gui_hotlist_save_entry(struct hotlist_entry *entry,
- xmlNode *node);
-bool ro_gui_hotlist_save_entry_comment(xmlNode *node,
- const char *name, int value);
-static void ro_gui_hotlist_link_entry(struct hotlist_entry *link, struct hotlist_entry *entry, bool before);
-static void ro_gui_hotlist_delink_entry(struct hotlist_entry *entry);
-static void ro_gui_hotlist_delete_entry(struct hotlist_entry *entry, bool siblings);
-static void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry *entry);
-static int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, int y0);
-static int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, int y0);
-static struct hotlist_entry *ro_gui_hotlist_create_entry(const char *title, const char *url,
- int filetype, struct hotlist_entry *folder);
-static void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry);
-static struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_entry *entry);
-static int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, bool redraw);
-static void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry,
- int x0, int y0, int x1, int y1,
- bool toggle, bool redraw);
-static int ro_gui_hotlist_selection_count(struct hotlist_entry *entry, bool folders);
-static void ro_gui_hotlist_update_expansion(struct hotlist_entry *entry, bool only_selected,
- bool folders, bool links, bool expand, bool contract);
-static void ro_gui_hotlist_launch_selection(struct hotlist_entry *entry);
-static void ro_gui_hotlist_invalidate_statistics(struct hotlist_entry *entry);
-static struct hotlist_entry *ro_gui_hotlist_first_selection(struct hotlist_entry *entry);
-static void ro_gui_hotlist_selection_to_process(struct hotlist_entry *entry);
-static bool ro_gui_hotlist_move_processing(struct hotlist_entry *entry, struct hotlist_entry *destination, bool before);
-
-#define hotlist_ensure_sprite(buffer, fallback) if (xwimpspriteop_read_sprite_info(buffer, 0, 0, 0, 0)) sprintf(buffer, fallback)
-#define hotlist_redraw_entry(entry, full) xwimp_force_redraw(hotlist_window, full ? 0 : entry->x0, \
- full ? -16384 : entry->y0, full ? 16384 : entry->x0 + entry->expanded_width, entry->y0 + entry->height);
-#define hotlist_redraw_entry_title(entry) xwimp_force_redraw(hotlist_window, entry->x0, \
- entry->y0 + entry->height - HOTLIST_LINE_HEIGHT, entry->x0 + entry->width, entry->y0 + entry->height);
-
-
-
-void ro_gui_hotlist_init(void) {
+void ro_gui_hotlist_initialise(void) {
+ FILE *fp;
const char *title;
- os_box extent = {0, 0, 0, 0};
os_error *error;
-
- /* Set the initial root options
- */
- root.next_entry = NULL;
- root.child_entry = NULL;
- root.children = 0;
- root.expanded = true;
-
- /* Load the hotlist
- */
- if (!ro_gui_hotlist_load()) return;
-
- /* Get our sprite ids for faster plotting.
- */
- if (ro_gui_hotlist_initialise_sprite("expand", HOTLIST_EXPAND) ||
- ro_gui_hotlist_initialise_sprite("collapse", HOTLIST_COLLAPSE) ||
- ro_gui_hotlist_initialise_sprite("entry", HOTLIST_ENTRY) ||
- ro_gui_hotlist_initialise_sprite("line", HOTLIST_LINE) ||
- ro_gui_hotlist_initialise_sprite("halflinet", HOTLIST_TLINE) ||
- ro_gui_hotlist_initialise_sprite("halflineb", HOTLIST_BLINE)) {
- return;
- }
-
- /* Update our text icon
- */
- text_icon.data.indirected_text.validation = (char *) -1;
- text_icon.data.indirected_text.size = 256;
- sprite_icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED |
- wimp_ICON_HCENTRED | wimp_ICON_VCENTRED |
- (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
- (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
- sprite_icon.data.indirected_sprite.area = wimpspriteop_AREA;
- sprite_icon.data.indirected_text.size = 12;
+ struct node *node;
/* Create our window
*/
title = messages_get("Hotlist");
- hotlist_window_definition.title_data.indirected_text.text = title;
+ hotlist_window_definition.title_data.indirected_text.text = strdup(title);
hotlist_window_definition.title_data.indirected_text.validation =
(char *) -1;
hotlist_window_definition.title_data.indirected_text.size = strlen(title);
@@ -299,47 +103,70 @@ void ro_gui_hotlist_init(void) {
error->errnum, error->errmess));
die(error->errmess);
}
+
+ /* Either load or create a hotlist
+ */
+ fp = fopen("Choices:WWW.NetSurf.Hotlist", "r");
+ if (!fp) {
+ 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;
+ }
+ hotlist_tree->root->expanded = true;
+ node = tree_create_folder_node(hotlist_tree->root, "NetSurf");
+ if (!node)
+ node = hotlist_tree->root;
+ tree_create_URL_node(node, messages_get("HotlistHomepage"),
+ "http://netsurf.sourceforge.net/", 0xfaf,
+ time(NULL), -1, 0);
+ tree_create_URL_node(node, messages_get("HotlistTestBuild"),
+ "http://netsurf.strcprstskrzkrk.co.uk/", 0xfaf,
+ time(NULL), -1, 0);
+ tree_initialise(hotlist_tree);
+ } else {
+ fclose(fp);
+ hotlist_tree = options_load_hotlist("Choices:WWW.NetSurf.Hotlist");
+ }
+ if (!hotlist_tree) return;
+ hotlist_tree->handle = (int)hotlist_window;
/* Create our toolbar
*/
hotlist_toolbar = ro_gui_theme_create_toolbar(NULL, THEME_HOTLIST_TOOLBAR);
- ro_gui_theme_attach_toolbar(hotlist_toolbar, hotlist_window);
-
- /* Update the extent
- */
if (hotlist_toolbar) {
- extent.x1 = 16384;
- extent.y1 = hotlist_toolbar->height;
- extent.y0 = -16384;
- error = xwimp_set_extent(hotlist_window, &extent);
- if (error) {
- LOG(("xwimp_set_extent: 0x%x: %s",
- error->errnum, error->errmess));
- die(error->errmess);
- }
- reformat_pending = true;
- }
+ ro_gui_theme_attach_toolbar(hotlist_toolbar, hotlist_window);
+ hotlist_tree->offset_y = hotlist_toolbar->height;
+ }
}
+
/**
- * Initialise a hotlist sprite for use with Tinct
- *
- * \param name the name of the sprite
- * \param number the sprite cache number
- * \return whether an error occurred
+ * Perform a save to the default file
*/
-bool ro_gui_hotlist_initialise_sprite(const char *name, int number) {
- os_error *error;
- sprintf(icon_name, "tr_%s", name);
- error = xosspriteop_select_sprite(osspriteop_USER_AREA, gui_sprites,
- (osspriteop_id)icon_name,
- (osspriteop_header **)&sprite[number]);
- if (error) {
- warn_user("MiscError", error->errmess);
- LOG(("Failed to load hotlist sprite 'tr_%s'", name));
- return true;
- }
- return false;
+void ro_gui_hotlist_save(void) {
+ os_error *error;
+
+ if (!hotlist_tree) return;
+
+ /* Ensure we have a directory to save to later.
+ */
+ xosfile_create_dir("<Choices$Write>.WWW", 0);
+ xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
+
+ /* Save to our file
+ */
+ options_save_hotlist(hotlist_tree, "<Choices$Write>.WWW.NetSurf.Hotlist");
+ error = xosfile_set_type("<Choices$Write>.WWW.NetSurf.Hotlist", 0xfaf);
+ if (error)
+ LOG(("xosfile_set_type: 0x%x: %s",
+ error->errnum, error->errmess));
}
@@ -355,7 +182,7 @@ void ro_gui_hotlist_show(void) {
/* We may have failed to initialise
*/
- if (!hotlist_window) return;
+ if (!hotlist_tree) return;
/* Get the window state
*/
@@ -370,10 +197,16 @@ void ro_gui_hotlist_show(void) {
open in the centre of the screen.
*/
if (!(state.flags & wimp_WINDOW_OPEN)) {
- /* Clear the selection/expansion states
- */
- ro_gui_hotlist_update_expansion(root.child_entry, false, true, true, false, true);
- ro_gui_hotlist_selection_state(root.child_entry, false, false);
+
+ /* Cancel any editing
+ */
+ ro_gui_tree_stop_edit(hotlist_tree);
+
+ /* Set the default state
+ */
+ if (hotlist_tree->root->child)
+ tree_handle_node_changed(hotlist_tree, hotlist_tree->root,
+ false, true);
/* Get the current screen size
*/
@@ -381,11 +214,11 @@ void ro_gui_hotlist_show(void) {
/* Move to the centre
*/
- dimension = state.visible.x1 - state.visible.x0;
+ dimension = 600; /*state.visible.x1 - state.visible.x0;*/
scroll_width = ro_get_vscroll_width(hotlist_window);
state.visible.x0 = (screen_width - (dimension + scroll_width)) / 2;
state.visible.x1 = state.visible.x0 + dimension;
- dimension = state.visible.y1 - state.visible.y0;
+ dimension = 800; /*state.visible.y1 - state.visible.y0;*/
state.visible.y0 = (screen_height - dimension) / 2;
state.visible.y1 = state.visible.y0 + dimension;
state.xscroll = 0;
@@ -397,2109 +230,228 @@ void ro_gui_hotlist_show(void) {
*/
ro_gui_menu_prepare_hotlist();
state.next = wimp_TOP;
- error = xwimp_open_window((wimp_open*)&state);
- if (error) {
- warn_user("WimpError", error->errmess);
- return;
- }
+ ro_gui_tree_open((wimp_open*)&state, hotlist_tree);
/* Set the caret position
*/
- xwimp_set_caret_position(state.w, -1, -100,
- -100, 32, -1);
-}
-
-
-bool ro_gui_hotlist_load(void) {
- fileswitch_object_type obj_type = 0;
- struct hotlist_entry *netsurf;
- struct hotlist_entry *entry;
-
- /* Check if we have an initial hotlist. OS_File does funny things relating to errors,
- so we use the object type to determine success
- */
- xosfile_read_stamped_no_path("Choices:WWW.NetSurf.Hotlist", &obj_type,
- (bits)0, (bits)0, (int *)0, (fileswitch_attr)0, (bits)0);
- if (obj_type == fileswitch_IS_FILE) {
- ro_gui_hotlist_load_file("Choices:WWW.NetSurf.Hotlist");
- return true;
-
- } else {
- /* Create a folder
- */
- netsurf = ro_gui_hotlist_create_entry("NetSurf", NULL, 0, &root);
- if (!netsurf)
- return false;
-
- /* Add some content
- */
- entry = ro_gui_hotlist_create_entry("NetSurf homepage",
- "http://netsurf.sourceforge.net/",
- 0xfaf, netsurf);
- if (!entry)
- return false;
- entry->add_date = (time_t) -1;
- entry = ro_gui_hotlist_create_entry("NetSurf test builds",
- "http://netsurf.strcprstskrzkrk.co.uk/",
- 0xfaf, netsurf);
- if (!entry)
- return false;
- entry->add_date = (time_t) -1;
-
- /* We succeeded
- */
- return true;
- }
-}
-
-
-/**
- * Load the hotlist from file.
- *
- * \param filename name of file to read
- */
-
-void ro_gui_hotlist_load_file(const char *filename)
-{
- xmlDoc *doc;
- xmlNode *html, *body, *ul;
-
- doc = htmlParseFile(filename, "iso-8859-1");
- if (!doc) {
- warn_user("HotlistLoadError", messages_get("ParsingFail"));
- return;
- }
-
- html = ro_gui_hotlist_find_element((xmlNode *) doc, "html");
- body = ro_gui_hotlist_find_element(html, "body");
- ul = ro_gui_hotlist_find_element(body, "ul");
- if (!ul) {
- xmlFreeDoc(doc);
- warn_user("HotlistLoadError",
- "(<html>...<body>...<ul> not found.)");
- return;
- }
-
- ro_gui_hotlist_load_directory(ul, &root);
-
- xmlFreeDoc(doc);
-}
-
-
-/**
- * Parse a directory represented as a ul.
- *
- * \param ul xmlNode for parsed ul
- * \param directory directory to add this directory to
- */
-
-void ro_gui_hotlist_load_directory(xmlNode *ul,
- struct hotlist_entry *directory)
-{
- char *title;
- struct hotlist_entry *dir;
- xmlNode *n;
-
- 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(n->name, "li") == 0) {
- /* entry */
- ro_gui_hotlist_load_entry(n, directory);
-
- } else if (strcmp(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(n->name, "ul") != 0) {
- /* next element isn't expected ul */
- free(title);
- warn_user("HotlistLoadError", "(Expected "
- "<ul> not present.)");
- return;
- }
-
- dir = ro_gui_hotlist_create_entry(title, NULL, 0,
- directory);
- if (!dir)
- return;
- ro_gui_hotlist_load_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 ro_gui_hotlist_load_entry(xmlNode *li,
- struct hotlist_entry *directory)
-{
- char *url = 0;
- char *title = 0;
- int filetype = 0xfaf;
- int add_date = -1;
- int last_date = -1;
- int visits = 0;
- char *comment;
- struct hotlist_entry *entry;
- xmlNode *n;
-
- for (n = li->children; n; n = n->next) {
- /* The li must contain an "a" element, and may contain
- * some additional data as comments. */
-
- if (n->type == XML_ELEMENT_NODE &&
- strcmp(n->name, "a") == 0) {
- url = (char *) xmlGetProp(n, (const xmlChar *) "href");
- title = (char *) xmlNodeGetContent(n);
-
- } else if (n->type == XML_COMMENT_NODE) {
- comment = (char *) xmlNodeGetContent(n);
- if (!comment)
- continue;
- if (strncmp("Type:", comment, 5) == 0)
- filetype = atoi(comment + 5);
- else if (strncmp("Added:", comment, 6) == 0)
- add_date = atoi(comment + 6);
- else if (strncmp("LastVisit:", comment, 10) == 0)
- last_date = atoi(comment + 10);
- else if (strncmp("Visits:", comment, 7) == 0)
- visits = atoi(comment + 7);
- }
- }
-
- if (!url || !title) {
- warn_user("HotlistLoadError", "(Missing <a> in <li> or "
- "memory exhausted.)");
- return;
- }
-
- entry = ro_gui_hotlist_create_entry(title, url, filetype, directory);
- if (!entry)
- return;
- entry->add_date = add_date;
- entry->last_date = last_date;
- entry->visits = visits;
-}
-
-
-/**
- * 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 *ro_gui_hotlist_find_element(xmlNode *node, const char *name)
-{
- xmlNode *n;
- if (!node)
- return 0;
- for (n = node->children;
- n && !(n->type == XML_ELEMENT_NODE &&
- strcmp(n->name, name) == 0);
- n = n->next)
- ;
- return n;
-}
-
-
-/**
- * Perform a save to the default file
- */
-
-void ro_gui_hotlist_save(void) {
- /* Don't save if we didn't load
- */
- if (!hotlist_window) return;
-
- /* Ensure we have a directory to save to later.
- */
- xosfile_create_dir("<Choices$Write>.WWW", 0);
- xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
-
- /* Save to our file
- */
- ro_gui_hotlist_save_as("<Choices$Write>.WWW.NetSurf.Hotlist");
-}
-
-
-/**
- * Perform a save to a specified file
- *
- * /param filename the file to save to
- */
-
-void ro_gui_hotlist_save_as(const char *filename)
-{
- int res;
- xmlDoc *doc;
- xmlNode *html, *head, *title, *body;
-
- /* Unfortunately the Browse Hotlist format is invalid HTML,
- * so this is a lie. */
- doc = htmlNewDoc("http://www.w3.org/TR/html4/strict.dtd",
- "-//W3C//DTD HTML 4.01//EN");
- if (!doc) {
- warn_user("NoMemory", 0);
- return;
- }
-
- html = xmlNewNode(NULL, "html");
- if (!html) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return;
- }
- xmlDocSetRootElement(doc, html);
-
- head = xmlNewChild(html, NULL, "head", NULL);
- if (!head) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return;
- }
-
- title = xmlNewTextChild(head, NULL, "title", "NetSurf Hotlist");
- if (!title) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return;
- }
-
- body = xmlNewChild(html, NULL, "body", NULL);
- if (!body) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return;
- }
-
- if (!ro_gui_hotlist_save_directory(&root, body)) {
- warn_user("NoMemory", 0);
- xmlFreeDoc(doc);
- return;
- }
-
- doc->charset = XML_CHAR_ENCODING_UTF8;
- res = htmlSaveFileEnc(filename, doc, "iso-8859-1");
- if (res == -1) {
- warn_user("HotlistSaveError", 0);
- xmlFreeDoc(doc);
- return;
- }
-
- xmlFreeDoc(doc);
-
- xosfile_set_type(filename, 0xfaf);
-}
-
-
-/**
- * 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 ro_gui_hotlist_save_directory(struct hotlist_entry *directory,
- xmlNode *node)
-{
- struct hotlist_entry *child;
- xmlNode *ul, *h4;
-
- ul = xmlNewChild(node, NULL, "ul", NULL);
- if (!ul)
- return false;
-
- for (child = directory->child_entry; child; child = child->next_entry) {
- if (child->url) {
- /* entry */
- if (!ro_gui_hotlist_save_entry(child, ul))
- return false;
-
- } else {
- /* directory */
- /* invalid HTML */
- h4 = xmlNewTextChild(ul, NULL, "h4", child->title);
- if (!h4)
- return false;
-
- if (!ro_gui_hotlist_save_directory(child, ul))
- return false;
- }
- }
-
- return true;
-}
-
-
-/**
- * Add an entry to the HTML tree for saving.
- *
- * \param entry hotlist entry to add
- * \param node node to add li to
- * \return true on success, false on memory exhaustion
- */
-
-bool ro_gui_hotlist_save_entry(struct hotlist_entry *entry,
- xmlNode *node)
-{
- xmlNode *li, *a;
- xmlAttr *href;
-
- li = xmlNewChild(node, NULL, "li", NULL);
- if (!li)
- return false;
-
- a = xmlNewTextChild(li, NULL, "a", entry->title);
- if (!a)
- return false;
-
- href = xmlNewProp(a, "href", entry->url);
- if (!href)
- return false;
-
- if (entry->filetype != 0xfaf)
- if (!ro_gui_hotlist_save_entry_comment(li,
- "Type", entry->filetype))
- return false;
-
- if (entry->add_date != -1)
- if (!ro_gui_hotlist_save_entry_comment(li,
- "Added", entry->add_date))
- return false;
-
- if (entry->last_date != -1)
- if (!ro_gui_hotlist_save_entry_comment(li,
- "LastVisit", entry->last_date))
- return false;
-
- if (entry->visits != 0)
- if (!ro_gui_hotlist_save_entry_comment(li,
- "Visits", entry->visits))
- return false;
-
- return true;
-}
-
-
-/**
- * Add a special comment node to the HTML tree for saving.
- *
- * \param node node to add comment to
- * \param name name of special comment
- * \param value value of special comment
- * \return true on success, false on memory exhaustion
- */
-
-bool ro_gui_hotlist_save_entry_comment(xmlNode *node,
- const char *name, int value)
-{
- char s[40];
- xmlNode *comment;
-
- snprintf(s, sizeof s, "%s:%i", name, value);
- s[sizeof s - 1] = 0;
-
- comment = xmlNewComment(s);
- if (!comment)
- return false;
- if (!xmlAddChild(node, comment)) {
- xmlFreeNode(comment);
- return false;
- }
-
- return true;
-}
-
-
-/**
- * Adds a hotlist entry to the root of the tree.
- *
- * \param title the entry title
- * \param content the content to add
- */
-void ro_gui_hotlist_add(char *title, struct content *content) {
- ro_gui_hotlist_create_entry(title, content->url, ro_content_filetype(content), &root);
-}
-
-
-/**
- * Informs the hotlist that some content has been visited
- *
- * \param content the content visited
- */
-void hotlist_visited(struct content *content) {
- if ((!content) || (!content->url)) return;
- ro_gui_hotlist_visited_update(content, root.child_entry);
-}
-
-
-/**
- * Informs the hotlist that some content has been visited (internal)
- *
- * \param content the content visited
- * \param entry the entry to check siblings and children of
- */
-void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry *entry) {
- char *url;
- bool full = false;
-
- /* Update the hotlist
- */
- url = content->url;
- while (entry) {
- if ((entry->url) && (strcmp(url, entry->url) == 0)) {
- /* Check if we're going to need a full redraw downwards
- */
- full = ((entry->visits == 0) || (entry->last_date == -1));
-
- /* Update our values
- */
- if (entry->children == -1) entry->filetype = ro_content_filetype(content);
- entry->visits++;
- entry->last_date = time(NULL);
- ro_gui_hotlist_update_entry_size(entry);
-
- /* Redraw the least we can get away with
- */
- if (entry->expanded) hotlist_redraw_entry(entry, full);
- }
- if (entry->child_entry) ro_gui_hotlist_visited_update(content, entry->child_entry);
- entry = entry->next_entry;
- }
-}
-
-
-/**
- * Adds a hotlist entry to a folder of the tree.
- *
- * \param title the entry title (copied)
- * \param url the entry url (NULL to create a folder) (copied)
- * \param filetype filetype of entry
- * \param folder the folder to add the entry into
- * \return the new entry, or NULL on error and error reported
- */
-struct hotlist_entry *ro_gui_hotlist_create_entry(const char *title,
- const char *url, int filetype,
- struct hotlist_entry *folder) {
- struct hotlist_entry *entry;
- url_func_result res;
-
- /* Check we have a title or a URL
- */
- if (!title && !url) return NULL;
-
- /* Allocate some memory
- */
- entry = (struct hotlist_entry *)calloc(1, sizeof(struct hotlist_entry));
- if (!entry) {
- warn_user("NoMemory", 0);
- return NULL;
- }
-
- /* Normalise the URL and add the title if we have one, or
- use the URL instead
- */
- entry->url = 0;
- if ((url) && ((res = url_normalize(url, &entry->url)) != URL_FUNC_OK)) {
- /** \todo use correct error message */
- warn_user("NoMemory", 0);
- free(entry->url);
- free(entry);
- return NULL;
- }
- if (title) {
- entry->title = squash_whitespace(title);
- if (!entry->title) {
- warn_user("NoMemory", 0);
- free(entry->url);
- free(entry);
- return NULL;
- }
- entry->title = strip(entry->title);
- } else {
- entry->title = strdup(entry->url);
- if (!entry->title) {
- warn_user("NoMemory", 0);
- free(entry->url);
- free(entry);
- return NULL;
- }
- }
-
- /* Set the other values
- */
- entry->children = (url == NULL) ? 0 : -1;
- entry->filetype = filetype;
- entry->visits = 0;
- entry->add_date = time(NULL);
- entry->last_date = (time_t)-1;
- ro_gui_hotlist_update_entry_size(entry);
-
- /* Link into the tree
- */
- ro_gui_hotlist_link_entry(folder, entry, false);
- return entry;
-}
-
-
-/**
- * Links a hotlist entry into the tree.
- *
- * \param link the entry to link as a child (folders) or before/after (link)
- * \param entry the entry to link
- * \param before whether to link siblings before or after the supplied link
- */
-void ro_gui_hotlist_link_entry(struct hotlist_entry *link, struct hotlist_entry *entry, bool before) {
- struct hotlist_entry *link_entry;
-
- if ((!link || !entry) || (link == entry)) return;
-
- /* Check if the parent is a folder or an entry
- */
- if (link->children == -1) {
- entry->parent_entry = link->parent_entry;
- entry->parent_entry->children++;
- if (before) {
- entry->next_entry = link;
- entry->previous_entry = link->previous_entry;
- if (link->previous_entry) link->previous_entry->next_entry = entry;
- link->previous_entry = entry;
- if (link->parent_entry) {
- if (link->parent_entry->child_entry == link) {
- link->parent_entry->child_entry = entry;
- }
- }
- } else {
- entry->previous_entry = link;
- entry->next_entry = link->next_entry;
- if (link->next_entry) link->next_entry->previous_entry = entry;
- link->next_entry = entry;
- }
- } else {
- link_entry = link->child_entry;
-
- /* Link into the tree as a child at the end
- */
- if (!link_entry) {
- link->child_entry = entry;
- entry->previous_entry = NULL;
- } else {
- while (link_entry->next_entry) link_entry = link_entry->next_entry;
- link_entry->next_entry = entry;
- entry->previous_entry = link_entry;
- }
-
- /* Update the links
- */
- entry->parent_entry = link;
- entry->next_entry = NULL;
-
- /* Increment the number of children
- */
- link->children += 1;
- }
-
- /* Force a redraw
- */
- reformat_pending = true;
- xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 0);
-}
-
-
-/**
- * De-links a hotlist entry from the tree.
- *
- * \param entry the entry to de-link
- */
-void ro_gui_hotlist_delink_entry(struct hotlist_entry *entry) {
- if (!entry) return;
-
- /* Sort out if the entry was the initial child reference
- */
- if (entry->parent_entry) {
- entry->parent_entry->children -= 1;
- if (entry->parent_entry->children == 0) entry->parent_entry->expanded = false;
- if (entry->parent_entry->child_entry == entry) {
- entry->parent_entry->child_entry = entry->next_entry;
- }
- entry->parent_entry = NULL;
- }
-
- /* Remove the entry from siblings
- */
- if (entry->previous_entry) {
- entry->previous_entry->next_entry = entry->next_entry;
- }
- if (entry->next_entry) {
- entry->next_entry->previous_entry = entry->previous_entry;
- }
- entry->previous_entry = NULL;
- entry->next_entry = NULL;
-
- /* Force a redraw
- */
- reformat_pending = true;
- xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 0);
-}
-
-
-/**
- * Delete an entry and all children
- * This function also performs any necessary delinking
- *
- * \param entry the entry to delete
- * \param siblings delete all following siblings
- */
-void ro_gui_hotlist_delete_entry(struct hotlist_entry *entry, bool siblings) {
- struct hotlist_entry *next_entry = NULL;
- while (entry) {
-
- /* Recurse to children first
- */
- if (entry->child_entry) ro_gui_hotlist_delete_entry(entry->child_entry, true);
-
- /* Free our memory
- */
- free(entry->url);
- free(entry->title);
-
- /* Get the next entry before we de-link and delete
- */
- if (siblings) next_entry = entry->next_entry;
-
- /* Delink and delete our entry and move on
- */
- ro_gui_hotlist_delink_entry(entry);
- free(entry);
- entry = next_entry;
- }
-}
-
-
-/**
- * Updates and entrys size
- */
-void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) {
- int width;
- int max_width;
- int line_number = 0;
-
- /* Get the width of the title
- */
- xwimptextop_string_width(entry->title,
- strlen(entry->title) > 256 ? 256 : strlen(entry->title),
- &width);
- entry->collapsed_width = width;
- max_width = width;
-
- /* Get the width of the URL
- */
- if (entry->url) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistURL"), entry->url);
- if (strlen(extended_text) >= 255) {
- extended_text[252] = '.';
- extended_text[253] = '.';
- extended_text[254] = '.';
- extended_text[255] = '\0';
- }
- xwimptextop_string_width(extended_text,
- strlen(extended_text) > 256 ? 256 : strlen(extended_text),
- &width);
- if (width > max_width) max_width = width;
- entry->widths[line_number++] = width;
- }
-
- /* Get the width of the add date
- */
- if (entry->add_date != -1) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistAdded"), ctime(&entry->add_date));
- xwimptextop_string_width(extended_text,
- strlen(extended_text) > 256 ? 256 : strlen(extended_text),
- &width);
- if (width > max_width) max_width = width;
- entry->widths[line_number++] = width;
- }
-
- /* Get the width of the last visit
- */
- if (entry->last_date != -1) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistLast"), ctime(&entry->last_date));
- xwimptextop_string_width(extended_text,
- strlen(extended_text) > 256 ? 256 : strlen(extended_text),
- &width);
- if (width > max_width) max_width = width;
- entry->widths[line_number++] = width;
- }
-
- /* Get the width of the visit count
- */
- if (entry->visits > 0) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistVisits"), entry->visits);
- xwimptextop_string_width(extended_text,
- strlen(extended_text) > 256 ? 256 : strlen(extended_text),
- &width);
- if (width > max_width) max_width = width;
- entry->widths[line_number++] = width;
- }
-
- /* Increase the text width by the borders
- */
- entry->expanded_width = max_width + HOTLIST_LEAF_INSET + HOTLIST_ICON_WIDTH + HOTLIST_TEXT_PADDING;
- entry->collapsed_width += HOTLIST_LEAF_INSET + HOTLIST_ICON_WIDTH + HOTLIST_TEXT_PADDING;
- reformat_pending = true;
-}
-
-
-/**
- * Redraws a section of the hotlist window
- *
- * \param redraw the area to redraw
- */
-void ro_gui_hotlist_redraw(wimp_draw *redraw) {
- wimp_window_state state;
- osbool more;
- os_box extent = {0, 0, 0, 0};;
-
- /* Reset our min/max sizes
- */
- max_width = 0;
- max_height = 0;
-
- /* Redraw each rectangle
- */
- more = wimp_redraw_window(redraw);
- while (more) {
- clip_x0 = redraw->clip.x0;
- clip_y0 = redraw->clip.y0;
- clip_x1 = redraw->clip.x1;
- clip_y1 = redraw->clip.y1;
- origin_x = redraw->box.x0 - redraw->xscroll;
- origin_y = redraw->box.y1 - redraw->yscroll;
- ro_gui_hotlist_redraw_tree(root.child_entry, 0,
- origin_x + 8, origin_y - 4);
- more = wimp_get_rectangle(redraw);
- }
-
- /* Check if we should reformat
- */
- if (reformat_pending) {
- max_width += 8;
- max_height -= 4;
- if (max_width < 600) max_width = 600;
- if (max_height > -800) max_height = -800;
- extent.x1 = max_width;
- extent.y0 = max_height;
- if (hotlist_toolbar) {
- extent.y1 += hotlist_toolbar->height;
- }
- xwimp_set_extent(hotlist_window, &extent);
- state.w = hotlist_window;
- wimp_get_window_state(&state);
- wimp_open_window((wimp_open *) &state);
- reformat_pending = false;
- }
-}
-
-
-/**
- * Redraws a section of the hotlist window (non-WIMP interface)
- *
- * \param entry the entry to draw descendants and siblings of
- * \param level the tree level of the entry
- * \param x0 the x co-ordinate to plot from
- * \param y0 the y co-ordinate to plot from
- * \returns the height of the tree
- */
-int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, int y0) {
- bool first = true;
- int cumulative = 0;
- int height = 0;
- int box_y0;
-
- if (!entry) return 0;
-
- /* Repeatedly draw our entries
- */
- while (entry) {
-
- /* Redraw the item
- */
- height = ro_gui_hotlist_redraw_item(entry, level, x0 + HOTLIST_LEAF_INSET, y0);
- box_y0 = y0;
- cumulative += height;
-
- /* Update the entry position
- */
- if (entry->children == -1) {
- entry->height = height;
- } else {
- entry->height = HOTLIST_LINE_HEIGHT;
- }
- entry->x0 = x0 - origin_x;
- entry->y0 = y0 - origin_y - entry->height;
- if (entry->expanded) {
- entry->width = entry->expanded_width;
- } else {
- entry->width = entry->collapsed_width;
- }
-
- /* Get the maximum extents
- */
- if ((x0 + entry->width) > (max_width + origin_x))
- max_width = x0 + entry->width - origin_x;
- if ((y0 - height) < (max_height + origin_y))
- max_height = y0 - height - origin_y;
-
- /* Draw the vertical links
- */
- if (entry->next_entry) {
- /* Draw a half-line for the first entry in the top tree
- */
- if (first && (level == 0)) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_BLINE], x0 + 8, y0 - HOTLIST_LINE_HEIGHT,
- tinct_BILINEAR_FILTER);
- y0 -= HOTLIST_LINE_HEIGHT;
- height -= HOTLIST_LINE_HEIGHT;
- }
-
- /* Draw the rest of the lines
- */
- while (height > 0) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_LINE], x0 + 8, y0 - HOTLIST_LINE_HEIGHT,
- tinct_BILINEAR_FILTER);
- y0 -= HOTLIST_LINE_HEIGHT;
- height -= HOTLIST_LINE_HEIGHT;
- }
-
- } else {
- /* Draw a half-line for the last entry
- */
- if (!first || (level != 0)) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_TLINE], x0 + 8, y0 - 22,
- tinct_BILINEAR_FILTER);
- height -= HOTLIST_LINE_HEIGHT;
- y0 -= HOTLIST_LINE_HEIGHT;
- }
- }
-
- /* Draw the expansion type
- */
- if (entry->children == 0) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_ENTRY], x0, box_y0 - 23,
- tinct_BILINEAR_FILTER);
- } else {
- if (entry->expanded) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_COLLAPSE], x0, box_y0 - 31,
- tinct_BILINEAR_FILTER);
- } else {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_EXPAND], x0, box_y0 - 31,
- tinct_BILINEAR_FILTER);
- }
- }
-
- /* Move to the next entry
- */
- entry = entry->next_entry;
- first = false;
- }
-
- /* Return our height
- */
- return cumulative;
-}
-
-
-/**
- * Redraws an entry in the tree and any children
- *
- * \param entry the entry to redraw
- * \param level the level of the entry
- * \param x0 the x co-ordinate to plot at
- * \param y0 the y co-ordinate to plot at
- * \return the height of the entry
- */
-int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, int y0) {
- int height = HOTLIST_LINE_HEIGHT;
- int line_y0;
- int line_height;
-
- /* Set the correct height
- */
- if ((entry->children == -1) && (entry->expanded)) {
- if (entry->url) height += HOTLIST_LINE_HEIGHT;
- if (entry->visits > 0) height += HOTLIST_LINE_HEIGHT;
- if (entry->add_date != -1) height += HOTLIST_LINE_HEIGHT;
- if (entry->last_date != -1) height += HOTLIST_LINE_HEIGHT;
- }
-
- /* Check whether we need to redraw
- */
- if ((x0 < clip_x1) && (y0 > clip_y0) && ((x0 + entry->width) > clip_x0) &&
- ((y0 - height) < clip_y1)) {
-
-
- /* Update the selection state
- */
- text_icon.flags = wimp_ICON_TEXT | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
- (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
- wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED;
- if (entry->selected) {
- sprite_icon.flags |= wimp_ICON_SELECTED;
- text_icon.flags |= wimp_ICON_SELECTED;
- text_icon.flags |= wimp_ICON_FILLED;
- }
-
- /* Draw our icon type
- */
- sprite_icon.extent.x0 = x0 - origin_x;
- sprite_icon.extent.x1 = x0 - origin_x + HOTLIST_ICON_WIDTH;
- sprite_icon.extent.y0 = y0 - origin_y - HOTLIST_LINE_HEIGHT;
- sprite_icon.extent.y1 = y0 - origin_y;
- sprite_icon.data.indirected_sprite.id = (osspriteop_id)icon_name;
- if (entry->children != -1) {
- if ((entry->expanded) && (entry->children > 0)) {
- sprintf(icon_name, "small_diro");
- hotlist_ensure_sprite(icon_name, "small_dir");
- } else {
- sprintf(icon_name, "small_dir");
- }
- } else {
- /* Get the icon sprite
- */
- sprintf(icon_name, "small_%x", entry->filetype);
- hotlist_ensure_sprite(icon_name, "small_xxx");
- }
- xwimp_plot_icon(&sprite_icon);
-
- /* Draw our textual information
- */
- text_icon.data.indirected_text.text = entry->title;
- text_icon.extent.x0 = x0 - origin_x + HOTLIST_ICON_WIDTH;
- text_icon.extent.x1 = x0 - origin_x + entry->collapsed_width - HOTLIST_LEAF_INSET;
- text_icon.extent.y0 = y0 - origin_y - HOTLIST_LINE_HEIGHT + 2;
- text_icon.extent.y1 = y0 - origin_y - 2;
- xwimp_plot_icon(&text_icon);
-
- /* Clear the selection state
- */
- if (entry->selected) {
- sprite_icon.flags &= ~wimp_ICON_SELECTED;
- }
-
- /* Draw our further information if expanded
- */
- if ((entry->children == -1) && (entry->expanded) && (height > HOTLIST_LINE_HEIGHT)) {
- text_icon.flags = wimp_ICON_TEXT | (wimp_COLOUR_DARK_GREY << wimp_ICON_FG_COLOUR_SHIFT) |
- wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED;
- text_icon.extent.y0 = y0 - origin_y - HOTLIST_LINE_HEIGHT;
- text_icon.extent.y1 = y0 - origin_y;
-
- /* Draw the lines
- */
- y0 -= HOTLIST_LINE_HEIGHT;
- line_y0 = y0;
- line_height = height - HOTLIST_LINE_HEIGHT;
- while (line_height > 0) {
- if (line_height == HOTLIST_LINE_HEIGHT) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_TLINE], x0 + 16, line_y0 - 22,
- tinct_BILINEAR_FILTER);
- } else {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_LINE], x0 + 16, line_y0 - HOTLIST_LINE_HEIGHT,
- tinct_BILINEAR_FILTER);
- }
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- sprite[HOTLIST_ENTRY], x0 + 8, line_y0 - 23,
- tinct_BILINEAR_FILTER);
- line_height -= HOTLIST_LINE_HEIGHT;
- line_y0 -= HOTLIST_LINE_HEIGHT;
- }
-
- /* Set the right extent of the icon to be big enough for anything
- */
- text_icon.extent.x1 = x0 - origin_x + 4096;
-
- /* Plot the URL text
- */
- text_icon.data.indirected_text.text = extended_text;
- if (entry->url) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistURL"), entry->url);
- if (strlen(extended_text) >= 255) {
- extended_text[252] = '.';
- extended_text[253] = '.';
- extended_text[254] = '.';
- extended_text[255] = '\0';
- }
- text_icon.extent.y0 -= HOTLIST_LINE_HEIGHT;
- text_icon.extent.y1 -= HOTLIST_LINE_HEIGHT;
- xwimp_plot_icon(&text_icon);
- }
-
- /* Plot the date added text
- */
- if (entry->add_date != -1) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistAdded"), ctime(&entry->add_date));
- text_icon.extent.y0 -= HOTLIST_LINE_HEIGHT;
- text_icon.extent.y1 -= HOTLIST_LINE_HEIGHT;
- xwimp_plot_icon(&text_icon);
- }
-
- /* Plot the last visited text
- */
- if (entry->last_date != -1) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistLast"), ctime(&entry->last_date));
- text_icon.extent.y0 -= HOTLIST_LINE_HEIGHT;
- text_icon.extent.y1 -= HOTLIST_LINE_HEIGHT;
- xwimp_plot_icon(&text_icon);
- }
-
- /* Plot the visit count text
- */
- if (entry->visits > 0) {
- snprintf(extended_text, HOTLIST_TEXT_BUFFER,
- messages_get("HotlistVisits"), entry->visits);
- text_icon.extent.y0 -= HOTLIST_LINE_HEIGHT;
- text_icon.extent.y1 -= HOTLIST_LINE_HEIGHT;
- xwimp_plot_icon(&text_icon);
- }
- }
- }
-
- /* Draw any children
- */
- if ((entry->child_entry) && (entry->expanded)) {
- height += ro_gui_hotlist_redraw_tree(entry->child_entry, level + 1,
- x0 + 8, y0 - HOTLIST_LINE_HEIGHT);
- }
- return height;
+ xwimp_set_caret_position(state.w, -1, -100, -100, 32, -1);
}
/**
* Respond to a mouse click
*
- * /param pointer the pointer state
+ * \param pointer the pointer state
*/
void ro_gui_hotlist_click(wimp_pointer *pointer) {
- wimp_caret caret;
- wimp_drag drag;
- struct hotlist_entry *entry;
- wimp_window_state state;
- wimp_mouse_state buttons;
- int x, y;
- int x_offset;
- int y_offset;
- bool no_entry = false;
- os_error *error;
- os_box box = { pointer->pos.x - 34, pointer->pos.y - 34,
- pointer->pos.x + 34, pointer->pos.y + 34 };
- int selection;
-
- /* Get the button state
- */
- buttons = pointer->buttons;
-
- /* Get the window state. Quite why the Wimp can't give relative
- positions is beyond me.
- */
- state.w = hotlist_window;
- wimp_get_window_state(&state);
-
- /* Translate by the origin/scroll values
- */
- x = (pointer->pos.x - (state.visible.x0 - state.xscroll));
- y = (pointer->pos.y - (state.visible.y1 - state.yscroll));
-
- /* We want the caret on a click
- */
- error = xwimp_get_caret_position(&caret);
- if (error) {
- LOG(("xwimp_get_caret_position: 0x%x: %s", error->errnum,
- error->errmess));
- }
- if (((pointer->buttons == (wimp_CLICK_SELECT << 8)) ||
- (pointer->buttons == (wimp_CLICK_ADJUST << 8))) &&
- (caret.w != state.w)) {
- error = xwimp_set_caret_position(state.w, -1, -100,
- -100, 32, -1);
- if (error) {
- LOG(("xwimp_set_caret_position: 0x%x: %s",
- error->errnum, error->errmess));
- }
- }
-
- /* Find our entry
- */
- entry = ro_gui_hotlist_find_entry(x, y, root.child_entry);
- if (entry) {
- /* Check if we clicked on the expanding bit
- */
- x_offset = x - entry->x0;
- y_offset = y - (entry->y0 + entry->height);
- if (((x_offset < HOTLIST_LEAF_INSET) && (y_offset > -HOTLIST_LINE_HEIGHT) &&
- ((buttons == wimp_CLICK_SELECT << 8) || (buttons == wimp_CLICK_ADJUST << 8) ||
- (buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST))) ||
- ((entry->children != -1) &&
- ((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)))) {
- if (entry->children != 0) {
- ro_gui_hotlist_update_expansion(entry->child_entry, false, true, true, false, true);
- ro_gui_hotlist_selection_state(entry->child_entry,
- false, false);
- entry->expanded = !entry->expanded;
- if (x_offset >= HOTLIST_LEAF_INSET) entry->selected = false;
- reformat_pending = true;
- hotlist_redraw_entry(entry, true);
- ro_gui_menu_prepare_hotlist();
- }
- } else if (x_offset >= HOTLIST_LEAF_INSET) {
-
- /* We treat a menu click as a Select click if we have no selections
- */
- if (buttons == wimp_CLICK_MENU) {
- if (ro_gui_hotlist_selection_count(root.child_entry, true) == 0) {
- menu_selection = true;
- buttons = (wimp_CLICK_SELECT << 8);
- }
- }
-
- /* Check for selection
- */
- if (buttons == (wimp_CLICK_SELECT << 8)) {
- if (!entry->selected) {
- ro_gui_hotlist_selection_state(root.child_entry,
- false, true);
- entry->selected = true;
- hotlist_redraw_entry_title(entry);
- ro_gui_menu_prepare_hotlist();
-
- }
- } else if (buttons == (wimp_CLICK_ADJUST << 8)) {
- entry->selected = !entry->selected;
- hotlist_redraw_entry_title(entry);
- ro_gui_menu_prepare_hotlist();
- }
-
- /* Check if we should open the URL
- */
- if (((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)) &&
- (entry->children == -1)) {
- browser_window_create(entry->url, NULL, 0);
- if (buttons == wimp_DOUBLE_SELECT) {
- ro_gui_hotlist_selection_state(root.child_entry,
- false, true);
- ro_gui_menu_prepare_hotlist();
- } else {
- entry->selected = false;
- ro_gui_dialog_close_persistant(hotlist_window);
- xwimp_close_window(hotlist_window);
- }
- }
-
- /* Check if we should start a drag
- */
- if ((buttons == (wimp_CLICK_SELECT <<4)) || (buttons == (wimp_CLICK_ADJUST << 4))) {
- selection = ro_gui_hotlist_get_selected(true);
- if (selection > 0) {
- gui_current_drag_type = GUI_DRAG_HOTLIST_MOVE;
- if (selection > 1) {
- sprintf(drag_name, "package");
- } else {
- if (entry->children != -1) {
- if ((entry->expanded) && (entry->children > 0)) {
- sprintf(drag_name, "directoryo");
- hotlist_ensure_sprite(drag_name, "directory");
- } else {
- sprintf(drag_name, "directory");
- }
- } else {
- sprintf(drag_name, "file_%x", entry->filetype);
- hotlist_ensure_sprite(drag_name, "file_xxx");
- }
- }
- error = xdragasprite_start(dragasprite_HPOS_CENTRE |
- dragasprite_VPOS_CENTRE |
- dragasprite_BOUND_POINTER |
- dragasprite_DROP_SHADOW,
- (osspriteop_area *) 1, drag_name, &box, 0);
- dragging = true;
- }
- }
- } else {
- if (!((x_offset < HOTLIST_LEAF_INSET) && (y_offset > -HOTLIST_LINE_HEIGHT))) {
- no_entry = true;
- }
- }
- } else {
- no_entry = true;
- }
-
- /* Get the original button state back
- */
- buttons = pointer->buttons;
-
- /* Create a menu if we should
- */
- if (buttons == wimp_CLICK_MENU) {
+ ro_gui_tree_click(pointer, hotlist_tree);
+ if (pointer->buttons == wimp_CLICK_MENU)
ro_gui_create_menu(hotlist_menu, pointer->pos.x,
pointer->pos.y, NULL);
- menu_open = true;
- return;
- }
-
- /* Handle a click without an entry
- */
- if (no_entry) {
- /* Deselect everything if we click nowhere
- */
- if (buttons == (wimp_CLICK_SELECT << 8)) {
- ro_gui_hotlist_selection_state(root.child_entry,
- false, true);
- ro_gui_menu_prepare_hotlist();
- }
-
- /* Handle the start of a drag
- */
- if (buttons == (wimp_CLICK_SELECT << 4) ||
- buttons == (wimp_CLICK_ADJUST << 4)) {
-
- /* Clear the current selection
- */
- if (buttons == (wimp_CLICK_SELECT << 4)) {
- ro_gui_hotlist_selection_state(root.child_entry,
- false, true);
- ro_gui_menu_prepare_hotlist();
- }
-
- /* Start a drag box
- */
- drag_buttons = buttons;
- gui_current_drag_type = GUI_DRAG_HOTLIST_SELECT;
- drag.w = hotlist_window;
- drag.type = wimp_DRAG_USER_RUBBER;
- drag.initial.x0 = pointer->pos.x;
- drag.initial.x1 = pointer->pos.x;
- drag.initial.y0 = pointer->pos.y;
- drag.initial.y1 = pointer->pos.y;
- drag.bbox.x0 = state.visible.x0;
- drag.bbox.x1 = state.visible.x1;
- drag.bbox.y0 = state.visible.y0;
- drag.bbox.y1 = state.visible.y1;
- if (hotlist_toolbar) drag.bbox.y1 -= hotlist_toolbar->height;
- xwimp_drag_box(&drag);
- dragging = true;
- }
- }
-}
-
-
-/**
- * Find an entry at a particular position
- *
- * \param x the x co-ordinate
- * \param y the y co-ordinate
- * \param entry the entry to check down from (root->child_entry for the entire tree)
- * /return the entry occupying the positon
- */
-struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_entry *entry) {
- struct hotlist_entry *find_entry;
- int inset_x = 0;
- int inset_y = 0;
-
- /* Check we have an entry (only applies if we have an empty hotlist)
- */
- if (!entry) return NULL;
-
- /* Get the first child entry
- */
- while (entry) {
- /* Check if this entry could possibly match
- */
- if ((x > entry->x0) && (y > entry->y0) && (x < (entry->x0 + entry->width)) &&
- (y < (entry->y0 + entry->height))) {
-
- /* The top line extends all the way left
- */
- if (y - (entry->y0 + entry->height) > -HOTLIST_LINE_HEIGHT) {
- if (x < (entry->x0 + entry->collapsed_width)) return entry;
- return NULL;
- }
-
- /* No other entry can occupy the left edge
- */
- inset_x = x - entry->x0 - HOTLIST_LEAF_INSET - HOTLIST_ICON_WIDTH;
- if (inset_x < 0) return NULL;
-
- /* Check the right edge against our various widths
- */
- inset_y = -((y - entry->y0 - entry->height) / HOTLIST_LINE_HEIGHT);
- if (inset_x < (entry->widths[inset_y - 1] + HOTLIST_TEXT_PADDING)) return entry;
- return NULL;
- }
-
- /* Continue onwards
- */
- if ((entry->child_entry) && (entry->expanded)) {
- find_entry = ro_gui_hotlist_find_entry(x, y, entry->child_entry);
- if (find_entry) return find_entry;
- }
- entry = entry->next_entry;
- }
- return NULL;
-}
-
-
-/**
- * Updated the selection state of the tree
- *
- * \param entry the entry to update all siblings and descendants of
- * \param selected the selection state to set
- * \param redraw update the icons in the Wimp
- * \return the number of entries that have changed
- */
-int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, bool redraw) {
- int changes = 0;
-
- /* Check we have an entry (only applies if we have an empty hotlist)
- */
- if (!entry) return 0;
-
- /* Get the first child entry
- */
- while (entry) {
- /* Check this entry
- */
- if (entry->selected != selected) {
- /* Update the selection state
- */
- entry->selected = selected;
- changes++;
-
- /* Redraw the entrys first line
- */
- if (redraw) hotlist_redraw_entry_title(entry);
- }
-
- /* Continue onwards
- */
- if ((entry->child_entry) && ((!selected) || (entry->expanded))) {
- changes += ro_gui_hotlist_selection_state(entry->child_entry,
- selected, redraw & (entry->expanded));
- }
- entry = entry->next_entry;
- }
- return changes;
-}
-
-
-/**
- * Returns the first selected item
- *
- * \param entry the search siblings and children of
- * \return the first selected item
- */
-struct hotlist_entry *ro_gui_hotlist_first_selection(struct hotlist_entry *entry) {
- struct hotlist_entry *test_entry;
-
- /* Check we have an entry (only applies if we have an empty hotlist)
- */
- if (!entry) return NULL;
-
- /* Work through our entries
- */
- while (entry) {
- if (entry->selected) return entry;
- if (entry->child_entry) {
- test_entry = ro_gui_hotlist_first_selection(entry->child_entry);
- if (test_entry) return test_entry;
- }
- entry = entry->next_entry;
- }
- return NULL;
-}
-
-
-/**
- * Return the current number of selected items (internal interface)
- *
- * \param entry the entry to count siblings and children of
- */
-int ro_gui_hotlist_selection_count(struct hotlist_entry *entry, bool folders) {
- int count = 0;
- if (!entry) return 0;
- while (entry) {
- if ((entry->selected) && (folders || (entry->children == -1))) count++;
- if (entry->child_entry) count += ro_gui_hotlist_selection_count(entry->child_entry, folders);
- entry = entry->next_entry;
- }
- return count;
-}
-
-
-/**
- * Launch the current selection (internal interface)
- *
- * \param entry the entry to launch siblings and children of
- */
-void ro_gui_hotlist_launch_selection(struct hotlist_entry *entry) {
- if (!entry) return;
- while (entry) {
- if ((entry->selected) && (entry->url)) browser_window_create(entry->url, NULL, 0);
- if (entry->child_entry) ro_gui_hotlist_launch_selection(entry->child_entry);
- entry = entry->next_entry;
- }
-}
-
-
-/**
- * Invalidate the statistics for any selected items (internal interface)
- *
- * \param entry the entry to update siblings and children of
- */
-void ro_gui_hotlist_invalidate_statistics(struct hotlist_entry *entry) {
- if (!entry) return;
- while (entry) {
- if ((entry->selected) && (entry->children == -1)) {
- entry->visits = 0;
- entry->last_date = (time_t)-1;
- if (entry->expanded) hotlist_redraw_entry(entry, true);
- }
- if (entry->child_entry) ro_gui_hotlist_invalidate_statistics(entry->child_entry);
- entry = entry->next_entry;
- }
-}
-
-
-/**
- * Set the process flag for the current selection (internal interface)
- *
- * \param entry the entry to modify siblings and children of
- */
-void ro_gui_hotlist_selection_to_process(struct hotlist_entry *entry) {
- if (!entry) return;
- while (entry) {
- entry->process = entry->selected;
- if (entry->child_entry) ro_gui_hotlist_selection_to_process(entry->child_entry);
- entry = entry->next_entry;
- }
-}
-
-
-/**
- * Toggles the expanded state for selected icons
- * If neither expand not contract are set then the entries are toggled
- *
- * \param entry the entry to update all siblings and descendants of
- * \param only_selected whether to only update selected icons
- * \param folders whether to update folders
- * \param links whether to update links
- * \param expand force all entries to be expanded (dominant)
- * \param contract force all entries to be contracted (recessive)
- */
-void ro_gui_hotlist_update_expansion(struct hotlist_entry *entry, bool only_selected,
- bool folders, bool links, bool expand, bool contract) {
- bool current;
-
- /* Set a reformat to be pending
- */
- reformat_pending = true;
-
- /* Check we have an entry (only applies if we have an empty hotlist)
- */
- if (!entry) return;
-
- /* Get the first child entry
- */
- while (entry) {
- /* Check this entry
- */
- if ((entry->selected) || (!only_selected)) {
- current = entry->expanded;
-
- /* Only update what we should
- */
- if (((links) && (entry->children == -1)) || ((folders) && (entry->children > 0))) {
- /* Update the expansion state
- */
- if (expand) {
- entry->expanded = true;
- } else if (contract) {
- entry->expanded = false;
- } else {
- entry->expanded = !entry->expanded;
- }
- }
-
- /* If we have contracted then we de-select and collapse any children
- */
- if (entry->child_entry && !entry->expanded) {
- ro_gui_hotlist_update_expansion(entry->child_entry, false, true, true, false, true);
- ro_gui_hotlist_selection_state(entry->child_entry, false, false);
- }
-
- /* Redraw the entrys first line
- */
- if (current != entry->expanded) hotlist_redraw_entry(entry, true);
- }
-
- /* Continue onwards (child entries cannot be selected if the parent is
- not expanded)
- */
- if (entry->child_entry && entry->expanded) {
- ro_gui_hotlist_update_expansion(entry->child_entry,
- only_selected, folders, links, expand, contract);
- }
- entry = entry->next_entry;
- }
+ else
+ ro_gui_menu_prepare_hotlist();
}
/**
- * Updated the selection state of the tree
+ * Respond to a keypress
*
- * \param entry the entry to update all siblings and descendants of
- * \param x0 the left edge of the box
- * \param y0 the top edge of the box
- * \param x1 the right edge of the box
- * \param y1 the bottom edge of the box
- * \param toggle toggle the selection state, otherwise set
- * \param redraw update the icons in the Wimp
+ * \param key the key pressed
*/
-void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry,
- int x0, int y0, int x1, int y1,
- bool toggle, bool redraw) {
- bool do_update;
- int line;
- int test_y;
-
- /* Check we have an entry (only applies if we have an empty hotlist)
- */
- if (!entry) return;
-
- /* Get the first child entry
- */
- while (entry) {
- /* Check if this entry could possibly match
- */
- if ((x1 > (entry->x0 + HOTLIST_LEAF_INSET)) && (y0 > entry->y0) &&
- (x0 < (entry->x0 + entry->width)) &&
- (y1 < (entry->y0 + entry->height))) {
- do_update = false;
-
- /* Check the exact area of the title line
- */
- if ((x1 > (entry->x0 + HOTLIST_LEAF_INSET)) &&
- (y0 > entry->y0 + entry->height - HOTLIST_LINE_HEIGHT) &&
- (x0 < (entry->x0 + entry->collapsed_width)) &&
- (y1 < (entry->y0 + entry->height))) {
- do_update = true;
- }
-
- /* Check the other lines
- */
- line = 1;
- test_y = entry->y0 + entry->height - HOTLIST_LINE_HEIGHT;
- while (((line * HOTLIST_LINE_HEIGHT) < entry->height) && (!do_update)) {
- /* Check this line
- */
- if ((x1 > (entry->x0 + HOTLIST_LEAF_INSET + HOTLIST_ICON_WIDTH)) &&
- (y1 < test_y) && (y0 > test_y - HOTLIST_LINE_HEIGHT) &&
- (x0 < (entry->x0 + entry->widths[line - 1] +
- HOTLIST_LEAF_INSET + HOTLIST_ICON_WIDTH +
- HOTLIST_TEXT_PADDING))) {
- do_update = true;
- }
-
- /* Move to the next line
- */
- line++;
- test_y -= HOTLIST_LINE_HEIGHT;
- }
-
- /* Redraw the entrys first line
- */
- if (do_update) {
- if (toggle) {
- entry->selected = !entry->selected;
- } else {
- entry->selected = true;
- }
- if (redraw) hotlist_redraw_entry_title(entry);
- }
- }
-
- /* Continue onwards
- */
- if ((entry->child_entry) && (entry->expanded)) {
- ro_gui_hotlist_selection_drag(entry->child_entry,
- x0, y0, x1, y1, toggle, redraw);
- }
- entry = entry->next_entry;
- do_update = false;
- }
-}
-
-
-/**
- * The end of a selection drag has been reached
- *
- * \param drag the final drag co-ordinates
- */
-void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag) {
- wimp_window_state state;
- int x0, y0, x1, y1;
- int toolbar_height = 0;
-
- /* Reset our dragging state
- */
- dragging = false;
-
- /* Get the toolbar height
- */
- if (hotlist_toolbar) toolbar_height = hotlist_toolbar->height * 2;
-
- /* Get the window state to make everything relative
- */
- state.w = hotlist_window;
- wimp_get_window_state(&state);
-
- /* Create the relative positions
- */
- x0 = drag->final.x0 - state.visible.x0 - state.xscroll;
- x1 = drag->final.x1 - state.visible.x0 - state.xscroll;
- y0 = drag->final.y0 - state.visible.y1 - state.yscroll + toolbar_height;
- y1 = drag->final.y1 - state.visible.y1 - state.yscroll + toolbar_height;
-
- /* Make sure x0 < x1 and y0 > y1
- */
- if (x0 > x1) {
- x0 ^= x1;
- x1 ^= x0;
- x0 ^= x1;
- }
- if (y0 < y1) {
- y0 ^= y1;
- y1 ^= y0;
- y0 ^= y1;
- }
-
- /* Update the selection state
- */
- if (drag_buttons == (wimp_CLICK_SELECT << 4)) {
- ro_gui_hotlist_selection_drag(root.child_entry, x0, y0, x1, y1, false, true);
- } else {
- ro_gui_hotlist_selection_drag(root.child_entry, x0, y0, x1, y1, true, true);
- }
+bool ro_gui_hotlist_keypress(int key) {
+ // struct node_element *edit = hotlist_tree->editing;
+ bool result = ro_gui_tree_keypress(key, hotlist_tree);
ro_gui_menu_prepare_hotlist();
-}
-
-
-/**
- * The end of a item moving drag has been reached
- *
- * \param drag the final drag co-ordinates
- */
-void ro_gui_hotlist_move_drag_end(wimp_dragged *drag) {
- wimp_pointer pointer;
- int toolbar_height = 0;
- wimp_window_state state;
- struct hotlist_entry *test_entry;
- struct hotlist_entry *entry;
- int x, y, x0, y0, x1, y1;
- bool before = false;
-
- /* Reset our dragging state
- */
- dragging = false;
-
- /* Check we dropped to our window
- */
- xwimp_get_pointer_info(&pointer);
- if (pointer.w != hotlist_window) return;
-
- /* Get the toolbar height
- */
- if (hotlist_toolbar) toolbar_height = hotlist_toolbar->height * 2;
-
- /* Set the process flag for all selected items
- */
- ro_gui_hotlist_selection_to_process(root.child_entry);
-
- /* Get the window state to make everything relative
- */
- state.w = hotlist_window;
- wimp_get_window_state(&state);
-
- /* Create the relative positions
- */
- x0 = drag->final.x0 - state.visible.x0 - state.xscroll;
- x1 = drag->final.x1 - state.visible.x0 - state.xscroll;
- y0 = drag->final.y0 - state.visible.y1 - state.yscroll + toolbar_height;
- y1 = drag->final.y1 - state.visible.y1 - state.yscroll + toolbar_height;
- x = (x0 + x1) / 2;
- y = (y0 + y1) / 2;
-
- /* Find our entry
- */
- entry = ro_gui_hotlist_find_entry(x, y, root.child_entry);
- if (!entry) entry = &root;
-
- /* No parent of the destination can be processed
- */
- test_entry = entry;
- while (test_entry != NULL) {
- if (test_entry->process) return;
- test_entry = test_entry->parent_entry;
- }
- /* Check for before/after
- */
- before = ((y - (entry->y0 + entry->height)) > (-HOTLIST_LINE_HEIGHT / 2));
-
- /* Start our recursive moving
- */
- while (ro_gui_hotlist_move_processing(root.child_entry, entry, before));
-}
-
-
-
-bool ro_gui_hotlist_move_processing(struct hotlist_entry *entry, struct hotlist_entry *destination, bool before) {
- bool result = false;
- if (!entry) return false;
- while (entry) {
- if (entry->process) {
- entry->process = false;
- ro_gui_hotlist_delink_entry(entry);
- ro_gui_hotlist_link_entry(destination, entry, before);
- result = true;
- }
- if (entry->child_entry) {
- result |= ro_gui_hotlist_move_processing(entry->child_entry, destination, before);
- }
- entry = entry->next_entry;
- }
+/* if ((edit) && (!hotlist_tree->editing))
+ ro_gui_hotlist_save();
+*/
return result;
}
+
/**
- * Handle a menu being closed
+ * Handles a menu closed event
*/
void ro_gui_hotlist_menu_closed(void) {
- menu_open = false;
- if (menu_selection) {
- ro_gui_hotlist_selection_state(root.child_entry, false, true);
- menu_selection = false;
- }
+ ro_gui_tree_menu_closed(hotlist_tree);
+ current_menu = NULL;
+ ro_gui_menu_prepare_hotlist();
}
+
/**
- * Handle a keypress
+ * Respond to a mouse click
*
- * \param key the key pressed
- * \return whether the key was processed
+ * \param pointer the pointer state
*/
-bool ro_gui_hotlist_keypress(int key) {
- wimp_window_state state;
- int y;
-
- /* Handle basic keys
- */
- switch (key) {
- case 1: /* CTRL+A */
- ro_gui_hotlist_selection_state(root.child_entry, true, true);
- if (menu_open) ro_gui_create_menu(hotlist_menu, 0, 0, NULL);
- return true;
- case 26: /* CTRL+Z */
- ro_gui_hotlist_selection_state(root.child_entry, false, true);
- if (menu_open) ro_gui_create_menu(hotlist_menu, 0, 0, NULL);
- return true;
- case 32: /* SPACE */
- ro_gui_hotlist_update_expansion(root.child_entry, true, true, true, false, false);
- if (menu_open) ro_gui_create_menu(hotlist_menu, 0, 0, NULL);
- return true;
- case wimp_KEY_RETURN:
- ro_gui_hotlist_launch_selection(root.child_entry);
- return true;
- case wimp_KEY_F3:
- ro_gui_hotlist_save();
- return true;
- case wimp_KEY_UP:
- case wimp_KEY_DOWN:
- case wimp_KEY_PAGE_UP:
- case wimp_KEY_PAGE_DOWN:
- case wimp_KEY_CONTROL | wimp_KEY_UP:
- case wimp_KEY_CONTROL | wimp_KEY_DOWN:
- break;
-
- default:
- return false;
- }
-
- /* Handle keypress scrolling
- */
- state.w = hotlist_window;
- wimp_get_window_state(&state);
- y = state.visible.y1 - state.visible.y0 - 32;
- switch (key) {
- case wimp_KEY_UP:
- state.yscroll += 32;
- break;
- case wimp_KEY_DOWN:
- state.yscroll -= 32;
- break;
- case wimp_KEY_PAGE_UP:
- state.yscroll += y;
- break;
- case wimp_KEY_PAGE_DOWN:
- state.yscroll -= y;
- break;
- case wimp_KEY_CONTROL | wimp_KEY_UP:
- state.yscroll = 1000;
- break;
- case wimp_KEY_CONTROL | wimp_KEY_DOWN:
- state.yscroll = -0x10000000;
- break;
- }
- xwimp_open_window((wimp_open *) &state);
- return true;
-}
-
-
void ro_gui_hotlist_toolbar_click(wimp_pointer* pointer) {
- int selection;
+ struct node *node;
- /* Store the toolbar
- */
current_toolbar = hotlist_toolbar;
-
- /* Handle Menu clicks
- */
- if (pointer->buttons == wimp_CLICK_MENU) {
- ro_gui_create_menu(toolbar_menu, pointer->pos.x,
- pointer->pos.y, NULL);
- return;
- }
+ ro_gui_tree_stop_edit(hotlist_tree);
- /* Handle the buttons appropriately
- */
switch (pointer->i) {
case ICON_TOOLBAR_CREATE:
- hotlist_insert = false;
- if (pointer->buttons == wimp_CLICK_SELECT) {
- ro_gui_hotlist_prepare_folder_dialog(false);
- ro_gui_dialog_open_persistant(hotlist_window, dialog_folder, true);
- } else {
- ro_gui_hotlist_prepare_entry_dialog(false);
- ro_gui_dialog_open_persistant(hotlist_window, dialog_entry, true);
- }
+ node = tree_create_folder_node(hotlist_tree->root,
+ messages_get("TreeNewFolder"));
+ tree_redraw_area(hotlist_tree, node->box.x - NODE_INSTEP,
+ 0, NODE_INSTEP, 16384);
+ tree_handle_node_changed(hotlist_tree, node, false, true);
+ ro_gui_tree_start_edit(hotlist_tree, &node->data, NULL);
break;
case ICON_TOOLBAR_OPEN:
- selection = ro_gui_hotlist_get_selected(true);
- ro_gui_hotlist_update_expansion(root.child_entry, (selection != 0), true, false,
+ tree_handle_expansion(hotlist_tree, hotlist_tree->root,
(pointer->buttons == wimp_CLICK_SELECT),
- (pointer->buttons == wimp_CLICK_ADJUST));
+ true, false);
break;
case ICON_TOOLBAR_EXPAND:
- selection = ro_gui_hotlist_get_selected(true);
- ro_gui_hotlist_update_expansion(root.child_entry, (selection != 0), false, true,
+ tree_handle_expansion(hotlist_tree, hotlist_tree->root,
(pointer->buttons == wimp_CLICK_SELECT),
- (pointer->buttons == wimp_CLICK_ADJUST));
+ false, true);
break;
case ICON_TOOLBAR_DELETE:
- ro_gui_hotlist_delete_selected();
+ tree_delete_selected_nodes(hotlist_tree,
+ hotlist_tree->root);
break;
case ICON_TOOLBAR_LAUNCH:
- ro_gui_hotlist_keypress(wimp_KEY_RETURN);
+ ro_gui_tree_launch_selected(hotlist_tree);
break;
}
}
-void ro_gui_hotlist_prepare_folder_dialog(bool selected) {
- struct hotlist_entry *entry = NULL;
- if (selected) entry = ro_gui_hotlist_first_selection(root.child_entry);
-
- /* Update the title
- */
- dialog_folder_add = selected;
- if (selected) {
- ro_gui_set_window_title(dialog_folder, messages_get("EditFolder"));
- } else {
- ro_gui_set_window_title(dialog_folder, messages_get("NewFolder"));
- }
-
- /* Update the icons
- */
- if (entry == NULL) {
- ro_gui_set_icon_string(dialog_folder, 1, messages_get("Folder"));
- } else {
- ro_gui_set_icon_string(dialog_folder, 1, entry->title);
- }
-}
-
-void ro_gui_hotlist_prepare_entry_dialog(bool selected) {
- struct hotlist_entry *entry = NULL;
- if (selected) entry = ro_gui_hotlist_first_selection(root.child_entry);
-
- /* Update the title
- */
- dialog_entry_add = selected;
- if (selected) {
- ro_gui_set_window_title(dialog_entry, messages_get("EditLink"));
- } else {
- ro_gui_set_window_title(dialog_entry, messages_get("NewLink"));
- }
-
- /* Update the icons
- */
- if (entry == NULL) {
- ro_gui_set_icon_string(dialog_entry, 1, messages_get("Link"));
- ro_gui_set_icon_string(dialog_entry, 3, "");
- } else {
- ro_gui_set_icon_string(dialog_entry, 1, entry->title);
- ro_gui_set_icon_string(dialog_entry, 3, entry->url);
- }
-}
-
-
/**
- * Set all items to either selected or deselected
+ * Informs the hotlist that some content has been visited
*
- * \param selected the state to set all items to
+ * \param content the content visited
*/
-void ro_gui_hotlist_set_selected(bool selected) {
- ro_gui_hotlist_selection_state(root.child_entry, selected, true);
- menu_selection = false;
+void hotlist_visited(struct content *content) {
+ if ((!content) || (!content->url) || (!hotlist_tree))
+ return;
+ ro_gui_hotlist_visited(content, hotlist_tree, hotlist_tree->root);
}
/**
- * Reset the statistics for selected entries
+ * 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 ro_gui_hotlist_reset_statistics(void) {
- ro_gui_hotlist_invalidate_statistics(root.child_entry);
+void ro_gui_hotlist_visited(struct content *content, struct tree *tree,
+ struct node *node) {
+ 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->url))) {
+ element->user_data = ro_content_filetype(content);
+ element = tree_find_element(node,
+ TREE_ELEMENT_VISITS);
+ if (element)
+ element->user_data += 1;
+ element = tree_find_element(node,
+ TREE_ELEMENT_LAST_VISIT);
+ if (element)
+ element->user_data = time(NULL);
+ tree_update_URL_node(node);
+ tree_handle_node_changed(tree, node, true, false);
+ }
+ }
+ if (node->child)
+ ro_gui_hotlist_visited(content, tree, node->child);
+ }
}
/**
- * Return the current number of selected items
+ * Prepares the folder dialog contents for a node
*
- * \param folders include folders in the selection count
- * \return the number of selected items
+ * \param node the node to prepare the dialogue for, or NULL
*/
-int ro_gui_hotlist_get_selected(bool folders) {
- return ro_gui_hotlist_selection_count(root.child_entry, folders);
+void ro_gui_hotlist_prepare_folder_dialog(struct node *node) {
+ dialog_folder_node = node;
+ if (node) {
+ ro_gui_set_window_title(dialog_folder, messages_get("EditFolder"));
+ ro_gui_set_icon_string(dialog_folder, 1, node->data.text);
+ } else {
+ ro_gui_set_window_title(dialog_folder, messages_get("NewFolder"));
+ ro_gui_set_icon_string(dialog_folder, 1, messages_get("Folder"));
+ }
}
/**
- * Set all items to either selected or deselected
+ * Prepares the entry dialog contents for a node
*
- * \param expand whether to expand (collapse otherwise)
- * \param folders whether to update folders
- * \param links whether to update links
+ * \param node the node to prepare the dialogue for, or NULL
*/
-void ro_gui_hotlist_set_expanded(bool expand, bool folders, bool links) {
- ro_gui_hotlist_update_expansion(root.child_entry, false, folders, links, expand, !expand);
+void ro_gui_hotlist_prepare_entry_dialog(struct node *node) {
+ struct node_element *element;
+
+ dialog_entry_node = node;
+ if (node) {
+ ro_gui_set_window_title(dialog_entry, messages_get("EditLink"));
+ ro_gui_set_icon_string(dialog_entry, 1, node->data.text);
+ element = tree_find_element(node, TREE_ELEMENT_URL);
+ if (element)
+ ro_gui_set_icon_string(dialog_entry, 3, element->text);
+ else
+ ro_gui_set_icon_string(dialog_entry, 3, "");
+ } else {
+ ro_gui_set_window_title(dialog_entry, messages_get("NewLink"));
+ ro_gui_set_icon_string(dialog_entry, 1, messages_get("Link"));
+ ro_gui_set_icon_string(dialog_entry, 3, "");
+ }
}
/**
- * Deletes any selected items
+ * Respond to a mouse click
*
- * \param selected the state to set all items to
+ * \param pointer the pointer state
*/
-void ro_gui_hotlist_delete_selected(void) {
- struct hotlist_entry *entry;
- while ((entry = ro_gui_hotlist_first_selection(root.child_entry)) != NULL) {
- ro_gui_hotlist_delete_entry(entry, false);
- }
-}
-
void ro_gui_hotlist_dialog_click(wimp_pointer *pointer) {
- struct hotlist_entry *entry = NULL;
+ struct node_element *element;
+ struct node *node;
char *title = NULL;
char *url = NULL;
char *old_value;
int icon = pointer->i;
int close_icon, ok_icon;
- bool folder;
- bool add;
url_func_result res;
- /* Get our data
- */
if (pointer->w == dialog_entry) {
title = strip(ro_gui_get_icon_string(pointer->w, 1));
url = strip(ro_gui_get_icon_string(pointer->w, 3));
close_icon = 4;
ok_icon = 5;
- folder = false;
- add = !dialog_entry_add;
+ node = dialog_entry_node;
} else {
title = strip(ro_gui_get_icon_string(pointer->w, 1));
close_icon = 2;
ok_icon = 3;
- folder = true;
- add = !dialog_folder_add;
+ node = dialog_folder_node;
}
- /* Check for cancelling
- */
if (icon == close_icon) {
if (pointer->buttons == wimp_CLICK_SELECT) {
ro_gui_dialog_close(pointer->w);
xwimp_create_menu((wimp_menu *)-1, 0, 0);
- return;
- }
- if (folder) {
- ro_gui_hotlist_prepare_folder_dialog(dialog_folder_add);
} else {
- ro_gui_hotlist_prepare_entry_dialog(dialog_entry_add);
+ if (pointer->w == dialog_folder)
+ ro_gui_hotlist_prepare_folder_dialog(dialog_folder_node);
+ else
+ ro_gui_hotlist_prepare_entry_dialog(dialog_entry_node);
}
return;
}
- /* Check for ok
- */
- if (icon != ok_icon) return;
+ if (icon != ok_icon)
+ return;
/* Check we have valid values
*/
@@ -2514,95 +466,66 @@ void ro_gui_hotlist_dialog_click(wimp_pointer *pointer) {
/* Update/insert our data
*/
- if (add) {
- /* todo: insert at the selection place if hotlist_insert is set */
- ro_gui_hotlist_create_entry(title, url, folder ? 0 : 0xfaf, &root);
+ if (!node) {
+ if (pointer->w == dialog_folder) {
+ dialog_folder_node = tree_create_folder_node(hotlist_tree->root,
+ title);
+ node = dialog_folder_node;
+ } else {
+ dialog_entry_node = tree_create_URL_node(hotlist_tree->root,
+ title, url, 0xfaf, time(NULL), -1, 0);
+ node = dialog_entry_node;
+ }
+ 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 {
- entry = ro_gui_hotlist_first_selection(root.child_entry);
- if (entry == NULL) return;
if (url) {
- old_value = entry->url;
- res = url_normalize(url, &entry->url);
- if (res != URL_FUNC_OK) {
- /** \todo use correct error message */
- warn_user("NoMemory", 0);
- entry->url = old_value;
- return;
+ element = tree_find_element(node, TREE_ELEMENT_URL);
+ if (element) {
+ old_value = element->text;
+ res = url_normalize(url, &element->text);
+ if (res != URL_FUNC_OK) {
+ warn_user("NoMemory", 0);
+ element->text = old_value;
+ return;
+ }
+ free(old_value);
}
- if (old_value) free(old_value);
}
if (title) {
- old_value = entry->title;
- entry->title = strdup(title);
- if (!entry->title) {
+ old_value = node->data.text;
+ node->data.text = strdup(title);
+ if (!node->data.text) {
warn_user("NoMemory", 0);
- entry->title = old_value;
+ node->data.text = old_value;
return;
}
free(old_value);
}
- hotlist_redraw_entry(entry, false); /* first for contracting size */
- ro_gui_hotlist_update_entry_size(entry);
- hotlist_redraw_entry(entry, false); /* then for expanding size */
+ tree_handle_node_changed(hotlist_tree, node, true, false);
}
- /* Close if we should
- */
if (pointer->buttons == wimp_CLICK_SELECT) {
xwimp_create_menu((wimp_menu *)-1, 0, 0);
ro_gui_dialog_close(pointer->w);
return;
}
-
- /* Update our display
- */
- if (folder) {
- ro_gui_hotlist_prepare_folder_dialog(dialog_folder_add);
- } else {
- ro_gui_hotlist_prepare_entry_dialog(dialog_entry_add);
- }
+ if (pointer->w == dialog_folder)
+ ro_gui_hotlist_prepare_folder_dialog(dialog_folder_node);
+ else
+ ro_gui_hotlist_prepare_entry_dialog(dialog_entry_node);
}
-int ro_gui_hotlist_help(int x, int y) {
- struct hotlist_entry *entry;
- wimp_window_state state;
- int toolbar_height = 0;
- int x_offset, y_offset;
-
- /* Return the dragging codes
- */
- if (dragging) {
- if (gui_current_drag_type == GUI_DRAG_HOTLIST_SELECT) return 6;
- if (gui_current_drag_type == GUI_DRAG_HOTLIST_MOVE) return 7;
- return -1;
- }
-
- /* Get the toolbar height
- */
- if (hotlist_toolbar) toolbar_height = hotlist_toolbar->height * 2;
-
- /* Get the window state to make everything relative
- */
- state.w = hotlist_window;
- wimp_get_window_state(&state);
-
- /* Create the relative positions
- */
- x = x - state.visible.x0 - state.xscroll;
- y = y - state.visible.y1 - state.yscroll + toolbar_height;
-
- /* Get the current entry
- */
- entry = ro_gui_hotlist_find_entry(x, y, root.child_entry);
- if (entry == NULL) return -1;
- /* Return the relevant code
- */
- x_offset = x - entry->x0;
- y_offset = y - (entry->y0 + entry->height);
- if ((x_offset < HOTLIST_LEAF_INSET) && (y_offset > -HOTLIST_LINE_HEIGHT)) {
- if (entry->children == 0) return -1;
- return (((entry->children == -1) ? 2 : 0) + ((entry->expanded) ? 1 : 0));
- }
- return ((entry->children == -1) ? 5 : 4);
+/**
+ * Attempts to process an interactive help message request
+ *
+ * \param x the x co-ordinate to give help for
+ * \param y the x co-ordinate to give help for
+ * \return the message code index
+ */
+int ro_gui_hotlist_help(int x, int y) {
+ return -1;
}