From a1d73ecd110f6cc252f6146672802f87cc45723d Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 27 Jun 2004 23:24:11 +0000 Subject: [project @ 2004-06-27 23:24:11 by bursa] Rewritten download window. Now downloads direct to file. New download window gui. svn path=/import/netsurf/; revision=1020 --- riscos/download.c | 727 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 607 insertions(+), 120 deletions(-) (limited to 'riscos/download.c') diff --git a/riscos/download.c b/riscos/download.c index 03d96b9d1..e1599fc46 100644 --- a/riscos/download.c +++ b/riscos/download.c @@ -6,10 +6,26 @@ * Copyright 2003 Rob Jackson */ +/** \file + * Download windows (RISC OS implementation). + * + * This file implements the interface given by desktop/gui.h for download + * windows. Each download window has an associated fetch. Downloads start by + * writing received data to a temporary file. At some point the user chooses + * a destination (by drag & drop), and the temporary file is then moved to the + * destination and the download continues until complete. + */ + #include #include +#include +#include #include "oslib/mimemap.h" +#include "oslib/osargs.h" #include "oslib/osfile.h" +#include "oslib/osfind.h" +#include "oslib/osfscontrol.h" +#include "oslib/osgbpb.h" #include "oslib/wimp.h" #include "oslib/wimpspriteop.h" #include "netsurf/content/fetch.h" @@ -21,8 +37,57 @@ #include "netsurf/utils/utils.h" +/** Data for a download window. */ +struct gui_download_window { + /** Associated fetch, or 0 if the fetch has completed or aborted. */ + struct fetch *fetch; + unsigned int received; /**< Amount of data received so far. */ + unsigned int total_size; /**< Size of resource, or 0 if unknown. */ + + wimp_w window; /**< RISC OS window handle. */ + bits file_type; /**< RISC OS file type. */ + + char url[256]; /**< Buffer for URL icon. */ + char sprite_name[20]; /**< Buffer for sprite icon. */ + char path[256]; /**< Buffer for pathname icon. */ + char status[256]; /**< Buffer for status icon. */ + + /** User has chosen the destination, and it is being written. */ + bool saved; + bool error; /**< Error occurred, aborted. */ + /** RISC OS file handle, of temporary file when !saved, and of + * destination when saved. */ + os_fw file; + + 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. */ + + struct gui_download_window *prev; /**< Previous in linked list. */ + struct gui_download_window *next; /**< Next in linked list. */ +}; + + +/** List of all download windows. */ +static struct gui_download_window *download_window_list = 0; +/** Download window with current save operation. */ +static struct gui_download_window *download_window_current = 0; + +/** Template for a download window. */ static wimp_window *download_template; +/** Width of progress bar at 100%. */ +static int download_progress_width; +/** Coordinates of progress bar. */ +static int download_progress_x0; +static int download_progress_y0; +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); + /** * Load the download window template. @@ -31,164 +96,427 @@ static wimp_window *download_template; void ro_gui_download_init(void) { download_template = ro_gui_dialog_load_template("download"); + download_progress_width = + download_template->icons[ICON_DOWNLOAD_STATUS].extent.x1 - + download_template->icons[ICON_DOWNLOAD_STATUS].extent.x0; + download_progress_x0 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.x0; + download_progress_y0 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y0; + download_progress_y1 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y1; } /** * Create and open a download progress window. + * + * \param url URL of download + * \param mime_type MIME type sent by server + * \param fetch fetch structure + * \param total_size size of resource, or 0 if unknown + * \return a new gui_download_window structure, or 0 on error and error + * reported */ -gui_window *gui_create_download_window(struct content *content) +struct gui_download_window *gui_download_window_create(const char *url, + const char *mime_type, struct fetch *fetch, + unsigned int total_size) { char *nice; - gui_window *g = xcalloc(1, sizeof(gui_window)); - os_error *e; + char temp_name[40]; + struct gui_download_window *dw; + os_error *error; - assert(content->type == CONTENT_OTHER); + dw = malloc(sizeof *dw); + if (!dw) { + warn_user("NoMemory", 0); + return 0; + } - g->type = GUI_DOWNLOAD_WINDOW; - g->data.download.content = content; + dw->fetch = fetch; + dw->saved = false; + dw->error = false; + dw->received = 0; + dw->total_size = total_size; + strncpy(dw->url, url, sizeof dw->url); + dw->url[sizeof dw->url - 1] = 0; + dw->status[0] = 0; + gettimeofday(&dw->start_time, 0); + dw->last_time = dw->start_time; + dw->last_received = 0; /* convert MIME type to RISC OS file type */ - e = xmimemaptranslate_mime_type_to_filetype(content->mime_type, - &(g->data.download.file_type)); - if (e) - g->data.download.file_type = 0xffd; + error = xmimemaptranslate_mime_type_to_filetype(mime_type, + &(dw->file_type)); + if (error) { + LOG(("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); + dw->file_type = 0xffd; + } + + /* open temporary output file */ + snprintf(temp_name, sizeof temp_name, ".ns%x", + (unsigned int) dw); + error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR, + temp_name, 0, &dw->file); + if (error) { + LOG(("xosfind_openoutw: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + free(dw); + return 0; + } /* fill in download window icons */ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text = - content->url; + dw->url; download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size = - strlen(content->url) + 1; - strncpy(g->status, content->status_message, 256); - download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text.text = - g->status; - download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text.size = - 256; - sprintf(g->data.download.sprite_name, "file_%.3x", - g->data.download.file_type); - e = xwimpspriteop_select_sprite(g->data.download.sprite_name, 0); - if (e) - strcpy(g->data.download.sprite_name, "file_xxx"); + sizeof dw->url; + + download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. + text = dw->status; + download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. + size = sizeof dw->status; + + sprintf(dw->sprite_name, "file_%.3x", dw->file_type); + error = xwimpspriteop_select_sprite(dw->sprite_name, 0); + if (error) { + if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) { + LOG(("xwimpspriteop_select_sprite: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); + } + strcpy(dw->sprite_name, "file_xxx"); + } download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id = - (osspriteop_id) g->data.download.sprite_name; - strcpy(g->data.download.path, messages_get("SaveObject")); - if ((nice = url_nice(content->url))) { - strcpy(g->data.download.path, nice); + (osspriteop_id) dw->sprite_name; + + strcpy(dw->path, messages_get("SaveObject")); + if ((nice = url_nice(url))) { + strcpy(dw->path, nice); free(nice); } download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text = - g->data.download.path; + dw->path; download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size = - 256; + sizeof dw->path; + + download_template->icons[ICON_DOWNLOAD_DESTINATION].data. + indirected_text.text = dw->path; + download_template->icons[ICON_DOWNLOAD_DESTINATION].data. + indirected_text.size = sizeof dw->path; + + download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |= + wimp_ICON_DELETED; /* create and open the download window */ - g->window = wimp_create_window(download_template); - ro_gui_dialog_open(g->window); + error = xwimp_create_window(download_template, &dw->window); + if (error) { + LOG(("xwimp_create_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + free(dw); + return 0; + } + + dw->prev = 0; + dw->next = download_window_list; + download_window_list = dw; + + ro_gui_download_update_status(dw); + + ro_gui_dialog_open(dw->window); - g->data.download.download_status = download_INCOMPLETE; + return dw; +} + + +/** + * Handle received download data. + * + * \param dw download window + * \param data pointer to block of data received + * \param size size of data + */ + +void gui_download_window_data(struct gui_download_window *dw, const char *data, + unsigned int size) +{ + int unwritten; + os_error *error; + + error = xosgbpb_writew(dw->file, data, size, &unwritten); + if (error) { + LOG(("xosgbpb_writew: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); + return; + } + if (unwritten) { + LOG(("xosgbpb_writew: unwritten %i", unwritten)); + warn_user("SaveError", messages_get("Unwritten")); + fetch_abort(dw->fetch); + gui_download_window_error(dw, messages_get("Unwritten")); + return; + } + + dw->received += size; +} + + +/** + * Update the status text and progress bar. + * + * \param dw download window + */ + +void ro_gui_download_update_status(struct gui_download_window *dw) +{ + char *received; + char *total_size; + char *speed; + char time[20] = "?"; + float f = 0; + struct timeval t; + float dt; + unsigned int left; + float rate; + os_error *error; + + gettimeofday(&t, 0); + dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec + + 0.000001 * dw->last_time.tv_usec); + if (dt == 0) + dt = 0.001; + + total_size = human_friendly_bytesize(dw->total_size); + + if (dw->fetch) { + rate = (dw->received - dw->last_received) / dt; + received = human_friendly_bytesize(dw->received); + speed = human_friendly_bytesize(rate); + if (dw->total_size) { + if (rate) { + left = (dw->total_size - dw->received) / rate; + sprintf(time, "%u:%.2u", left / 60, left % 60); + } + snprintf(dw->status, sizeof dw->status, + messages_get("Download"), + received, total_size, speed, time); + } else { + left = t.tv_sec - dw->start_time.tv_sec; + sprintf(time, "%u:%.2u", left / 60, left % 60); + snprintf(dw->status, sizeof dw->status, + messages_get("DownloadU"), + received, speed, time); + } + } else { + left = dw->last_time.tv_sec - dw->start_time.tv_sec; + rate = (float) dw->received / (float) left; + sprintf(time, "%u:%.2u", left / 60, left % 60); + speed = human_friendly_bytesize(rate); + snprintf(dw->status, sizeof dw->status, + messages_get("Downloaded"), + total_size, speed, time); + } + + dw->last_time = t; + dw->last_received = dw->received; + + if (dw->total_size) + f = (float) dw->received / + (float) dw->total_size; + error = xwimp_resize_icon(dw->window, ICON_DOWNLOAD_PROGRESS, + download_progress_x0, + download_progress_y0, + download_progress_x0 + download_progress_width * f, + download_progress_y1); + if (error) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_STATUS, 0, 0); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } - g->next = window_list; - window_list = g; - return g; + if (dw->fetch) + schedule(100, ro_gui_download_update_status_wrapper, dw); + else + schedule_remove(ro_gui_download_update_status_wrapper, dw); } /** - * Refresh the status icon in the download window. + * Wrapper for ro_gui_download_update_status(), suitable for schedule(). */ -void gui_download_window_update_status(gui_window *g) +void ro_gui_download_update_status_wrapper(void *p) { - strncpy(g->status, g->data.download.content->status_message, 256); - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_STATUS, 0, 0); + ro_gui_download_update_status((struct gui_download_window *) p); } /** * Handle failed downloads. + * + * \param dw download window + * \param error_msg error message */ -void gui_download_window_error(gui_window *g, const char *error) +void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) { - g->data.download.content = 0; + os_error *error; + + dw->fetch = 0; + dw->error = true; + + schedule_remove(ro_gui_download_update_status_wrapper, dw); /* place error message in status icon in red */ - strncpy(g->status, error, 256); - wimp_set_icon_state(g->window, + strncpy(dw->status, error_msg, sizeof dw->status); + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_STATUS, wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT, wimp_ICON_FG_COLOUR); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } - /* grey out file and pathname icons */ - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_ICON, wimp_ICON_SHADED, 0); - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_PATH, wimp_ICON_SHADED, 0); - - g->data.download.download_status = download_ERROR; + /* grey out pathname icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, + wimp_ICON_SHADED, 0); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } } /** * Handle completed downloads. + * + * \param dw download window */ -void gui_download_window_done(gui_window *g) +void gui_download_window_done(struct gui_download_window *dw) { - snprintf(g->status, 256, messages_get("Downloaded"), - human_friendly_bytesize(g->data.download.content->source_size)); - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_STATUS, 0, 0); - - // clear shaded path and icon icons - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_ICON, 0, wimp_ICON_SHADED); - wimp_set_icon_state(g->window, - ICON_DOWNLOAD_PATH, 0, wimp_ICON_SHADED); - - g->data.download.download_status = download_COMPLETE; + os_error *error; + + dw->fetch = 0; + ro_gui_download_update_status(dw); + + error = xosfind_closew(dw->file); + if (error) { + LOG(("xosfind_closew: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + dw->file = 0; + + if (dw->saved) { + error = xosfile_set_type(dw->path, + dw->file_type); + if (error) { + LOG(("xosfile_set_type: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + + schedule(200, ro_gui_download_window_destroy_wrapper, dw); + } } /** - * Handle clicks in a download window. + * Convert a RISC OS window handle to a gui_download_window. + * + * \param w RISC OS window handle + * \return pointer to a structure if found, 0 otherwise */ -void ro_download_window_click(struct gui_window *g, wimp_pointer *pointer) +struct gui_download_window * ro_gui_download_window_lookup(wimp_w w) { - switch (pointer->i) { - case ICON_DOWNLOAD_ABORT: - if (g->data.download.download_status == - download_INCOMPLETE) - fetch_abort(g->data.download.content->fetch); - - ro_download_window_close(g); - break; - - case ICON_DOWNLOAD_ICON: - if (g->data.download.download_status == - download_COMPLETE) { - gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE; - current_gui = g; - ro_gui_drag_icon(pointer); + struct gui_download_window *dw; + for (dw = download_window_list; dw; dw = dw->next) + if (dw->window == w) + return dw; + return 0; +} + + +/** + * Handle Mouse_Click events in a download window. + * + * \param dw download window + * \param pointer block returned by Wimp_Poll + */ + +void ro_gui_download_window_click(struct gui_download_window *dw, + wimp_pointer *pointer) +{ + char command[256] = "Filer_OpenDir "; + char *dot; + os_error *error; + + if (pointer->i == ICON_DOWNLOAD_ICON && !dw->error && + !dw->saved) { + gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE; + download_window_current = dw; + ro_gui_drag_icon(pointer); + + } else if (pointer->i == ICON_DOWNLOAD_DESTINATION) { + strncpy(command + 14, dw->path, 242); + command[255] = 0; + dot = strrchr(command, '.'); + if (dot) { + *dot = 0; + error = xos_cli(command); + if (error) { + LOG(("xos_cli: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); } - break; + } } } /** * Handle User_Drag_Box event for a drag from a download window. + * + * \param drag block returned by Wimp_Poll */ -void ro_download_drag_end(wimp_dragged *drag) +void ro_gui_download_drag_end(wimp_dragged *drag) { wimp_pointer pointer; wimp_message message; + struct gui_download_window *dw = download_window_current; + os_error *error; - wimp_get_pointer_info(&pointer); + if (dw->saved || dw->error) + return; + + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG(("xwimp_get_pointer_info: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } message.your_ref = 0; message.action = message_DATA_SAVE; @@ -196,71 +524,230 @@ void ro_download_drag_end(wimp_dragged *drag) message.data.data_xfer.i = pointer.i; message.data.data_xfer.pos.x = pointer.pos.x; message.data.data_xfer.pos.y = pointer.pos.y; - message.data.data_xfer.est_size = (int) - current_gui->data.download.content->source_size; - message.data.data_xfer.file_type = current_gui->data.download.file_type; - strncpy(message.data.data_xfer.file_name, - current_gui->data.download.path, 212); + message.data.data_xfer.est_size = dw->total_size ? dw->total_size : + dw->received; + message.data.data_xfer.file_type = dw->file_type; + strncpy(message.data.data_xfer.file_name, dw->path, 212); message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) & (~3u)); - wimp_send_message_to_window(wimp_USER_MESSAGE, &message, - pointer.w, pointer.i); + error = xwimp_send_message_to_window(wimp_USER_MESSAGE, &message, + pointer.w, pointer.i, 0); + if (error) { + LOG(("xwimp_send_message_to_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } } /** * Handle Message_DataSaveAck for a drag from a download window. + * + * \param message block returned by Wimp_Poll */ -void ro_download_datasave_ack(wimp_message *message) +void ro_gui_download_datasave_ack(wimp_message *message) { - char *data; - char *data_end; + char temp_name[40]; + char *file_name; + struct gui_download_window *dw = download_window_current; os_error *error; - assert(current_gui->data.download.download_status == download_COMPLETE); + if (dw->saved || dw->error) + return; - data = current_gui->data.download.content->source_data; - data_end = data + current_gui->data.download.content->source_size; + file_name = message->data.data_xfer.file_name; + snprintf(temp_name, sizeof temp_name, ".ns%x", + (unsigned int) dw); + + /* close temporary file */ + if (dw->file) { + error = xosfind_closew(dw->file); + dw->file = 0; + if (error) { + LOG(("xosfind_closew: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + if (dw->fetch) + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); + return; + } + } - error = xosfile_save_stamped(message->data.data_xfer.file_name, - current_gui->data.download.file_type, - data, data_end); - if (error) { - LOG(("0x%x: %s\n", error->errnum, error->errmess)); + /* move or copy temporary file to destination file */ + error = xosfscontrol_rename(temp_name, file_name); + if (error && error->errnum == error_BAD_RENAME) { + /* rename failed: copy with delete */ + error = xosfscontrol_copy(temp_name, file_name, + osfscontrol_COPY_FORCE | + osfscontrol_COPY_DELETE | + osfscontrol_COPY_LOOK, + 0, 0, 0, 0, 0); + if (error) { + LOG(("xosfscontrol_copy: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + if (dw->fetch) + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); + return; + } + } else if (error) { + LOG(("xosfscontrol_rename: 0x%x: %s", + error->errnum, error->errmess)); warn_user("SaveError", error->errmess); + if (dw->fetch) + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); return; } + if (dw->fetch) { + /* open new destination file if still fetching */ + error = xosfile_write(file_name, 0xdeaddead, 0xdeaddead, + fileswitch_ATTR_OWNER_READ | + fileswitch_ATTR_OWNER_WRITE); + if (error) { + LOG(("xosfile_write: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + + error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR, + file_name, 0, &dw->file); + if (error) { + LOG(("xosfind_openupw: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + if (dw->fetch) + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); + return; + } + + error = xosargs_set_ptrw(dw->file, dw->received); + if (error) { + LOG(("xosargs_set_ptrw: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + if (dw->fetch) + fetch_abort(dw->fetch); + gui_download_window_error(dw, error->errmess); + return; + } + + } else { + /* otherwise just set the file type */ + error = xosfile_set_type(file_name, + dw->file_type); + if (error) { + LOG(("xosfile_set_type: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + } + + dw->saved = true; + strncpy(dw->path, file_name, sizeof dw->path); + + /* hide writeable path icon and show destination icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, + wimp_ICON_DELETED, wimp_ICON_DELETED); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + error = xwimp_set_icon_state(dw->window, + ICON_DOWNLOAD_DESTINATION, 0, wimp_ICON_DELETED); + if (error) { + LOG(("xwimp_set_icon_state: 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; - wimp_send_message_to_window(wimp_USER_MESSAGE, message, message->data.data_xfer.w, message->data.data_xfer.i); + error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message, + message->data.data_xfer.w, + message->data.data_xfer.i, 0); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } - ro_download_window_close(current_gui); + if (!dw->fetch) + schedule(200, ro_gui_download_window_destroy_wrapper, dw); } -struct gui_window * ro_lookup_download_window_from_w(wimp_w window) +/** + * Close a download window and free any related resources. + * + * \param dw download window + */ + +void ro_gui_download_window_destroy(struct gui_download_window *dw) { - gui_window* g; - for (g = window_list; g != NULL; g = g->next) - { - if (g->type == GUI_DOWNLOAD_WINDOW) - { - if (g->window == window) - { - return g; - } - } - } - return NULL; + char temp_name[40]; + os_error *error; + + schedule_remove(ro_gui_download_update_status_wrapper, dw); + + /* remove from list */ + if (dw->prev) + dw->prev->next = dw->next; + else + download_window_list = dw->next; + if (dw->next) + dw->next->prev = dw->prev; + + /* delete window */ + error = xwimp_delete_window(dw->window); + if (error) { + LOG(("xwimp_delete_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + /* close download file */ + if (dw->file) { + error = xosfind_closew(dw->file); + if (error) { + LOG(("xosfind_closew: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + } + + /* delete temporary file */ + if (!dw->saved) { + snprintf(temp_name, sizeof temp_name, ".ns%x", + (unsigned int) dw); + error = xosfile_delete(temp_name, 0, 0, 0, 0, 0); + if (error) { + LOG(("xosfile_delete: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); + } + } + + if (dw->fetch) + fetch_abort(dw->fetch); + + free(dw); } -void ro_download_window_close(struct gui_window *g) -{ - // free contexts etc??? - wimp_close_window(g->window); +/** + * Wrapper for ro_gui_download_window_destroy(), suitable for schedule(). + */ + +void ro_gui_download_window_destroy_wrapper(void *p) +{ + ro_gui_download_window_destroy((struct gui_download_window *) p); } -- cgit v1.2.3