mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-02 02:46:59 +03:00
a2388a91cf
The use of the application instance handle global variable was inconsistent throughout the windows frontend. By rationalising the passing of these handles it showed that some of the toolbar and throbber parent handles were also setup wrong giving odd offset behaviour. All these issues have been addressed and the throbber is now in the correct position.
351 lines
8.8 KiB
C
351 lines
8.8 KiB
C
/*
|
|
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.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/>.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
* windows frontend download implementation
|
|
*
|
|
* \todo The windows download functionality is very buggy this needs redoing
|
|
*/
|
|
|
|
#include <limits.h>
|
|
#include "utils/inet.h" /* get correct winsock ordering */
|
|
#include <shlobj.h>
|
|
#include <windows.h>
|
|
|
|
#include "utils/sys_time.h"
|
|
#include "utils/log.h"
|
|
#include "utils/messages.h"
|
|
#include "utils/url.h"
|
|
#include "utils/nsurl.h"
|
|
#include "utils/utils.h"
|
|
#include "utils/string.h"
|
|
#include "content/fetch.h"
|
|
#include "netsurf/download.h"
|
|
#include "desktop/download.h"
|
|
|
|
#include "windows/download.h"
|
|
#include "windows/window.h"
|
|
#include "windows/gui.h"
|
|
#include "windows/resourceid.h"
|
|
#include "windows/schedule.h"
|
|
|
|
struct gui_download_window {
|
|
HWND hwnd;
|
|
char *title;
|
|
char *filename;
|
|
char *domain;
|
|
char *time_left;
|
|
char *total_size;
|
|
char *original_total_size;
|
|
int size;
|
|
int downloaded;
|
|
unsigned int progress;
|
|
int time_remaining;
|
|
struct timeval start_time;
|
|
int speed;
|
|
int error;
|
|
struct gui_window *window;
|
|
FILE *file;
|
|
download_status status;
|
|
};
|
|
|
|
static bool downloading = false;
|
|
static struct gui_download_window *download1;
|
|
|
|
|
|
static void nsws_download_update_label(void *p)
|
|
{
|
|
struct gui_download_window *w = p;
|
|
if (w->hwnd == NULL) {
|
|
win32_schedule(-1, nsws_download_update_label, p);
|
|
return;
|
|
}
|
|
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_LABEL);
|
|
char *size = human_friendly_bytesize(w->downloaded);
|
|
int i = 0, temp = w->time_remaining;
|
|
if (temp == -1) {
|
|
w->time_left = strdup(messages_get("UnknownSize"));
|
|
i = strlen(w->time_left);
|
|
} else {
|
|
do {
|
|
temp = temp / 10;
|
|
i++;
|
|
} while (temp > 2);
|
|
w->time_left = malloc(i + SLEN(" s") + 1);
|
|
if (w->time_left != NULL) {
|
|
if (w->time_remaining > 3600)
|
|
sprintf(w->time_left, "%d h",
|
|
w->time_remaining / 3600);
|
|
else if (w->time_remaining > 60)
|
|
sprintf(w->time_left, "%d m",
|
|
w->time_remaining / 60);
|
|
else
|
|
sprintf(w->time_left, "%d s",
|
|
w->time_remaining);
|
|
}
|
|
}
|
|
char label[strlen(w->title) + strlen(size) + strlen(w->total_size) +
|
|
+ strlen(w->domain) + strlen(w->filename) +
|
|
SLEN("download from to \n[\t/\t]\n estimate of time"
|
|
" remaining ") + i + 1];
|
|
sprintf(label, "download %s from %s to %s\n[%s\t/\t%s] [%d%%]\n"
|
|
"estimate of time remaining %s", w->title, w->domain,
|
|
w->filename, size, w->total_size, w->progress / 100,
|
|
w->time_left);
|
|
if (w->time_left != NULL) {
|
|
free(w->time_left);
|
|
w->time_left = NULL;
|
|
}
|
|
SendMessage(sub, WM_SETTEXT, (WPARAM)0, (LPARAM)label);
|
|
if (w->progress < 10000) {
|
|
win32_schedule(500, nsws_download_update_label, p);
|
|
}
|
|
}
|
|
|
|
|
|
static void nsws_download_update_progress(void *p)
|
|
{
|
|
struct gui_download_window *w = p;
|
|
if (w->hwnd == NULL) {
|
|
win32_schedule(-1, nsws_download_update_progress, p);
|
|
return;
|
|
}
|
|
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_PROGRESS);
|
|
SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0);
|
|
if (w->progress < 10000) {
|
|
win32_schedule(500, nsws_download_update_progress, p);
|
|
}
|
|
}
|
|
|
|
|
|
static void nsws_download_clear_data(struct gui_download_window *w)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
if (w->title != NULL)
|
|
free(w->title);
|
|
if (w->filename != NULL)
|
|
free(w->filename);
|
|
if (w->domain != NULL)
|
|
free(w->domain);
|
|
if (w->time_left != NULL)
|
|
free(w->time_left);
|
|
if (w->total_size != NULL)
|
|
free(w->total_size);
|
|
if (w->file != NULL)
|
|
fclose(w->file);
|
|
win32_schedule(-1, nsws_download_update_progress, (void *)w);
|
|
win32_schedule(-1, nsws_download_update_label, (void *)w);
|
|
}
|
|
|
|
|
|
static BOOL CALLBACK
|
|
nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
nsws_download_update_label((void *)download1);
|
|
nsws_download_update_progress((void *)download1);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wparam)) {
|
|
case IDOK:
|
|
if (download1->downloaded != download1->size)
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
nsws_download_clear_data(download1);
|
|
download1 = NULL;
|
|
downloading = false;
|
|
EndDialog(hwnd, IDCANCEL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static bool nsws_download_window_up(struct gui_download_window *w)
|
|
{
|
|
w->hwnd = CreateDialog(hinst,
|
|
MAKEINTRESOURCE(IDD_DLG_DOWNLOAD),
|
|
gui_window_main_window(w->window),
|
|
nsws_download_event_callback);
|
|
if (w->hwnd == NULL) {
|
|
return false;
|
|
}
|
|
ShowWindow(w->hwnd, SW_SHOW);
|
|
return true;
|
|
}
|
|
|
|
|
|
static struct gui_download_window *
|
|
gui_download_window_create(download_context *ctx, struct gui_window *gui)
|
|
{
|
|
if (downloading) {
|
|
/* initial implementation */
|
|
win32_warning("1 download at a time please", 0);
|
|
return NULL;
|
|
}
|
|
downloading = true;
|
|
struct gui_download_window *w =
|
|
malloc(sizeof(struct gui_download_window));
|
|
if (w == NULL) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
return NULL;
|
|
}
|
|
int total_size = download_context_get_total_length(ctx);
|
|
char *domain, *filename, *destination;
|
|
nsurl *url = download_context_get_url(ctx);
|
|
bool unknown_size = (total_size == 0);
|
|
const char *size = (unknown_size) ?
|
|
messages_get("UnknownSize") :
|
|
human_friendly_bytesize(total_size);
|
|
|
|
if (nsurl_nice(url, &filename, false) != NSERROR_OK) {
|
|
filename = strdup(messages_get("UnknownFile"));
|
|
}
|
|
if (filename == NULL) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
|
|
if (nsurl_has_component(url, NSURL_HOST)) {
|
|
domain = strdup(lwc_string_data(nsurl_get_component(url, NSURL_HOST)));
|
|
} else {
|
|
domain = strdup(messages_get("UnknownHost"));
|
|
}
|
|
if (domain == NULL) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
free(filename);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
destination = malloc(PATH_MAX);
|
|
if (destination == NULL) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
free(domain);
|
|
free(filename);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT,
|
|
destination);
|
|
if (strlen(destination) < PATH_MAX - 2)
|
|
strcat(destination, "/");
|
|
if (strlen(destination) + strlen(filename) < PATH_MAX - 1)
|
|
strcat(destination, filename);
|
|
LOG("download %s [%s] from %s to %s", filename, size, domain, destination);
|
|
w->title = filename;
|
|
w->domain = domain;
|
|
w->size = total_size;
|
|
w->total_size = strdup(size);
|
|
if (w->total_size == NULL) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
free(destination);
|
|
free(domain);
|
|
free(filename);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
w->downloaded = 0;
|
|
w->speed = 0;
|
|
gettimeofday(&(w->start_time), NULL);
|
|
w->time_remaining = -1;
|
|
w->time_left = NULL;
|
|
w->status = DOWNLOAD_NONE;
|
|
w->filename = destination;
|
|
w->progress = 0;
|
|
w->error = 0;
|
|
w->window = gui;
|
|
w->file = fopen(destination, "wb");
|
|
if (w->file == NULL) {
|
|
win32_warning(messages_get("FileOpenWriteError"), destination);
|
|
free(destination);
|
|
free(domain);
|
|
free(filename);
|
|
free(w->total_size);
|
|
free(w->time_left);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
download1 = w;
|
|
|
|
if (nsws_download_window_up(w) == false) {
|
|
win32_warning(messages_get("NoMemory"), 0);
|
|
free(destination);
|
|
free(domain);
|
|
free(filename);
|
|
free(w->total_size);
|
|
free(w->time_left);
|
|
free(w);
|
|
return NULL;
|
|
}
|
|
return w;
|
|
}
|
|
|
|
|
|
static nserror
|
|
gui_download_window_data(struct gui_download_window *w, const char *data,
|
|
unsigned int size)
|
|
{
|
|
if ((w == NULL) || (w->file == NULL))
|
|
return NSERROR_SAVE_FAILED;
|
|
size_t res;
|
|
struct timeval val;
|
|
res = fwrite((void *)data, 1, size, w->file);
|
|
if (res != size)
|
|
LOG("file write error %d of %d", size - res, size);
|
|
w->downloaded += res;
|
|
w->progress = (unsigned int)(((long long)(w->downloaded) * 10000)
|
|
/ w->size);
|
|
gettimeofday(&val, NULL);
|
|
w->time_remaining = (w->progress == 0) ? -1 :
|
|
(int)((val.tv_sec - w->start_time.tv_sec) *
|
|
(10000 - w->progress) / w->progress);
|
|
return NSERROR_OK;
|
|
}
|
|
|
|
static void gui_download_window_error(struct gui_download_window *w,
|
|
const char *error_msg)
|
|
{
|
|
LOG("error %s", error_msg);
|
|
}
|
|
|
|
static void gui_download_window_done(struct gui_download_window *w)
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
downloading = false;
|
|
if (w->hwnd != NULL)
|
|
EndDialog(w->hwnd, IDOK);
|
|
nsws_download_clear_data(w);
|
|
}
|
|
|
|
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 *win32_download_table = &download_table;
|