⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 download.c

📁 一个很有名的浏览器
💻 C
字号:
/* Download dialogs *//* $Id: download.c,v 1.67.4.4 2005/05/01 22:16:08 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "bfu/dialog.h"#include "dialogs/download.h"#include "dialogs/menu.h"#include "dialogs/status.h"#include "intl/gettext/libintl.h"#include "lowlevel/select.h"#include "protocol/uri.h"#include "sched/download.h"#include "sched/session.h"#include "terminal/draw.h"#include "terminal/terminal.h"#include "util/color.h"#include "util/conv.h"#include "util/error.h"#include "util/memlist.h"#include "util/memory.h"#include "util/object.h"#include "util/string.h"#include "util/ttime.h"static voidundisplay_download(struct file_download *file_download){	/* We are maybe called from bottom halve so check consistency */	if (is_in_downloads_list(file_download) && file_download->dlg_data)		cancel_dialog(file_download->dlg_data, NULL);}static voiddo_abort_download(struct file_download *file_download){	/* We are maybe called from bottom halve so check consistency */	if (is_in_downloads_list(file_download)) {		file_download->stop = 1;		abort_download(file_download);	}}static t_handler_event_statusdlg_set_notify(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct file_download *file_download = dlg_data->dlg->udata;	file_download->notify = 1;	undisplay_download(file_download);	return EVENT_PROCESSED;}static t_handler_event_statusdlg_abort_download(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct file_download *file_download = dlg_data->dlg->udata;	object_unlock(file_download);	register_bottom_half((void (*)(void *)) do_abort_download,			     file_download);	return EVENT_PROCESSED;}static t_handler_event_statuspush_delete_button(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct file_download *file_download = dlg_data->dlg->udata;	file_download->delete = 1;	object_unlock(file_download);	register_bottom_half((void (*)(void *)) do_abort_download,			     file_download);	return EVENT_PROCESSED;}static t_handler_event_statusdlg_undisplay_download(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct file_download *file_download = dlg_data->dlg->udata;	object_unlock(file_download);	register_bottom_half((void (*)(void *)) undisplay_download,			     file_download);	return EVENT_PROCESSED;}static voiddownload_abort_function(struct dialog_data *dlg_data){	struct file_download *file_download = dlg_data->dlg->udata;	file_download->dlg_data = NULL;}voiddownload_progress_bar(struct terminal *term, int x, int y, int width,		      unsigned char *text, struct color_pair *meter_color,		      longlong current, longlong total){	/* Note : values > 100% are theorically possible and were seen. */	int progress = (int) ((longlong) 100 * current / total);	struct box barprogress;	/* Draw the progress meter part "[###    ]" */	if (!text && width > 2) {		width -= 2;		draw_text(term, x++, y, "[", 1, 0, NULL);		draw_text(term, x + width, y, "]", 1, 0, NULL);	}	if (!meter_color) meter_color = get_bfu_color(term, "dialog.meter");	set_box(&barprogress,		x, y, int_min(width * progress / 100, width), 1);	draw_box(term, &barprogress, ' ', 0, meter_color);	/* On error, will print '?' only, should not occur. */	if (text) {		width = int_min(width, strlen(text));	} else if (width > 1) {		static unsigned char percent[] = "????"; /* Reduce or enlarge at will. */		unsigned int percent_len = 0;		int max = int_min(sizeof(percent), width) - 1;		if (ulongcat(percent, &percent_len, progress, max, 0)) {			percent[0] = '?';			percent_len = 1;		}		percent[percent_len++] = '%';		/* Draw the percentage centered in the progress meter */		x += (1 + width - percent_len) / 2;		assert(percent_len <= width);		width = percent_len;		text = percent;	}	draw_text(term, x, y, text, width, 0, NULL);}static voiddownload_dialog_layouter(struct dialog_data *dlg_data){	struct file_download *file_download = dlg_data->dlg->udata;	struct terminal *term = dlg_data->win->term;	int w = dialog_max_width(term);	int rw = w;	int x, y = 0;	int url_len;	unsigned char *url;	struct download *download = &file_download->download;	struct color_pair *dialog_text_color = get_bfu_color(term, "dialog.text");	unsigned char *msg = get_download_msg(download, term, 1, 1, "\n");	int show_meter = (download_is_progressing(download)			  && download->progress->size >= 0);	redraw_below_window(dlg_data->win);	file_download->dlg_data = dlg_data;	if (!msg) return;	url = get_uri_string(file_download->uri, URI_PUBLIC);	if (!url) {		mem_free(msg);		return;	}	url_len = strlen(url);	if (show_meter) {		int_lower_bound(&w, DOWN_DLG_MIN);	}	dlg_format_text_do(NULL, url, 0, &y, w, &rw,			dialog_text_color, ALIGN_LEFT);	y++;	if (show_meter) y += 2;	dlg_format_text_do(NULL, msg, 0, &y, w, &rw,			dialog_text_color, ALIGN_LEFT);	y++;	dlg_format_buttons(NULL, dlg_data->widgets_data,			   dlg_data->number_of_widgets, 0, &y, w,			   &rw, ALIGN_CENTER);	draw_dialog(dlg_data, w, y);	w = rw;	if (url_len > w) {		/* Truncate too long urls */		url_len = w;		url[url_len] = '\0';		if (url_len > 4) {			url[--url_len] = '.';			url[--url_len] = '.';			url[--url_len] = '.';		}	}	y = dlg_data->box.y + DIALOG_TB + 1;	x = dlg_data->box.x + DIALOG_LB;	dlg_format_text_do(term, url, x, &y, w, NULL,			dialog_text_color, ALIGN_LEFT);	if (show_meter) {		y++;		download_progress_bar(term, x, y, w, NULL, NULL,				      download->progress->pos,				      download->progress->size);		y++;	}	y++;	dlg_format_text_do(term, msg, x, &y, w, NULL,			dialog_text_color, ALIGN_LEFT);	y++;	dlg_format_buttons(term, dlg_data->widgets_data,			   dlg_data->number_of_widgets, x, &y, w,			   NULL, ALIGN_CENTER);	mem_free(url);	mem_free(msg);}voiddisplay_download(struct terminal *term, struct file_download *file_download,		 struct session *ses){	struct dialog *dlg;	if (!is_in_downloads_list(file_download))		return;#define DOWNLOAD_WIDGETS_COUNT 4	dlg = calloc_dialog(DOWNLOAD_WIDGETS_COUNT, 0);	if (!dlg) return;	undisplay_download(file_download);	file_download->ses = ses;	dlg->title = _("Download", term);	dlg->layouter = download_dialog_layouter;	dlg->abort = download_abort_function;	dlg->udata = file_download;	object_lock(file_download);	add_dlg_button(dlg, _("~Background", term), B_ENTER | B_ESC, dlg_undisplay_download, NULL);	add_dlg_button(dlg, _("Background with ~notify", term), B_ENTER | B_ESC, dlg_set_notify, NULL);	add_dlg_button(dlg, _("~Abort", term), 0, dlg_abort_download, NULL);	/* Downloads scheduled to be opened by external handlers are always	 * deleted. */	if (!file_download->external_handler) {		add_dlg_button(dlg, _("Abort and ~delete file", term), 0, push_delete_button, NULL);		add_dlg_end(dlg, DOWNLOAD_WIDGETS_COUNT);	} else {		add_dlg_end(dlg, DOWNLOAD_WIDGETS_COUNT - 1);	}	do_dialog(term, dlg, getml(dlg, NULL));}/* The download manager */static voidlock_file_download(struct listbox_item *item){	object_lock((struct file_download *) item->udata);}static voidunlock_file_download(struct listbox_item *item){	object_unlock((struct file_download *) item->udata);}static intis_file_download_used(struct listbox_item *item){	return is_object_used((struct file_download *) item->udata);}static unsigned char *get_file_download_text(struct listbox_item *item, struct terminal *term){	struct file_download *file_download = item->udata;	return get_uri_string(file_download->uri, URI_PUBLIC);}static unsigned char *get_file_download_info(struct listbox_item *item, struct terminal *term){	return NULL;}static struct uri *get_file_download_uri(struct listbox_item *item){	struct file_download *file_download = item->udata;	return get_uri_reference(file_download->uri);}static struct listbox_item *get_file_download_root(struct listbox_item *item){	return NULL;}static intcan_delete_file_download(struct listbox_item *item){	return 1;}static voiddelete_file_download(struct listbox_item *item, int last){	struct file_download *file_download = item->udata;	assert(!is_object_used(file_download));	register_bottom_half((void (*)(void *)) do_abort_download,			     file_download);}static enum dlg_refresh_coderefresh_file_download(struct dialog_data *dlg_data, void *data){	/* Always refresh (until we keep finished downloads) */	return are_there_downloads() ? REFRESH_DIALOG : REFRESH_STOP;}/* TODO: Make it configurable */#define DOWNLOAD_METER_WIDTH 15#define DOWNLOAD_URI_PERCENTAGE 50static voiddraw_file_download(struct listbox_item *item, struct listbox_context *context,		   int x, int y, int width){	struct file_download *file_download = item->udata;	struct download *download = &file_download->download;	unsigned char *stylename;	struct color_pair *color;	unsigned char *text = struri(file_download->uri);	int length = strlen(text);	int trimmedlen;	int meter = DOWNLOAD_METER_WIDTH;	/* We have nothing to work with */	if (width < 4) return;	stylename = (item == context->box->sel) ? "menu.selected"		  : ((item->marked)	        ? "menu.marked"					        : "menu.normal");	color = get_bfu_color(context->term, stylename);	/* Show atleast the required percentage of the URI */	if (length * DOWNLOAD_URI_PERCENTAGE / 100 < width - meter - 4) {		trimmedlen = int_min(length, width - meter - 4);	} else {		trimmedlen = int_min(length, width - 3);	}	draw_text(context->term, x, y, text, trimmedlen, 0, color);	if (trimmedlen < length) {		draw_text(context->term, x + trimmedlen, y, "...", 3, 0, color);		trimmedlen += 3;	}	if (!download->progress	    || download->progress->size < 0	    || download->state != S_TRANS	    || !(download->progress->elapsed / 100)) {		/* TODO: Show trimmed error message. */		return;	}	if (!dialog_has_refresh(context->dlg_data))		refresh_dialog(context->dlg_data, refresh_file_download, NULL);	if (trimmedlen + meter >= width) return;	x += width - meter;	download_progress_bar(context->term, x, y, meter, NULL, NULL,			      download->progress->pos,			      download->progress->size);}static struct listbox_ops_messages download_messages = {	/* cant_delete_item */	N_("Sorry, but download \"%s\" cannot be interrupted."),	/* cant_delete_used_item */	N_("Sorry, but download \"%s\" is being used by something else."),	/* cant_delete_folder */	NULL,	/* cant_delete_used_folder */	NULL,	/* delete_marked_items_title */	N_("Interrupt marked downloads"),	/* delete_marked_items */	N_("Interrupt marked downloads?"),	/* delete_folder_title */	NULL,	/* delete_folder */	NULL,	/* delete_item_title */	N_("Interrupt download"),	/* delete_item */	N_("Interrupt this download?"),	/* clear_all_items_title */	N_("Interrupt all downloads"),	/* clear_all_items_title */	N_("Do you really want to interrupt all downloads?"),};static struct listbox_ops downloads_listbox_ops = {	lock_file_download,	unlock_file_download,	is_file_download_used,	get_file_download_text,	get_file_download_info,	get_file_download_uri,	get_file_download_root,	NULL,	can_delete_file_download,	delete_file_download,	draw_file_download,	&download_messages,};static t_handler_event_statuspush_info_button(struct dialog_data *dlg_data, struct widget_data *button){	struct listbox_data *box = get_dlg_listbox_data(dlg_data);	struct terminal *term = dlg_data->win->term;	struct session *ses = dlg_data->dlg->udata;	struct file_download *file_download = box->sel ? box->sel->udata : NULL;	assert(ses);	if (!file_download) return EVENT_PROCESSED;	/* Don't layer on top of the download manager */	delete_window(dlg_data->win);	display_download(term, file_download, ses);	return EVENT_PROCESSED;}/* TODO: Ideas for buttons .. should be pretty trivial most of it * * - Resume or something that will use some goto like handler * - Open button that can be used to set file_download->prog. * - Toggle notify button */static struct hierbox_browser_button download_buttons[] = {	{ N_("~Info"),                  push_info_button           },	{ N_("~Abort"),                 push_hierbox_delete_button },#if 0	/* This requires more work to make locking work and query the user */	{ N_("Abort and delete file"),  push_delete_button         },#endif	{ N_("C~lear"),                 push_hierbox_clear_button  },};struct_hierbox_browser(	download_browser,	N_("Download manager"),	download_buttons,	&downloads_listbox_ops);voiddownload_manager(struct session *ses){	hierbox_browser(&download_browser, ses);	/* FIXME: It's workaround for bug 397. Real fix is needed. */	download_browser.do_not_save_state = 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -