From 9c1cb7bb2d712048f18a02441068b91d727cbcad Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Sat, 23 Apr 2005 02:58:27 +0000 Subject: [project @ 2005-04-23 02:58:27 by adrianl] Query windows, desktop save protocol, confirm abort/quit when downloads in progress svn path=/import/netsurf/; revision=1679 --- makefile | 2 +- riscos/dialog.c | 2 +- riscos/download.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++- riscos/gui.c | 95 +++++++++++++++++++++++++++++++++++++++++++- riscos/gui.h | 7 ++++ riscos/menus.c | 3 +- utils/utils.h | 21 ++++++++++ 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); @@ -1754,6 +1775,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. * @@ -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 -- cgit v1.2.3