summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--!NetSurf/Resources/en/Messages2
-rw-r--r--!NetSurf/Resources/fr/Messages2
-rw-r--r--riscos/gui.c11
-rw-r--r--riscos/gui.h1
-rw-r--r--riscos/hotlist.c579
-rw-r--r--riscos/menus.c9
-rw-r--r--riscos/window.c4
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 <stdlib.h>
#include <time.h>
#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("<Choices$Write>.WWW", 0);
+ xosfile_create_dir("<Choices$Write>.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("<Choices$Write>.WWW.NetSurf.Hotlist", &obj_type,
+ (bits)0, (bits)0, 0, (fileswitch_attr)0, (bits)0);
+ if (obj_type != 0) {
+ /* Open our file
+ */
+ fp = fopen("<Choices$Write>.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("<Choices$Write>.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 <string.h>
#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) {