From 4f664d155989c526aca0ac06b178d315a999b16d Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sun, 4 Jul 2004 14:59:29 +0000 Subject: [project @ 2004-07-04 14:59:29 by rjw] Futher hotlst development. Minor GUI tweaks. svn path=/import/netsurf/; revision=1044 --- !NetSurf/Resources/en/Messages | 2 + !NetSurf/Resources/fr/Messages | 2 + riscos/gui.c | 11 + riscos/gui.h | 1 + riscos/hotlist.c | 579 +++++++++++++++++++++++++++++------------ riscos/menus.c | 9 + riscos/window.c | 4 +- 7 files changed, 446 insertions(+), 162 deletions(-) diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index 471820fe7..e0fb50f93 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -108,6 +108,8 @@ WimpError:An unexpected Window Manager error occurred: Template:A window template is missing from the Templates file. Please reinstall NetSurf. MiscError:An unexpected error occurred: FileError:File does not exist: +HotlistSaveError:The hotlist was unable to be correctly saved. +HotlistLoadError:The hotlist was unable to be correctly loaded. # Some general purpose words and phrases Bytes: B diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages index 1ecd2fe62..a2742d92b 100644 --- a/!NetSurf/Resources/fr/Messages +++ b/!NetSurf/Resources/fr/Messages @@ -108,6 +108,8 @@ WimpError:Une erreur inattendue du Window Manager s'est produite: Template:Un modèle de fenêtre est absent du fichier Templates. Réinstallez NetSurf SVP. MiscError:Une erreur inattendue s'est produite: FileError:Le fichier n'existe pas: +HotlistSaveError:The hotlist was unable to be correctly saved. +HotlistLoadError:The hotlist was unable to be correctly loaded. # Some general purpose words and phrases Bytes: O diff --git a/riscos/gui.c b/riscos/gui.c index fcc3d2f26..8ae1fd26c 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -771,6 +771,17 @@ void ro_gui_drag_end(wimp_dragged *drag) void ro_gui_keypress(wimp_key *key) { bool handled = false; + + /* Check for hotlist windows + */ + if (key->w == hotlist_window) { + handled = ro_gui_hotlist_keypress(key->c); + if (!handled) wimp_process_key(key->c); + return; + } + + /* Handle the rest + */ gui_window *g = ro_gui_window_lookup(key->w); if (!g) { diff --git a/riscos/gui.h b/riscos/gui.h index cf27ffdb1..2ab06f165 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -183,6 +183,7 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw); void ro_gui_hotlist_click(wimp_pointer *pointer); void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag); void ro_gui_hotlist_move_drag_end(wimp_dragged *drag); +bool ro_gui_hotlist_keypress(int key); /* in save.c */ void ro_gui_save_click(wimp_pointer *pointer); diff --git a/riscos/hotlist.c b/riscos/hotlist.c index 663504c02..f791d24aa 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -14,6 +14,7 @@ #include #include #include "oslib/colourtrans.h" +#include "oslib/osfile.h" #include "oslib/wimp.h" #include "oslib/wimpspriteop.h" #include "netsurf/content/content.h" @@ -33,61 +34,61 @@ #define HOTLIST_TEXT_BUFFER 256 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 number of children (-1 for non-folders, >=0 for folders) */ int children; - + /** The title of the hotlist entry/folder */ 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]; @@ -119,7 +120,7 @@ static wimp_window hotlist_window_definition = { 1, 1, {"Hotlist"}, - 0 + 0, }; /* An icon to plot text with @@ -165,8 +166,10 @@ static osspriteop_trans_tab *pixel_table; wimp_mouse_state drag_buttons; -static void ro_gui_hotlist_load(void); +static bool ro_gui_hotlist_load(void); static void ro_gui_hotlist_save(void); +static bool ro_gui_hotlist_save_entry(FILE *fp, struct hotlist_entry entry); +static bool ro_gui_hotlist_load_entry(FILE *fp, struct hotlist_entry entry); static void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entry *entry); 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); @@ -179,11 +182,33 @@ static int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool sele 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); +static void ro_gui_hotlist_update_expansion(struct hotlist_entry *entry, bool only_selected, + bool expand, bool contract); + static char *last_visit_to_string(time_t last_visit); void ro_gui_hotlist_init(void) { os_error *error; + /* Ensure we have a directory to save to later. + */ + xosfile_create_dir(".WWW", 0); + xosfile_create_dir(".WWW.NetSurf", 0); + + /* 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. This could be done in a far more elegant manner, but it's late and my girlfriend will kill me if I don't go to bed soon. Sorry. @@ -215,7 +240,7 @@ void ro_gui_hotlist_init(void) { warn_user("MiscError", error->errmess); return; } - + /* Update our text icon */ text_icon.data.indirected_text.validation = null_text_string; @@ -226,7 +251,7 @@ void ro_gui_hotlist_init(void) { (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; - + /* Create our window */ error = xwimp_create_window(&hotlist_window_definition, &hotlist_window); @@ -234,23 +259,12 @@ void ro_gui_hotlist_init(void) { warn_user("WimpError", error->errmess); return; } - - /* Set the root options - */ - root.next_entry = NULL; - root.child_entry = NULL; - root.children = 0; - root.expanded = true; - - /* Load the hotlist - */ - ro_gui_hotlist_load(); } /** * Shows the hotlist window. - */ + */ void ro_gui_hotlist_show(void) { os_error *error; int screen_width, screen_height; @@ -275,14 +289,15 @@ void ro_gui_hotlist_show(void) { open in the centre of the screen. */ if (!(state.flags & wimp_WINDOW_OPEN)) { - /* Clear the selection state + /* Clear the selection/expansion states */ + ro_gui_hotlist_update_expansion(root.child_entry, false, false, true); ro_gui_hotlist_selection_state(root.child_entry, false, false); /* Get the current screen size */ ro_gui_screen_size(&screen_width, &screen_height); - + /* Move to the centre */ dimension = state.visible.x1 - state.visible.x0; @@ -304,35 +319,97 @@ void ro_gui_hotlist_show(void) { } } -void ro_gui_hotlist_load(void) { +bool ro_gui_hotlist_load(void) { + FILE *fp; + fileswitch_object_type obj_type = 0; struct hotlist_entry *netsurf; struct hotlist_entry *entry; + bool success; - /* Create a folder + /* Check if we have an initial hotlist. OS_File does funny things relating to errors, + so we use the object type to determine success */ - netsurf = ro_gui_hotlist_create("NetSurf", NULL, 0, &root); - netsurf->expanded = true; + xosfile_read_stamped_no_path(".WWW.NetSurf.Hotlist", &obj_type, + (bits)0, (bits)0, 0, (fileswitch_attr)0, (bits)0); + if (obj_type != 0) { + /* Open our file + */ + fp = fopen(".WWW.NetSurf.Hotlist", "r"); + if (!fp) { + warn_user("HotlistLoadError", 0); + return false; + } + + /* Start our recursive load + */ + success = ro_gui_hotlist_load_entry(fp, root); + + /* Tell the user if we had any problems + */ + if (!success) { + warn_user("HotlistLoadError", 0); + } + + /* Close our file and return + */ + fclose(fp); + return success; + } else { + /* Create a folder + */ + netsurf = ro_gui_hotlist_create("NetSurf", NULL, 0, &root); + + /* Add some content + */ + entry = ro_gui_hotlist_create("NetSurf homepage", "http://netsurf.sf.net", + 0xfaf, netsurf); + entry->add_date = (time_t)-1; + entry = ro_gui_hotlist_create("NetSurf test builds", "http://netsurf.strcprstskrzkrk.co.uk", + 0xfaf, netsurf); + entry->add_date = (time_t)-1; + + /* We succeeded + */ + return true; + } +} - /* Add some content +void ro_gui_hotlist_save(void) { + FILE *fp; + + /* Open our file + */ + fp = fopen(".WWW.NetSurf.Hotlist", "w"); + if (!fp) { + warn_user("HotlistSaveError", 0); + return; + } + + /* Start our recursive save */ - entry = ro_gui_hotlist_create("NetSurf homepage", "http://netsurf.sf.net", - 0xfaf, netsurf); - entry->add_date = (time_t)-1; - entry = ro_gui_hotlist_create("NetSurf test builds", "http://netsurf.strcprstskrzkrk.co.uk", - 0xfaf, netsurf); - entry->add_date = (time_t)-1; + if (!ro_gui_hotlist_save_entry(fp, root)) { + warn_user("HotlistSaveError", 0); + } + + /* Close our file + */ + fclose(fp); } -void ro_gui_hotlist_save(void) { +bool ro_gui_hotlist_save_entry(FILE *fp, struct hotlist_entry entry) { + return false; } +bool ro_gui_hotlist_load_entry(FILE *fp, struct hotlist_entry entry) { + return false; +} /** * 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(title, content->url, ro_content_filetype(content), &root); } @@ -345,7 +422,7 @@ void ro_gui_hotlist_add(char *title, struct content *content) { */ void hotlist_visited(struct content *content) { if ((!content) || (!content->url)) return; - ro_gui_hotlist_visited_update(content, root.child_entry); + ro_gui_hotlist_visited_update(content, root.child_entry); } @@ -358,7 +435,7 @@ void hotlist_visited(struct content *content) { void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry *entry) { char *url; bool full = false; - + /* Update the hotlist */ url = content->url; @@ -368,16 +445,16 @@ void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry /* Check if we're going to need a full redraw downwards */ full = ((entry->visits == 0) || (entry->last_date == -1)); - + /* Update our values */ entry->visits++; entry->last_date = time(NULL); - + /* Update the entry width (extreme case - never likely to happen) */ ro_gui_hotlist_update_entry_size(entry); - + /* Redraw the least we can get away with */ if (entry->expanded) { @@ -395,7 +472,7 @@ void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry } } if (entry->child_entry) { - ro_gui_hotlist_visited_update(content, entry->child_entry); + ro_gui_hotlist_visited_update(content, entry->child_entry); } entry = entry->next_entry; } @@ -408,11 +485,11 @@ void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry * \param title the entry title * \param url the entry url (NULL to create a folder) * \param folder the folder to add the entry into - */ + */ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, int filetype, struct hotlist_entry *folder) { struct hotlist_entry *entry; - + /* Check we have a title or a URL */ if (!title && !url) return NULL; @@ -424,7 +501,7 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, warn_user("NoMemory", 0); return NULL; } - + /* And enough for the url/title */ if (url) { @@ -432,7 +509,7 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, if (!entry->url) { warn_user("NoMemory", 0); free(entry); - return NULL; + return NULL; } strcpy(entry->url, url); } @@ -445,43 +522,43 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, warn_user("NoMemory", 0); free(entry->url); free(entry); - return NULL; + return NULL; } strcpy(entry->title, title); } else { - entry->title = entry->url; + entry->title = entry->url; } - + /* Set the children count */ if (url) { - entry->children = -1; + entry->children = -1; } else { entry->children = 0; } - + /* Set the filetype */ entry->filetype = filetype; - + /* Set the default values */ entry->visits = 0; - + /* Get our dates */ entry->add_date = time(NULL); entry->last_date = (time_t)-1; - + /* Set the expanded/selected state */ entry->expanded = false; entry->selected = false; - + /* Set the width */ ro_gui_hotlist_update_entry_size(entry); - + /* Link in as the last entry in root */ ro_gui_hotlist_link_entry(folder, entry); @@ -494,16 +571,16 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, * * \param parent the parent entry to link under * \param entry the entry to link - */ + */ void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entry *entry) { struct hotlist_entry *link_entry; if (!parent || !entry) return; - + /* Ensure the parent is a folder */ if (parent->children == -1) return; - + /* Get the first child entry */ link_entry = parent->child_entry; @@ -513,7 +590,7 @@ void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entr while (link_entry->next_entry) link_entry = link_entry->next_entry; link_entry->next_entry = entry; } - + /* Increment the number of children */ parent->children += 1; @@ -532,15 +609,15 @@ 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) { @@ -558,7 +635,7 @@ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { if (width > max_width) max_width = width; entry->widths[line_number++] = width; } - + /* Get the width of the add date */ if (entry->add_date != -1) { @@ -570,7 +647,7 @@ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { if (width > max_width) max_width = width; entry->widths[line_number++] = width; } - + /* Get the width of the last visit */ if (entry->last_date != -1) { @@ -582,7 +659,7 @@ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { if (width > max_width) max_width = width; entry->widths[line_number++] = width; } - + /* Get the width of the visit count */ if (entry->visits > 0) { @@ -594,7 +671,7 @@ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { if (width > max_width) max_width = width; entry->widths[line_number++] = width; } - + /* Increase the text width by the borders */ entry->expanded_width = max_width + 32 + 36 + 16; @@ -605,7 +682,7 @@ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { /** * Redraws a section of the hotlist window - * + * * \param redraw the area to redraw */ void ro_gui_hotlist_redraw(wimp_draw *redraw) { @@ -613,12 +690,12 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { osbool more; unsigned int size; os_box extent = {0, 0, 0, 0};; - + /* Reset our min/max sizes */ max_width = 0; max_height = 0; - + /* Get a pixel translation table for the sprites. We only get one for all the sprites, so they must all have the same characteristics. @@ -627,7 +704,7 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, 0, colourtrans_GIVEN_SPRITE, 0, 0, &size); pixel_table = malloc(size); - if (pixel_table) { + if (pixel_table) { xcolourtrans_generate_table_for_sprite(gui_sprites, sprite[HOTLIST_EXPAND], colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, pixel_table, colourtrans_GIVEN_SPRITE, 0, 0, 0); @@ -649,12 +726,12 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { origin_x + 8, origin_y - 4); more = wimp_get_rectangle(redraw); } - + /* Free our memory */ if (pixel_table) free(pixel_table); pixel_table = NULL; - + /* Check if we should reformat */ if (reformat_pending) { @@ -687,13 +764,13 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i 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 + 32, y0); @@ -736,7 +813,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i y0 -= 44; height -= 44; } - + /* Draw the rest of the lines */ while (height > 0) { @@ -748,7 +825,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i y0 -= 44; height -= 44; } - + } else { /* Draw a half-line for the last entry */ @@ -777,17 +854,17 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i gui_sprites, sprite[HOTLIST_COLLAPSE], x0, box_y0 - 31, osspriteop_USE_MASK | osspriteop_USE_PALETTE, - 0, pixel_table); + 0, pixel_table); } else { xosspriteop_put_sprite_scaled(osspriteop_PTR, gui_sprites, sprite[HOTLIST_EXPAND], x0, box_y0 - 31, osspriteop_USE_MASK | osspriteop_USE_PALETTE, 0, pixel_table); - - + + } - + } /* Move to the next entry @@ -795,7 +872,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i entry = entry->next_entry; first = false; } - + /* Return our height */ return cumulative; @@ -815,7 +892,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i int height = 44; int line_y0; int line_height; - + /* Set the correct height */ if ((entry->children == -1) && (entry->expanded)) { @@ -824,13 +901,13 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i if (entry->add_date != -1) height += 44; if (entry->last_date != -1) height += 44; } - + /* 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) | @@ -856,7 +933,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i /* Check it exists (pre-OS3.5) */ if (xwimpspriteop_read_sprite_info(icon_name, 0, 0, 0, 0)) { - sprintf(icon_name, "small_dir"); + sprintf(icon_name, "small_dir"); } } else { sprintf(icon_name, "small_dir"); @@ -865,11 +942,11 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i /* Get the icon sprite */ sprintf(icon_name, "small_%x", entry->filetype); - + /* Check it exists */ if (xwimpspriteop_read_sprite_info(icon_name, 0, 0, 0, 0)) { - sprintf(icon_name, "small_xxx"); + sprintf(icon_name, "small_xxx"); } } xwimp_plot_icon(&sprite_icon); @@ -896,7 +973,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED; text_icon.extent.y0 = y0 - origin_y - 44; text_icon.extent.y1 = y0 - origin_y; - + /* Draw the lines */ y0 -= 44; @@ -915,13 +992,13 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i x0 + 16, line_y0 - 44, osspriteop_USE_MASK | osspriteop_USE_PALETTE, 0, pixel_table); - + } xosspriteop_put_sprite_scaled(osspriteop_PTR, gui_sprites, sprite[HOTLIST_ENTRY], x0 + 8, line_y0 - 29, osspriteop_USE_MASK | osspriteop_USE_PALETTE, - 0, pixel_table); + 0, pixel_table); line_height -= 44; line_y0 -= 44; } @@ -946,7 +1023,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i text_icon.extent.y1 -= 44; xwimp_plot_icon(&text_icon); } - + /* Plot the date added text */ if (entry->add_date != -1) { @@ -966,7 +1043,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i text_icon.extent.y1 -= 44; xwimp_plot_icon(&text_icon); } - + /* Plot the visit count text */ if (entry->visits > 0) { @@ -995,6 +1072,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i * /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; @@ -1003,6 +1081,7 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { int x_offset; int y_offset; bool no_entry = false; + os_error *error; /* Get the button state */ @@ -1018,8 +1097,25 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { */ 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); @@ -1030,6 +1126,7 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { y_offset = y - (entry->y0 + entry->height); if (((x_offset < 32) && (y_offset > -44)) || ((entry->children != -1) && ((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)))) { + ro_gui_hotlist_update_expansion(entry->child_entry, false, false, true); ro_gui_hotlist_selection_state(entry->child_entry, false, false); entry->expanded = !entry->expanded; @@ -1039,32 +1136,36 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { 0, -16384, 16384, entry->y0 + entry->height); } else if (x_offset >= 32) { + + /* 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) == 0) { + buttons = (wimp_CLICK_SELECT << 8); + } + } + /* Check for selection */ if (buttons == (wimp_CLICK_SELECT << 8)) { - if (entry->selected) { - entry->selected = false; - ro_gui_hotlist_selection_state(root.child_entry, - false, true); - entry->selected = true; - } else { + if (!entry->selected) { ro_gui_hotlist_selection_state(root.child_entry, false, true); entry->selected = true; xwimp_force_redraw(hotlist_window, entry->x0, entry->y0 + entry->height - 44, entry->x0 + entry->width, - entry->y0 + entry->height); + entry->y0 + entry->height); } } else if (buttons == (wimp_CLICK_ADJUST << 8)) { entry->selected = !entry->selected; xwimp_force_redraw(hotlist_window, entry->x0, entry->y0 + entry->height - 44, entry->x0 + entry->width, - entry->y0 + entry->height); - + entry->y0 + entry->height); + } - + /* Check if we should open the URL */ if (((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)) && @@ -1084,7 +1185,17 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { } else { no_entry = true; } - + + /* Get the original button state back + */ + buttons = pointer->buttons; + + /* Create a menu if we should + */ + if (buttons == (wimp_CLICK_MENU << 8)) { +/* todo: menu */ + return; + } /* Handle a click without an entry */ @@ -1095,12 +1206,12 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { ro_gui_hotlist_selection_state(root.child_entry, false, true); } - + /* Handle the start of a drag */ - if (buttons == (wimp_CLICK_SELECT << 4) || + if (buttons == (wimp_CLICK_SELECT << 4) || buttons == (wimp_CLICK_ADJUST << 4)) { - + /* Clear the current selection */ if (buttons == (wimp_CLICK_SELECT << 4)) { @@ -1112,17 +1223,17 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { */ 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; - xwimp_drag_box(&drag); + 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; + xwimp_drag_box(&drag); } } } @@ -1140,7 +1251,7 @@ struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_ent 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; @@ -1159,19 +1270,19 @@ struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_ent if (x < (entry->x0 + entry->collapsed_width)) return entry; return NULL; } - + /* No other entry can occupy the left edge */ inset_x = x - entry->x0 - 32 - 36; if (inset_x < 0) return NULL; - + /* Check the right edge against our various widths */ inset_y = -((y - entry->y0 - entry->height) / 44); if (inset_x < (entry->widths[inset_y - 1] + 16)) return entry; - return NULL; + return NULL; } - + /* Continue onwards */ if ((entry->child_entry) && (entry->expanded)) { @@ -1209,7 +1320,7 @@ int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, b */ entry->selected = selected; changes++; - + /* Redraw the entrys first line */ if (redraw) { @@ -1231,15 +1342,99 @@ int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, b return changes; } +int ro_gui_hotlist_selection_count(struct hotlist_entry *entry) { + int count = 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) count++; + + /* Continue onwards + */ + if (entry->child_entry) { + count += ro_gui_hotlist_selection_count(entry->child_entry); + } + entry = entry->next_entry; + } + return count; +} + + +/** + * 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 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 expand, bool contract) { + bool current; + /* 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; + /* Update the selection 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, false, true); + ro_gui_hotlist_selection_state(entry->child_entry, false, false); + } + + /* Redraw the entrys first line + */ + if (current != entry->expanded) { + xwimp_force_redraw(hotlist_window, + 0, -16384, 16384, + entry->y0 + entry->height); + } + } + + /* 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, expand, contract); + } + entry = entry->next_entry; + } +} + /** * Updated the selection state of the tree * * \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 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 */ @@ -1262,7 +1457,7 @@ void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, if ((x1 > (entry->x0 + 32)) && (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 + 32)) && (y0 > entry->y0 + entry->height - 44) && @@ -1295,7 +1490,7 @@ void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, if (toggle) { entry->selected = !entry->selected; } else { - entry->selected = true; + entry->selected = true; } if (redraw) { xwimp_force_redraw(hotlist_window, @@ -1305,7 +1500,7 @@ void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, } } } - + /* Continue onwards */ if ((entry->child_entry) && (entry->expanded)) { @@ -1325,20 +1520,20 @@ void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, */ void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag) { wimp_window_state state; - int x0, y0, x1, y1; - + int x0, y0, x1, y1; + /* 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; y1 = drag->final.y1 - state.visible.y1 - state.yscroll; - + /* Make sure x0 < x1 and y0 > y1 */ if (x0 > x1) { @@ -1350,15 +1545,15 @@ void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag) { 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); - } + } + + /* 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); + } } @@ -1368,11 +1563,73 @@ void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag) { * \param drag the final drag co-ordinates */ void ro_gui_hotlist_move_drag_end(wimp_dragged *drag) { - + } +/** + * Handle a keypress + * + * \param key the key pressed + * \return whether the key was processed + */ +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); + return true; + case 26: /* CTRL+Z */ + ro_gui_hotlist_selection_state(root.child_entry, false, true); + return true; + case 32: /* SPACE */ + ro_gui_hotlist_update_expansion(root.child_entry, true, false, false); + 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; +} @@ -1412,10 +1669,10 @@ char *last_visit_to_string(time_t last_visit) seconds = difference; - if (years > 0) len += 8; /* '99 years' */ - if (weeks > 0) len += 8 + (len > 0 ? 1 : 0); /* '51 weeks' */ - if (days > 0) len += 6 + (len > 0 ? 1 : 0); /* '6 days' */ - if (hours > 0) len += 8 + (len > 0 ? 1 : 0); /* '23 hours' */ + if (years > 0) len += 8; /* '99 years' */ + if (weeks > 0) len += 8 + (len > 0 ? 1 : 0); /* '51 weeks' */ + if (days > 0) len += 6 + (len > 0 ? 1 : 0); /* '6 days' */ + if (hours > 0) len += 8 + (len > 0 ? 1 : 0); /* '23 hours' */ if (minutes > 0) len += 10 + (len > 0 ? 1 : 0); /* '59 minutes' */ if (seconds > 0) len += 10 + (len > 0 ? 1 : 0); /* '59 seconds' */ len += 4; diff --git a/riscos/menus.c b/riscos/menus.c index 580c719a2..3f3e263b7 100644 --- a/riscos/menus.c +++ b/riscos/menus.c @@ -16,6 +16,7 @@ #include #include "oslib/os.h" #include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" #include "netsurf/desktop/gui.h" #include "netsurf/riscos/gui.h" #include "netsurf/riscos/help.h" @@ -857,6 +858,14 @@ void ro_gui_menu_prepare_save(struct content *c) if ((nice = url_nice(c->url))) name = nice; + /* Ensure the correct icon exists + */ + if (xwimpspriteop_read_sprite_info(icon, 0, 0, 0, 0)) { + icon = "file_xxx"; + } + + /* Update the GUI + */ ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_ICON, icon); ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, name); } diff --git a/riscos/window.c b/riscos/window.c index b765b361c..bbcc01d99 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -809,7 +809,9 @@ void ro_gui_window_click(gui_window* g, wimp_pointer* pointer) { return; } - if (pointer->buttons == wimp_CLICK_SELECT && caret.w != state.w) { + if (((pointer->buttons == wimp_CLICK_SELECT) || + (pointer->buttons == wimp_CLICK_ADJUST)) && + (caret.w != state.w)) { error = xwimp_set_caret_position(state.w, -1, -100, -100, 32, -1); if (error) { -- cgit v1.2.3