summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile2
-rw-r--r--riscos/dialog.c2
-rw-r--r--riscos/download.c117
-rw-r--r--riscos/gui.c95
-rw-r--r--riscos/gui.h7
-rw-r--r--riscos/menus.c3
-rw-r--r--utils/utils.h21
7 files changed, 241 insertions, 6 deletions
diff --git a/makefile b/makefile
index 60d14523f..b75ac436a 100644
--- a/makefile
+++ b/makefile
@@ -32,7 +32,7 @@ OBJECTS_RISCOS += browser.o netsurf.o selection.o textinput.o version.o # desk
OBJECTS_RISCOS += 401login.o bitmap.o buffer.o debugwin.o \
dialog.o download.o draw.o filetype.o font.o \
global_history.o gui.o help.o history.o hotlist.o image.o \
- menus.o mouseactions.o plotters.o plugin.o print.o \
+ menus.o mouseactions.o plotters.o plugin.o print.o query.o \
save.o save_complete.o save_draw.o save_text.o \
schedule.o search.o sprite.o textselection.o theme.o \
theme_install.o thumbnail.o treeview.o ucstables.o uri.o \
diff --git a/riscos/dialog.c b/riscos/dialog.c
index f97c4604f..599355ebf 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -39,7 +39,7 @@
wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
- dialog_config_prox, dialog_config_th, download_template,
+ dialog_config_prox, dialog_config_th,
#ifdef WITH_AUTH
dialog_401li,
#endif
diff --git a/riscos/download.c b/riscos/download.c
index 5cd8d3a1d..1a1932588 100644
--- a/riscos/download.c
+++ b/riscos/download.c
@@ -31,6 +31,7 @@
#include "netsurf/content/fetch.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/riscos/gui.h"
+#include "netsurf/riscos/query.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
@@ -55,11 +56,15 @@ struct gui_download_window {
/** User has chosen the destination, and it is being written. */
bool saved;
+ bool close_confirmed;
bool error; /**< Error occurred, aborted. */
/** RISC OS file handle, of temporary file when !saved, and of
* destination when saved. */
os_fw file;
+ query_id query;
+ bool query_quit;
+
struct timeval start_time; /**< Time download started. */
struct timeval last_time; /**< Time status was last updated. */
unsigned int last_received; /**< Value of received at last_time. */
@@ -88,6 +93,15 @@ static int download_progress_y1;
static void ro_gui_download_update_status(struct gui_download_window *dw);
static void ro_gui_download_update_status_wrapper(void *p);
static void ro_gui_download_window_destroy_wrapper(void *p);
+static void ro_gui_download_close_confirmed(query_id, enum query_response res, void *p);
+static void ro_gui_download_close_cancelled(query_id, enum query_response res, void *p);
+
+static const query_callback close_funcs =
+{
+ ro_gui_download_close_confirmed,
+ ro_gui_download_close_cancelled,
+ ro_gui_download_close_cancelled
+};
/**
@@ -138,7 +152,9 @@ struct gui_download_window *gui_download_window_create(const char *url,
dw->fetch = fetch;
dw->saved = false;
+ dw->close_confirmed = false;
dw->error = false;
+ dw->query = QUERY_INVALID;
dw->received = 0;
dw->total_size = total_size;
strncpy(dw->url, url, sizeof dw->url);
@@ -557,6 +573,7 @@ void ro_gui_download_datasave_ack(wimp_message *message)
char *file_name;
struct gui_download_window *dw = download_window_current;
os_error *error;
+ wimp_caret caret;
if (dw->saved || dw->error)
return;
@@ -675,6 +692,22 @@ void ro_gui_download_datasave_ack(wimp_message *message)
warn_user("WimpError", error->errmess);
}
+ /* hide the caret but preserve input focus */
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG(("xwimp_get_caret_position: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ else if (caret.w == dw->window) {
+ error = xwimp_set_caret_position(dw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
+ if (error) {
+ LOG(("xwimp_get_caret_position: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+
/* Ack successful save with message_DATA_LOAD */
message->action = message_DATA_LOAD;
message->your_ref = message->my_ref;
@@ -703,6 +736,21 @@ void ro_gui_download_window_destroy(struct gui_download_window *dw)
char temp_name[40];
os_error *error;
+ if (!dw->saved && !dw->close_confirmed)
+ {
+ if (dw->query != QUERY_INVALID && dw->query_quit) {
+ query_close(dw->query);
+ dw->query = QUERY_INVALID;
+ }
+
+ dw->query_quit = false;
+ if (dw->query == QUERY_INVALID)
+ dw->query = query_user("AbortDownload", NULL, &close_funcs, dw);
+ else
+ ro_gui_query_window_bring_to_front(dw->query);
+ return;
+ }
+
schedule_remove(ro_gui_download_update_status_wrapper, dw);
schedule_remove(ro_gui_download_window_destroy_wrapper, dw);
@@ -757,5 +805,72 @@ void ro_gui_download_window_destroy(struct gui_download_window *dw)
void ro_gui_download_window_destroy_wrapper(void *p)
{
- ro_gui_download_window_destroy((struct gui_download_window *) p);
+ struct gui_download_window *dw = p;
+ if (dw->query != QUERY_INVALID)
+ query_close(dw->query);
+ dw->query = QUERY_INVALID;
+ ro_gui_download_window_destroy(dw);
+}
+
+
+/**
+ * User has opted to cancel the close, leaving the download to continue.
+ */
+
+void ro_gui_download_close_cancelled(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = p;
+ dw->query = QUERY_INVALID;
+}
+
+
+/**
+ * Download aborted, close window and tidy up.
+ */
+
+void ro_gui_download_close_confirmed(query_id id, enum query_response res, void *p)
+{
+ struct gui_download_window *dw = (struct gui_download_window *)p;
+ dw->query = QUERY_INVALID;
+ dw->close_confirmed = true;
+ if (dw->query_quit) {
+
+ /* destroy all our downloads */
+ while (download_window_list)
+ ro_gui_download_window_destroy_wrapper(download_window_list);
+
+ /* and restart the shutdown */
+ if (ro_gui_prequit())
+ netsurf_quit = true;
+ }
+ else
+ ro_gui_download_window_destroy(dw);
+}
+
+
+/**
+ * Respond to PreQuit message, displaying a prompt message if we need
+ * the user to confirm the shutdown.
+ *
+ * \return true iff we can shutdown straightaway
+ */
+
+bool ro_gui_download_prequit(void)
+{
+ if (download_window_list) {
+ struct gui_download_window *dw = download_window_list;
+
+ if (dw->query != QUERY_INVALID && !dw->query_quit) {
+ query_close(dw->query);
+ dw->query = QUERY_INVALID;
+ }
+
+ dw->query_quit = true;
+ if (dw->query == QUERY_INVALID)
+ dw->query = query_user("QuitDownload", NULL, &close_funcs, dw);
+ else
+ ro_gui_query_window_bring_to_front(dw->query);
+ return false;
+ }
+ return true;
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 0d35ed78d..cb0fc27ab 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -27,6 +27,7 @@
#include "oslib/osbyte.h"
#include "oslib/osfile.h"
#include "oslib/osfscontrol.h"
+#include "oslib/osgbpb.h"
#include "oslib/osspriteop.h"
#include "oslib/pdriver.h"
#include "oslib/plugin.h"
@@ -56,6 +57,7 @@
#ifdef WITH_PRINT
#include "netsurf/riscos/print.h"
#endif
+#include "netsurf/riscos/query.h"
#include "netsurf/riscos/save_complete.h"
#include "netsurf/riscos/theme.h"
#include "netsurf/riscos/treeview.h"
@@ -135,13 +137,15 @@ static clock_t gui_last_poll; /**< Time of last wimp_poll. */
osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
/** Accepted wimp user messages. */
-static wimp_MESSAGE_LIST(36) task_messages = { {
+static wimp_MESSAGE_LIST(38) task_messages = { {
message_HELP_REQUEST,
message_DATA_SAVE,
message_DATA_SAVE_ACK,
message_DATA_LOAD,
message_DATA_LOAD_ACK,
message_DATA_OPEN,
+ message_PRE_QUIT,
+ message_SAVE_DESKTOP,
message_MENU_WARNING,
message_MENUS_DELETED,
message_MODE_CHANGE,
@@ -215,6 +219,8 @@ static char *ro_gui_ieurl_file_parse(const char *file_name);
static void ro_msg_datasave(wimp_message *message);
static void ro_msg_datasave_ack(wimp_message *message);
static void ro_msg_dataopen(wimp_message *block);
+static void ro_msg_prequit(wimp_message *message);
+static void ro_msg_save_desktop(wimp_message *message);
static char *ro_path_to_url(const char *path);
@@ -329,6 +335,7 @@ void gui_init(int argc, char** argv)
ro_gui_dialog_init();
ro_gui_download_init();
ro_gui_menu_init();
+ ro_gui_query_init();
#ifdef WITH_AUTH
ro_gui_401login_init();
#endif
@@ -1011,6 +1018,7 @@ void ro_gui_mouse_click(wimp_pointer *pointer)
{
struct gui_window *g;
struct gui_download_window *dw;
+ struct gui_query_window *qw;
if (pointer->w == wimp_ICON_BAR)
ro_gui_icon_bar_click(pointer);
@@ -1046,6 +1054,8 @@ void ro_gui_mouse_click(wimp_pointer *pointer)
ro_gui_status_click(g, pointer);
else if ((dw = ro_gui_download_window_lookup(pointer->w)) != NULL)
ro_gui_download_window_click(dw, pointer);
+ else if ((qw = ro_gui_query_window_lookup(pointer->w)) != NULL)
+ ro_gui_query_window_click(qw, pointer);
else
ro_gui_dialog_click(pointer);
}
@@ -1136,6 +1146,7 @@ void ro_gui_drag_end(wimp_dragged *drag)
void ro_gui_keypress(wimp_key *key)
{
+ struct gui_query_window *qw;
bool handled = false;
struct gui_window *g;
os_error *error;
@@ -1148,6 +1159,8 @@ void ro_gui_keypress(wimp_key *key)
handled = ro_gui_window_keypress(g, key->c, false);
else if ((g = ro_gui_toolbar_lookup(key->w)) != NULL)
handled = ro_gui_window_keypress(g, key->c, true);
+ else if ((qw = ro_gui_query_window_lookup(key->w)) != NULL)
+ handled = ro_gui_query_window_keypress(qw, key);
else
handled = ro_gui_dialog_keypress(key);
@@ -1203,6 +1216,14 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
ro_msg_dataopen(message);
break;
+ case message_PRE_QUIT:
+ ro_msg_prequit(message);
+ break;
+
+ case message_SAVE_DESKTOP:
+ ro_msg_save_desktop(message);
+ break;
+
case message_MENU_WARNING:
ro_gui_menu_warning((wimp_message_menu_warning *)
&message->data);
@@ -1755,6 +1776,64 @@ void ro_msg_dataopen(wimp_message *message)
/**
+ * Handle PreQuit message
+ *
+ * \param message PreQuit message from Wimp
+ */
+
+void ro_msg_prequit(wimp_message *message)
+{
+ if (!ro_gui_prequit()) {
+ os_error *error;
+
+ /* we're objecting to the close down */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
+ message, message->sender);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle SaveDesktop message
+ *
+ * \param message SaveDesktop message from Wimp
+ */
+
+void ro_msg_save_desktop(wimp_message *message)
+{
+ os_error *error;
+
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)"Run ", 4, NULL);
+ if (!error) {
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL);
+ if (!error)
+ error = xos_bputw('\n', message->data.save_desktopw.file);
+ }
+
+ if (error) {
+ LOG(("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess));
+ warn_user("SaveError", error->errmess);
+
+ /* we must cancel the save by acknowledging the message */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
+ message, message->sender);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
* Convert a RISC OS pathname to a file: URL.
*
* \param path RISC OS pathname
@@ -1879,7 +1958,7 @@ void gui_launch_url(const char *url)
void warn_user(const char *warning, const char *detail)
{
- static char warn_buffer[300];
+ char warn_buffer[300];
LOG(("%s %s", warning, detail));
snprintf(warn_buffer, sizeof warn_buffer, "%s %s",
@@ -1918,3 +1997,15 @@ void die(const char *error)
(osspriteop_area *) 1, 0, 0);
exit(EXIT_FAILURE);
}
+
+
+/**
+ * Test whether it's okay to shutdown, prompting the user if not.
+ *
+ * \return true iff it's okay to shutdown immediately
+ */
+
+bool ro_gui_prequit(void)
+{
+ return ro_gui_download_prequit();
+}
diff --git a/riscos/gui.h b/riscos/gui.h
index 6d88a37c7..98064ee13 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -97,6 +97,7 @@ void ro_gui_open_help_page(const char *page);
void ro_gui_screen_size(int *width, int *height);
void ro_gui_view_source(struct content *content);
void ro_gui_drag_box_start(wimp_pointer *pointer);
+bool ro_gui_prequit(void);
/* in dialog.c */
void ro_gui_dialog_init(void);
@@ -126,6 +127,7 @@ void ro_gui_download_window_click(struct gui_download_window *dw,
void ro_gui_download_drag_end(wimp_dragged *drag);
void ro_gui_download_datasave_ack(wimp_message *message);
void ro_gui_download_window_destroy(struct gui_download_window *dw);
+bool ro_gui_download_prequit(void);
/* in mouseactions.c */
void ro_gui_mouse_action(struct gui_window *g);
@@ -379,6 +381,11 @@ void ro_gui_theme_install_click(wimp_pointer *pointer);
#define ICON_WARNING_CONTINUE 1
#define ICON_WARNING_HELP 2
+#define ICON_QUERY_MESSAGE 0
+#define ICON_QUERY_YES 1
+#define ICON_QUERY_NO 2
+#define ICON_QUERY_HELP 3
+
#define ICON_SEARCH_TEXT 0
#define ICON_SEARCH_START 1
#define ICON_SEARCH_CASE_SENSITIVE 2
diff --git a/riscos/menus.c b/riscos/menus.c
index ef1514977..121a18ceb 100644
--- a/riscos/menus.c
+++ b/riscos/menus.c
@@ -1547,7 +1547,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
/* misc actions */
case APPLICATION_QUIT:
- netsurf_quit = true;
+ if (ro_gui_prequit())
+ netsurf_quit = true;
return true;
case CHOICES_SHOW:
ro_gui_dialog_open_config();
diff --git a/utils/utils.h b/utils/utils.h
index e005fcbf7..9bd43a2f3 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -29,6 +29,25 @@
#define max(x,y) (((x)>(y))?(x):(y))
#endif
+enum query_response {
+ QUERY_CONTINUE,
+ QUERY_YES,
+ QUERY_NO,
+ QUERY_ESCAPE
+};
+
+typedef int query_id;
+
+#define QUERY_INVALID ((query_id)-1)
+
+typedef struct
+{
+ void (*confirm)(query_id id, enum query_response res, void *pw);
+ void (*cancel)(query_id, enum query_response res, void *pw);
+ void (*escape)(query_id, enum query_response res, void *pw);
+} query_callback;
+
+
char * strip(char * const s);
int whitespace(const char * str);
char * squash_whitespace(const char * s);
@@ -45,6 +64,8 @@ char *human_friendly_bytesize(unsigned long bytesize);
/* Platform specific functions */
void die(const char * const error);
void warn_user(const char *warning, const char *detail);
+query_id query_user(const char *query, const char *detail, const query_callback *cb, void *pw);
+void query_close(query_id);
const char *local_encoding_name(void);
#endif