From 32db7e04d0c3bd255b2e8aa7dbd7c2b884b35614 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Thu, 9 Dec 2004 10:30:44 +0000 Subject: [project @ 2004-12-09 10:30:43 by rjw] Re-implementation of hotlist via general tree code. Animations can be stopped once more. Purged a few xcalloc() calls. svn path=/import/netsurf/; revision=1394 --- riscos/hotlist.c | 2697 +++++++----------------------------------------------- 1 file changed, 310 insertions(+), 2387 deletions(-) (limited to 'riscos/hotlist.c') 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 #include +#include #include #include #include @@ -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; - - -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); - +struct node *dialog_folder_node; +struct node *dialog_entry_node; - -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(".WWW", 0); + xosfile_create_dir(".WWW.NetSurf", 0); + + /* Save to our file + */ + options_save_hotlist(hotlist_tree, ".WWW.NetSurf.Hotlist"); + error = xosfile_set_type(".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,2212 +230,302 @@ 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); + 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; - } +/** + * Respond to a mouse click + * + * \param pointer the pointer state + */ +void ro_gui_hotlist_click(wimp_pointer *pointer) { + 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); + else + ro_gui_menu_prepare_hotlist(); } /** - * Load the hotlist from file. + * Respond to a keypress * - * \param filename name of file to read + * \param key the key pressed */ +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(); -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", - "(......