diff options
Diffstat (limited to 'frontends/atari/download.c')
-rw-r--r-- | frontends/atari/download.c | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/frontends/atari/download.c b/frontends/atari/download.c new file mode 100644 index 000000000..9ebe78751 --- /dev/null +++ b/frontends/atari/download.c @@ -0,0 +1,453 @@ +/* + * Copyright 2010 Ole Loots <ole@monochrom.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdbool.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/nsoption.h" +#include "utils/string.h" +#include "content/urldb.h" +#include "content/fetch.h" +#include "desktop/save_complete.h" +#include "desktop/textinput.h" +#include "desktop/download.h" +#include "desktop/browser.h" +#include "desktop/gui_download.h" + +#include "atari/gui.h" +#include "atari/misc.h" +#include "atari/res/netsurf.rsh" +#include "atari/download.h" +#include "atari/osspec.h" + +extern struct gui_window * input_window; +extern GRECT desk_area; + +static void gui_download_window_destroy( struct gui_download_window * gdw ); +static void on_abort_click(struct gui_download_window *dw); +static void on_cbrdy_click(struct gui_download_window *dw); +static void on_close(struct gui_download_window * dw); +static void on_redraw(struct gui_download_window *dw, GRECT *clip); + +static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip) +{ + struct gui_download_window *data; + + if (msg != WM_REDRAW) { + data = gemtk_wm_get_user_data(win); + + assert(data); + + on_redraw(data, clip); + } +} + +static short on_aes_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + struct gui_download_window *data; + + GRECT clip; + + data = gemtk_wm_get_user_data(win); + + if ((ev_out->emo_events & MU_MESAG) != 0) { + // handle message + //printf("download win msg: %d\n", msg[0]); + switch (msg[0]) { + + case WM_REDRAW: + clip.g_x = msg[4]; + clip.g_y = msg[5]; + clip.g_w = msg[6]; + clip.g_h = msg[7]; + on_redraw(data, &clip); + break; + + case WM_CLOSED: + // TODO: this needs to iterate through all gui windows and + // check if the rootwin is this window... + on_close(data); + break; + + case WM_TOOLBAR: + switch(msg[4]){ + + case DOWNLOAD_BT_ABORT: + on_abort_click(data); + break; + + case DOWNLOAD_CB_CLOSE_RDY: + on_cbrdy_click(data); + break; + + default: break; + } + break; + + default: + break; + } + } + if ((ev_out->emo_events & MU_KEYBD) != 0) { + + + } + if ((ev_out->emo_events & MU_BUTTON) != 0) { + + } + + return(retval); +} + +static void on_redraw(struct gui_download_window *dw, GRECT *clip) +{ + OBJECT *tree = dw->tree; + GRECT work, visible; + uint32_t p = 0; + + gemtk_wm_get_grect(dw->guiwin, GEMTK_WM_AREA_TOOLBAR, &work); + tree->ob_x = work.g_x; + tree->ob_y = work.g_y; + + if(!rc_intersect(clip, &work)){ + return; + } + + /* + Update the AES Object to reflect current state of download: + */ + ((TEDINFO *)get_obspec(tree, DOWNLOAD_FILENAME))->te_ptext = dw->lbl_file; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_BYTES))->te_ptext = dw->lbl_done; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_PERCENT))->te_ptext = dw->lbl_percent; + ((TEDINFO *)get_obspec(tree, DOWNLOAD_LBL_SPEED))->te_ptext = dw->lbl_speed; + + if (dw->size_total > 0 ) { + p = ((double)dw->size_downloaded / (double)dw->size_total * 100); + } + tree[DOWNLOAD_PROGRESS_DONE].ob_width = MAX( MIN( p*(DOWNLOAD_BAR_MAX/100), + DOWNLOAD_BAR_MAX ), 1); + if (dw->close_on_finish) { + tree[DOWNLOAD_CB_CLOSE_RDY].ob_state |= (OS_SELECTED | OS_CROSSED); + } else { + tree[DOWNLOAD_CB_CLOSE_RDY].ob_state &= ~(OS_SELECTED | OS_CROSSED); + } + tree[DOWNLOAD_BT_ABORT].ob_state &= ~OS_SELECTED; + + /*Walk the AES rectangle list and redraw the visible areas of the window: */ + wind_get_grect(dw->aes_handle, WF_FIRSTXYWH, &visible); + while (visible.g_x && visible.g_y) { + if (rc_intersect(&work, &visible)) { + objc_draw_grect(tree, 0, 8, &visible); + } + wind_get_grect(dw->aes_handle, WF_NEXTXYWH, &visible); + } +} + +static void on_abort_click(struct gui_download_window *dw) +{ + if( dw->status == NSATARI_DOWNLOAD_COMPLETE + || dw->status == NSATARI_DOWNLOAD_ERROR ) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0); + } + else if( dw->status != NSATARI_DOWNLOAD_CANCELED ){ + dw->abort = true; + } +} + +static void on_cbrdy_click(struct gui_download_window *dw) +{ + dw->close_on_finish = !dw->close_on_finish; + if (dw->close_on_finish && dw->status == NSATARI_DOWNLOAD_COMPLETE) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0,0,0,0); + } + gemtk_wm_exec_redraw(dw->guiwin, NULL); + evnt_timer(250); +} + +static void on_close(struct gui_download_window * dw) +{ + gui_download_window_destroy(dw); +} + +static void gui_download_window_destroy( struct gui_download_window * gdw) +{ + LOG("gdw %p", gdw); + + if (gdw->status == NSATARI_DOWNLOAD_WORKING) { + download_context_abort(gdw->ctx); + } + + download_context_destroy(gdw->ctx); + + if (gdw->destination) { + free( gdw->destination ); + } + if (gdw->fd != NULL) { + fclose(gdw->fd); + gdw->fd = NULL; + } + if (gdw->fbuf != NULL) { + free( gdw->fbuf ); + } + gemtk_wm_remove(gdw->guiwin); + wind_close(gdw->aes_handle); + wind_delete(gdw->aes_handle); + free(gdw); +} + +static char * select_filepath( const char * path, const char * filename ) +{ + char tmp[PATH_MAX]; + char res_path[PATH_MAX]; + char res_file[PATH_MAX]; + char * ret = NULL; + + strncpy(res_path, path, PATH_MAX); + strncpy(res_file, filename, PATH_MAX); + res_file[PATH_MAX-1] = 0; + res_path[PATH_MAX-1] = 0; + + if(select_file(res_path, res_file, (char*)"*", + (char*)messages_get("SaveAsNS"), NULL)) { + snprintf(tmp, PATH_MAX, "%s%s", res_path, res_file); + ret = malloc(strlen(tmp)+1); + strcpy(ret, tmp); + } + + printf("download file: %s\n", ret); + return(ret); +} + +static struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *parent) +{ + const char *filename; + char *destination; + char gdos_path[PATH_MAX]; + struct gui_download_window * gdw; + int dlgres = 0; + OBJECT * tree = gemtk_obj_get_tree(DOWNLOAD); + char alert[200]; + + + LOG("Creating download window for gui window: %p", parent); + + /* TODO: Implement real form and use messages file strings! */ + + if (tree == NULL){ + die("Couldn't find AES Object tree for download window!"); + return(NULL); + } + + filename = download_context_get_filename((const download_context*)ctx); + snprintf(alert, 200, "[2][Accept download?|%.*s][Yes|Save as...|No]", + 40,filename); + dlgres = form_alert(2, alert); + if( dlgres == 3){ + return( NULL ); + } + else if( dlgres == 2 ){ + gemdos_realpath(nsoption_charp(downloads_path), gdos_path); + char * tmp = select_filepath( gdos_path, filename ); + if( tmp == NULL ) + return( NULL ); + destination = tmp; + } else { + int dstsize=0; + gemdos_realpath(nsoption_charp(downloads_path), gdos_path); + dstsize = strlen(gdos_path) + strlen(filename) + 2; + destination = malloc( dstsize ); + snprintf(destination, dstsize, "%s/%s", gdos_path, filename); + } + + gdw = calloc(1, sizeof(struct gui_download_window)); + if( gdw == NULL ){ + atari_warn_user(NULL, "Out of memory!"); + free( destination ); + return( NULL ); + } + + gdw->ctx = ctx; + gdw->abort = false; + gdw->start = clock() / CLOCKS_PER_SEC; + gdw->lastrdw = 0; + gdw->status = NSATARI_DOWNLOAD_WORKING; + gdw->parent = parent; + gdw->fbufsize = MAX(BUFSIZ, 48000); + gdw->size_downloaded = 0; + gdw->size_total = download_context_get_total_length(ctx); + gdw->destination = destination; + gdw->tree = tree; + + gdw->fd = fopen(gdw->destination, "wb"); + if( gdw->fd == NULL ){ + char spare[200]; + snprintf(spare, 200, "Couldn't open %s for writing!", gdw->destination); + gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT, spare); + gui_download_window_destroy(gdw); + return( NULL ); + } + + gdw->fbuf = malloc( gdw->fbufsize+1 ); + if( gdw->fbuf != NULL ){ + setvbuf( gdw->fd, gdw->fbuf, _IOFBF, gdw->fbufsize ); + } + + gdw->aes_handle = wind_create_grect(CLOSER | NAME | MOVER, &desk_area); + wind_set_str(gdw->aes_handle, WF_NAME, "Download"); + unsigned long gwflags = GEMTK_WM_FLAG_DEFAULTS; + gdw->guiwin = gemtk_wm_add(gdw->aes_handle, gwflags, on_aes_event); + if( gdw->guiwin == NULL || gdw->fd == NULL ){ + die("could not create guiwin"); + gui_download_window_destroy(gdw); + return( NULL ); + } + gemtk_wm_set_user_data(gdw->guiwin, gdw); + gemtk_wm_set_toolbar(gdw->guiwin, tree, 0, 0); + gemtk_wm_set_toolbar_redraw_func(gdw->guiwin, toolbar_redraw_cb); + + strncpy((char*)&gdw->lbl_file, filename, MAX_SLEN_LBL_FILE-1); + LOG("created download: %s (total size: %d)", gdw->destination, gdw->size_total); + + GRECT work, curr; + work.g_x = 0; + work.g_y = 0; + work.g_w = tree->ob_width; + work.g_h = tree->ob_height; + + wind_calc_grect(WC_BORDER, CLOSER | MOVER | NAME, &work, &curr); + + curr.g_x = (desk_area.g_w / 2) - (curr.g_w / 2); + curr.g_y = (desk_area.g_h / 2) - (curr.g_h / 2); + + wind_open_grect(gdw->aes_handle, &curr); + gdw->lastrdw = clock() / (CLOCKS_PER_SEC >> 3); + + return(gdw); +} + + +static nserror gui_download_window_data(struct gui_download_window *dw, + const char *data, unsigned int size) +{ + uint32_t clck = clock(); + uint32_t tnow = clck / (CLOCKS_PER_SEC>>3); + uint32_t sdiff = (clck / (CLOCKS_PER_SEC)) - dw->start; + + LOG("dw %p",dw); + + if (dw->abort == true){ + dw->status = NSATARI_DOWNLOAD_CANCELED; + dw->abort = false; + download_context_abort(dw->ctx); + gemtk_wm_exec_redraw(dw->guiwin, NULL); + return(NSERROR_OK); + } + + /* save data */ + fwrite( data , size, sizeof(unsigned char),dw->fd ); + dw->size_downloaded += size; + + /* Update GUI */ + if ((tnow - dw->lastrdw) > 1) { + float speed; + + dw->lastrdw = tnow; + speed = dw->size_downloaded / sdiff; + + if( dw->size_total > 0 ){ + uint32_t p = 0; + p = ((double)dw->size_downloaded / (double)dw->size_total * 100); + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%"PRIu32"%s", p, "%" + ); + } else { + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%s", "?%" + ); + } + snprintf( (char*)&dw->lbl_speed, MAX_SLEN_LBL_SPEED, "%s/s", + human_friendly_bytesize(speed) + ); + snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s", + human_friendly_bytesize(dw->size_downloaded), + (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : "?" + ); + + gemtk_wm_exec_redraw(dw->guiwin, NULL); + } + return NSERROR_OK; +} + +static void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ + LOG("%s", error_msg); + + strncpy((char*)&dw->lbl_file, error_msg, MAX_SLEN_LBL_FILE-1); + dw->status = NSATARI_DOWNLOAD_ERROR; + gemtk_wm_exec_redraw(dw->guiwin, NULL); + atari_window_set_status(input_window, messages_get("Done") ); + // TODO: change abort to close +} + +static void gui_download_window_done(struct gui_download_window *dw) +{ + LOG("dw %p", dw); + +// TODO: change abort to close + dw->status = NSATARI_DOWNLOAD_COMPLETE; + + if( dw->fd != NULL ) { + fclose( dw->fd ); + dw->fd = NULL; + } + + if (dw->close_on_finish) { + gemtk_wm_send_msg(dw->guiwin, WM_CLOSED, 0, 0, 0, 0); + } else { + snprintf( (char*)&dw->lbl_percent, MAX_SLEN_LBL_PERCENT, + "%u%s", 100, "%" + ); + snprintf( (char*)&dw->lbl_done, MAX_SLEN_LBL_DONE, "%s / %s", + human_friendly_bytesize(dw->size_downloaded), + (dw->size_total>0) ? human_friendly_bytesize(dw->size_total) : human_friendly_bytesize(dw->size_downloaded) + ); + gemtk_wm_exec_redraw(dw->guiwin, NULL); + } + atari_window_set_status(input_window, messages_get("Done") ); +} + +static struct gui_download_table download_table = { + .create = gui_download_window_create, + .data = gui_download_window_data, + .error = gui_download_window_error, + .done = gui_download_window_done, +}; + +struct gui_download_table *atari_download_table = &download_table; |