From 6032bc730af7411a65b8119caa65121fdc8f1946 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 14 Jul 2009 10:27:09 +0300 Subject: [PATCH 01/30] Disable resuming download of formatted document If the user chose File -> Save formatted document and typed the name of an existing file, ELinks offered to resume downloading the file. There are a few problems with that: * save_formatted_finish does not actually support resuming. It would instead overwrite the beginning of the file and not truncate it. * When save_formatted calls create_download_file, cdf_hop->data ends up pointing to struct document. If the user then chooses to resume, lun_resume would read *(int *)cdf_hop->data, hoping to get cmdw_hop.magic or codw_hop.magic. struct document does not begin with any such magic value. * Because ELinks already has the formatted document in memory, resuming saves neither time nor I/O. So don't show the "Resume download of the original file" button in this situation. --- src/session/download.c | 80 +++++++++++++++++++++++++++--------------- src/session/download.h | 20 +++++++++-- src/viewer/text/view.c | 6 ++-- 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 84214353..a3196cb3 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -446,13 +446,14 @@ download_data(struct download *download, struct file_download *file_download) } -/* XXX: We assume that resume is everytime zero in lun's callbacks. */ struct lun_hop { struct terminal *term; unsigned char *ofile, *file; - void (*callback)(struct terminal *, unsigned char *, void *, int); + void (*callback)(struct terminal *, unsigned char *, void *, + enum download_resume); void *data; + enum download_resume resume; }; enum { @@ -477,7 +478,7 @@ struct cdf_hop { unsigned char **real_file; int safe; - void (*callback)(struct terminal *, int, void *, int); + void (*callback)(struct terminal *, int, void *, enum download_resume); void *data; }; @@ -486,7 +487,8 @@ lun_alternate(void *lun_hop_) { struct lun_hop *lun_hop = lun_hop_; - lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data, 0); + lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data, + lun_hop->resume); mem_free_if(lun_hop->ofile); mem_free(lun_hop); } @@ -496,7 +498,8 @@ lun_cancel(void *lun_hop_) { struct lun_hop *lun_hop = lun_hop_; - lun_hop->callback(lun_hop->term, NULL, lun_hop->data, 0); + lun_hop->callback(lun_hop->term, NULL, lun_hop->data, + lun_hop->resume); mem_free_if(lun_hop->ofile); mem_free_if(lun_hop->file); mem_free(lun_hop); @@ -507,12 +510,14 @@ lun_overwrite(void *lun_hop_) { struct lun_hop *lun_hop = lun_hop_; - lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, 0); + lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, + lun_hop->resume); mem_free_if(lun_hop->file); mem_free(lun_hop); } -static void common_download_do(struct terminal *term, int fd, void *data, int resume); +static void common_download_do(struct terminal *term, int fd, void *data, + enum download_resume resume); static void lun_resume(void *lun_hop_) @@ -546,15 +551,18 @@ lun_resume(void *lun_hop_) cdf_hop->callback = common_download_do; } } - lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, 1); + lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, + lun_hop->resume | DOWNLOAD_RESUME_SELECTED); mem_free_if(lun_hop->file); mem_free(lun_hop); } static void -lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, - void (*callback)(struct terminal *, unsigned char *, void *, int), +lookup_unique_name(struct terminal *term, unsigned char *ofile, + enum download_resume resume, + void (*callback)(struct terminal *, unsigned char *, + void *, enum download_resume), void *data) { /* [gettext_accelerator_context(.lookup_unique_name)] */ @@ -566,7 +574,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, /* Minor code duplication to prevent useless call to get_opt_int() * if possible. --Zas */ - if (resume) { + if (resume & DOWNLOAD_RESUME_SELECTED) { callback(term, ofile, data, resume); return; } @@ -588,7 +596,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, msg_text(term, N_("'%s' is a directory."), ofile)); mem_free(ofile); - callback(term, NULL, data, 0); + callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); return; } @@ -598,7 +606,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, if (!file || overwrite == 1 || file == ofile) { /* Still nothing special to do... */ if (file != ofile) mem_free(ofile); - callback(term, file, data, 0); + callback(term, file, data, resume & ~DOWNLOAD_RESUME_SELECTED); return; } @@ -609,7 +617,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, if (!lun_hop) { if (file != ofile) mem_free(file); mem_free(ofile); - callback(term, NULL, data, 0); + callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); return; } lun_hop->term = term; @@ -617,6 +625,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, lun_hop->file = (file != ofile) ? file : stracpy(ofile); lun_hop->callback = callback; lun_hop->data = data; + lun_hop->resume = resume; msg_box(term, NULL, MSGBOX_FREE_TEXT, N_("File exists"), ALIGN_CENTER, @@ -629,15 +638,18 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, lun_hop, 4, MSG_BOX_BUTTON(N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER), MSG_BOX_BUTTON(N_("~Overwrite the original file"), lun_overwrite, 0), - MSG_BOX_BUTTON(N_("~Resume download of the original file"), lun_resume, 0), + MSG_BOX_BUTTON((resume & DOWNLOAD_RESUME_ALLOWED + ? N_("~Resume download of the original file") + : NULL), + lun_resume, 0), MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC)); } static void -create_download_file_do(struct terminal *term, unsigned char *file, void *data, - int resume) +create_download_file_do(struct terminal *term, unsigned char *file, + void *data, enum download_resume resume) { struct cdf_hop *cdf_hop = data; unsigned char *wd; @@ -660,8 +672,9 @@ create_download_file_do(struct terminal *term, unsigned char *file, void *data, /* O_APPEND means repositioning at the end of file before each write(), * thus ignoring seek()s and that can hide mysterious bugs. IMHO. * --pasky */ - h = open(file, O_CREAT | O_WRONLY | (resume ? 0 : O_TRUNC) - | (sf && !resume ? O_EXCL : 0), + h = open(file, O_CREAT | O_WRONLY + | (resume & DOWNLOAD_RESUME_SELECTED ? 0 : O_TRUNC) + | (sf && !(resume & DOWNLOAD_RESUME_SELECTED) ? O_EXCL : 0), sf ? 0600 : 0666); saved_errno = errno; /* Saved in case of ... --Zas */ @@ -708,15 +721,17 @@ finish: void create_download_file(struct terminal *term, unsigned char *fi, - unsigned char **real_file, int safe, int resume, - void (*callback)(struct terminal *, int, void *, int), + unsigned char **real_file, int safe, + enum download_resume resume, + void (*callback)(struct terminal *, int, + void *, enum download_resume), void *data) { struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop)); unsigned char *wd; if (!cdf_hop) { - callback(term, -1, data, 0); + callback(term, -1, data, resume & ~DOWNLOAD_RESUME_SELECTED); return; } @@ -824,7 +839,8 @@ subst_file(unsigned char *prog, unsigned char *file) static void -common_download_do(struct terminal *term, int fd, void *data, int resume) +common_download_do(struct terminal *term, int fd, void *data, + enum download_resume resume) { struct file_download *file_download; struct cmdw_hop *cmdw_hop = data; @@ -839,7 +855,8 @@ common_download_do(struct terminal *term, int fd, void *data, int resume) file_download = init_file_download(ses->download_uri, ses, file, fd); if (!file_download) return; - if (resume) file_download->seek = buf.st_size; + if (resume & DOWNLOAD_RESUME_SELECTED) + file_download->seek = buf.st_size; display_download(ses->tab->term, file_download, ses); @@ -848,7 +865,8 @@ common_download_do(struct terminal *term, int fd, void *data, int resume) } static void -common_download(struct session *ses, unsigned char *file, int resume) +common_download(struct session *ses, unsigned char *file, + enum download_resume resume) { struct cmdw_hop *cmdw_hop; @@ -868,19 +886,22 @@ common_download(struct session *ses, unsigned char *file, int resume) void start_download(void *ses, unsigned char *file) { - common_download(ses, file, 0); + common_download(ses, file, + DOWNLOAD_RESUME_ALLOWED); } void resume_download(void *ses, unsigned char *file) { - common_download(ses, file, 1); + common_download(ses, file, + DOWNLOAD_RESUME_ALLOWED | DOWNLOAD_RESUME_SELECTED); } static void -continue_download_do(struct terminal *term, int fd, void *data, int resume) +continue_download_do(struct terminal *term, int fd, void *data, + enum download_resume resume) { struct codw_hop *codw_hop = data; struct file_download *file_download = NULL; @@ -953,7 +974,8 @@ continue_download(void *data, unsigned char *file) create_download_file(type_query->ses->tab->term, file, &codw_hop->real_file, - !!type_query->external_handler, 0, + !!type_query->external_handler, + DOWNLOAD_RESUME_ALLOWED, continue_download_do, codw_hop); } diff --git a/src/session/download.h b/src/session/download.h index c3aacce2..860ce40a 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -99,11 +99,27 @@ int download_is_progressing(struct download *download); int are_there_downloads(void); +/** Whether to resume downloading to a file. This is a bit mask. + * Unrecognized bits should be preserved and ignored. */ +enum download_resume { + /** All bits clear. Downloading cannot be resumed; do not + * offer such an option to the user. */ + DOWNLOAD_RESUME_DISABLED = 0, + + /** Downloading can be resumed. This is the usual value. */ + DOWNLOAD_RESUME_ALLOWED = 1, + + /** The user wants to resume downloading. This must not occur + * without DOWNLOAD_RESUME_ALLOWED. */ + DOWNLOAD_RESUME_SELECTED = 2 +}; + void start_download(void *, unsigned char *); void resume_download(void *, unsigned char *); void create_download_file(struct terminal *, unsigned char *, unsigned char **, - int, int, - void (*)(struct terminal *, int, void *, int), + int, enum download_resume, + void (*)(struct terminal *, int, void *, + enum download_resume), void *); void abort_all_downloads(void); diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c index df7fa0eb..bd72f6b1 100644 --- a/src/viewer/text/view.c +++ b/src/viewer/text/view.c @@ -1616,7 +1616,8 @@ save_as(struct session *ses, struct document_view *doc_view, int magic) } static void -save_formatted_finish(struct terminal *term, int h, void *data, int resume) +save_formatted_finish(struct terminal *term, int h, + void *data, enum download_resume resume) { struct document *document = data; @@ -1643,7 +1644,8 @@ save_formatted(void *data, unsigned char *file) assert(doc_view && doc_view->document); if_assert_failed return; - create_download_file(ses->tab->term, file, NULL, 0, 0, + create_download_file(ses->tab->term, file, NULL, 0, + DOWNLOAD_RESUME_DISABLED, save_formatted_finish, doc_view->document); } From d41fd043c694fa2dddf7aa738e6de51680584745 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 17 Jul 2009 14:10:36 +0300 Subject: [PATCH 02/30] Add comments about struct type_query and related --- src/session/download.c | 175 +++++++++++++++++++++++++++++++++++++++-- src/session/download.h | 15 ++++ 2 files changed, 183 insertions(+), 7 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index a3196cb3..6be1bf71 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -446,39 +446,111 @@ download_data(struct download *download, struct file_download *file_download) } +/** The user is being asked what to do when the local file for + * the download already exists. This structure is allocated by + * lookup_unique_name() and freed by each lun_* function: + * lun_alternate(), lun_cancel(), lun_overwrite(), and lun_resume(). */ struct lun_hop { + /** The terminal in which ELinks is asking the question. + * This gets passed to the callback. */ struct terminal *term; - unsigned char *ofile, *file; - void (*callback)(struct terminal *, unsigned char *, void *, - enum download_resume); + /** The name of the local file into which the data was + * originally going to be downloaded, but which already + * exists. In this string, "~" has already been expanded + * to the home directory. The string must be freed with + * mem_free(). */ + unsigned char *ofile; + + /** An alternative file name that the user may choose instead + * of #ofile. The string must be freed with mem_free(). */ + unsigned char *file; + + /** This function will be called when the user answers. + * See lookup_unique_name() for more information. */ + void (*callback)(struct terminal *term, unsigned char *file, + void *data, enum download_resume resume); + + /** A pointer to be passed to #callback. If #resume includes + * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct + * cdf_hop because the pointer can be read by lun_resume(), + * which assumes so. */ void *data; + + /** Whether the download can be resumed. + * The ::DOWNLOAD_RESUME_SELECTED bit should be clear + * because otherwise there would have been no reason to + * ask the user and initialize this structure. */ enum download_resume resume; }; +/** To let lun_resume() detect whether cdf_hop.data points to struct + * cmdw_hop or to struct codw_hop, each of those structures begins + * with int magic, whose value is one of these + * constants. */ enum { COMMON_DOWNLOAD_DO = 0, CONTINUE_DOWNLOAD_DO }; +/** Data saved by common_download() for the common_download_do() + * callback. */ struct cmdw_hop { + /** Always ::COMMON_DOWNLOAD_DO. */ int magic; /* Must be first --witekfl */ + struct session *ses; + + /** The name of the local file to which the data will be + * downloaded. This is initially NULL, but its address is + * given to create_download_file(), which arranges for the + * pointer to be set before common_download_do() is called. + * The string must be freed with mem_free(). */ unsigned char *real_file; }; +/** Data saved by continue_download() for the continue_download_do() + * callback. */ struct codw_hop { + /** Always ::CONTINUE_DOWNLOAD_DO. */ int magic; /* must be first --witekfl */ + struct type_query *type_query; + + /** The name of the local file to which the data will be + * downloaded. This is initially NULL, but its address is + * given to create_download_file(), which arranges for the + * pointer to be set before continue_download_do() is called. + * The string must be freed with mem_free(). */ unsigned char *real_file; + unsigned char *file; }; +/** Data saved by create_download_file() for the create_download_file_do() + * callback. */ struct cdf_hop { + /** Where to save the name of the file that was actually + * opened. One of the arguments of #callback is a file + * descriptor for this file. @c real_file can be NULL if + * #callback does not care about the name. */ unsigned char **real_file; + + /** If nonzero, give only the user herself access to the file + * (even if the umask is looser), and create the file with + * @c O_EXCL unless resuming. */ int safe; + /** This function will be called when the file has been opened, + * or when it is known that the file will not be opened. + * See create_download_file() for more information. */ void (*callback)(struct terminal *, int, void *, enum download_resume); + + /** A pointer to be passed to #callback. If the @a resume + * argument given to create_download_file() included + * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct + * cmdw_hop or struct codw_hop because the pointer can be + * read by lun_resume(), which assumes so. */ void *data; }; @@ -558,11 +630,41 @@ lun_resume(void *lun_hop_) } +/** If attempting to download to an existing file, perhaps ask + * the user whether to resume, overwrite, or save elsewhere. + * This function constructs a struct lun_hop, which will be freed + * when the user answers the question. + * + * @param term + * The terminal in which this function should show its UI. + * + * @param[in] ofile + * A proposed name for the local file to which the data would be + * downloaded. "~" here refers to the home directory. + * lookup_unique_name() treats this original string as read-only. + * + * @param[in] resume + * Indicates if the user already chose to resume downloading, + * before ELinks even asked for the file name. + * See ::ACT_MAIN_LINK_DOWNLOAD_RESUME. + * + * @param callback + * Will be called when the user answers, or right away if the question + * need not or cannot be asked. In the parameters of the callback, + * @a term and @a data get their values directly from the arguments of + * lookup_unique_name(). @a file is the name of the local file to + * which the data should be downloaded, or NULL if the download should + * not begin. The callback is responsible of doing mem_free(@a file). + * + * @param data + * A pointer to be passed to @a callback. Although this is a void *, + * it must always point to struct cdf_hop because the pointer can get + * passed to lun_resume(), which assumes so. */ static void lookup_unique_name(struct terminal *term, unsigned char *ofile, enum download_resume resume, - void (*callback)(struct terminal *, unsigned char *, - void *, enum download_resume), + void (*callback)(struct terminal *term, unsigned char *file, + void *data, enum download_resume resume), void *data) { /* [gettext_accelerator_context(.lookup_unique_name)] */ @@ -647,6 +749,12 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, +/** Now that the final name of the download file has been chosen, + * open the file and call the callback that was originally given to + * create_download_file(). + * + * create_download_file() passes this function as a callback to + * lookup_unique_name(). */ static void create_download_file_do(struct terminal *term, unsigned char *file, void *data, enum download_resume resume) @@ -719,12 +827,55 @@ finish: mem_free(cdf_hop); } +/** Create a file to which data can be downloaded. + * This function constructs a struct cdf_hop that will be freed + * when @a callback returns. + * + * @param term + * If any dialog boxes are needed, show them in this terminal. + * + * @param fi + * A proposed name for the local file to which the data would be + * downloaded. "~" here refers to the home directory. + * create_download_file() treats this original string as read-only. + * + * @param real_file + * If non-NULL, prepare to save in *@a real_file the name of the local + * file that was eventually opened. The callback must then free this + * string with mem_free(). + * + * @param safe + * If nonzero, give only the user herself access to the file (even if + * the umask is looser), and create the file with @c O_EXCL unless + * resuming. + * + * @param resume + * Whether the download can be resumed, and whether the user already + * asked for it to be resumed. + * + * @param callback + * This function will be called when the file has been opened, + * or when it is known that the file will not be opened. + * In the parameters of the callback, @a term and @a data get their + * values directly from the arguments of create_download_file(). + * @a fd is a file descriptor to the opened file, or -1 if the file + * will not be opened; the callback may read the name of this file + * from *@a real_file if @a real_file was not NULL. + * @a resume is the same as the @a resume argument of + * create_download_file(), except the ::DOWNLOAD_RESUME_SELECTED bit + * will be changed to match what the user chose. + * + * @param data + * A pointer to be passed to #callback. If the @a resume argument + * given to create_download_file() included ::DOWNLOAD_RESUME_ALLOWED, + * this must point to struct cmdw_hop or struct codw_hop because the + * pointer can be read by lun_resume(), which assumes so. */ void create_download_file(struct terminal *term, unsigned char *fi, unsigned char **real_file, int safe, enum download_resume resume, - void (*callback)(struct terminal *, int, - void *, enum download_resume), + void (*callback)(struct terminal *term, int fd, + void *data, enum download_resume resume), void *data) { struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop)); @@ -945,6 +1096,11 @@ cancel: mem_free(codw_hop); } +/** When asked what to do with a file, the user chose to download it + * to a local file named @a file. + * Or an external handler was selected, in which case + * type_query.external_handler is non-NULL and @a file does not + * matter because this function will generate a name. */ static void continue_download(void *data, unsigned char *file) { @@ -1036,6 +1192,8 @@ tp_cancel(void *data) } +/** The user chose "Save" when asked what to do with a file. + * Now ask her where to save the file. */ void tp_save(struct type_query *type_query) { @@ -1089,6 +1247,9 @@ tp_display(struct type_query *type_query) done_type_query(type_query); } +/** The user chose "Open" when asked what to do with a file. + * Or an external handler was found and it has been configured + * to run without asking. */ static void tp_open(struct type_query *type_query) { diff --git a/src/session/download.h b/src/session/download.h index 860ce40a..9e9dfe2f 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -39,6 +39,12 @@ struct download { enum connection_priority pri; }; +/** The user has navigated to a resource that ELinks does not display + * automatically because of its MIME type, and ELinks is asking what + * to do. + * + * These structures are kept in the session.type_queries list, and + * destroy_session() calls done_type_query() to destroy them too. */ struct type_query { LIST_HEAD(struct type_query); struct download download; @@ -48,7 +54,16 @@ struct type_query { unsigned char *target_frame; unsigned char *external_handler; int block; + + /** Whether the resource was generated by ELinks running + * a local CGI program. If the user chooses to open the + * resource with an external handler, ELinks normally saves + * the resource to a temporary file and passes the name of + * that to the external handler. However, if the resource is + * from a "file" URI that does not refer to a local CGI, then + * Elinks need not copy the file. */ unsigned int cgi:1; + /* int frame; */ }; From dfe6d81683f210faea98e023c4787e3abef20d7a Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 17 Jul 2009 17:07:12 +0300 Subject: [PATCH 03/30] Add @relates markup for Doxygen --- src/session/download.c | 43 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 6be1bf71..a3ac779d 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -591,6 +591,7 @@ lun_overwrite(void *lun_hop_) static void common_download_do(struct terminal *term, int fd, void *data, enum download_resume resume); +/*! @relates lun_hop */ static void lun_resume(void *lun_hop_) { @@ -659,7 +660,9 @@ lun_resume(void *lun_hop_) * @param data * A pointer to be passed to @a callback. Although this is a void *, * it must always point to struct cdf_hop because the pointer can get - * passed to lun_resume(), which assumes so. */ + * passed to lun_resume(), which assumes so. + * + * @relates lun_hop */ static void lookup_unique_name(struct terminal *term, unsigned char *ofile, enum download_resume resume, @@ -754,7 +757,9 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, * create_download_file(). * * create_download_file() passes this function as a callback to - * lookup_unique_name(). */ + * lookup_unique_name(). + * + * @relates cdf_hop */ static void create_download_file_do(struct terminal *term, unsigned char *file, void *data, enum download_resume resume) @@ -869,7 +874,9 @@ finish: * A pointer to be passed to #callback. If the @a resume argument * given to create_download_file() included ::DOWNLOAD_RESUME_ALLOWED, * this must point to struct cmdw_hop or struct codw_hop because the - * pointer can be read by lun_resume(), which assumes so. */ + * pointer can be read by lun_resume(), which assumes so. + * + * @relates cdf_hop */ void create_download_file(struct terminal *term, unsigned char *fi, unsigned char **real_file, int safe, @@ -989,6 +996,7 @@ subst_file(unsigned char *prog, unsigned char *file) +/*! @relates cmdw_hop */ static void common_download_do(struct terminal *term, int fd, void *data, enum download_resume resume) @@ -1015,6 +1023,7 @@ common_download_do(struct terminal *term, int fd, void *data, PRI_DOWNLOAD, CACHE_MODE_NORMAL, file_download->seek); } +/*! @relates cmdw_hop */ static void common_download(struct session *ses, unsigned char *file, enum download_resume resume) @@ -1034,6 +1043,7 @@ common_download(struct session *ses, unsigned char *file, resume, common_download_do, cmdw_hop); } +/*! @relates cmdw_hop */ void start_download(void *ses, unsigned char *file) { @@ -1041,6 +1051,8 @@ start_download(void *ses, unsigned char *file) DOWNLOAD_RESUME_ALLOWED); } + +/*! @relates cmdw_hop */ void resume_download(void *ses, unsigned char *file) { @@ -1050,6 +1062,7 @@ resume_download(void *ses, unsigned char *file) +/*! @relates codw_hop */ static void continue_download_do(struct terminal *term, int fd, void *data, enum download_resume resume) @@ -1100,7 +1113,9 @@ cancel: * to a local file named @a file. * Or an external handler was selected, in which case * type_query.external_handler is non-NULL and @a file does not - * matter because this function will generate a name. */ + * matter because this function will generate a name. + * + * @relates codw_hop */ static void continue_download(void *data, unsigned char *file) { @@ -1136,6 +1151,7 @@ continue_download(void *data, unsigned char *file) } +/*! @relates type_query */ static struct type_query * init_type_query(struct session *ses, struct download *download, struct cache_entry *cached) @@ -1166,6 +1182,7 @@ init_type_query(struct session *ses, struct download *download, return type_query; } +/*! @relates type_query */ void done_type_query(struct type_query *type_query) { @@ -1181,6 +1198,7 @@ done_type_query(struct type_query *type_query) } +/*! @relates type_query */ void tp_cancel(void *data) { @@ -1193,7 +1211,9 @@ tp_cancel(void *data) /** The user chose "Save" when asked what to do with a file. - * Now ask her where to save the file. */ + * Now ask her where to save the file. + * + * @relates type_query */ void tp_save(struct type_query *type_query) { @@ -1202,7 +1222,9 @@ tp_save(struct type_query *type_query) } /** This button handler uses the add_dlg_button() interface so that pressing - * 'Show header' will not close the type query dialog. */ + * 'Show header' will not close the type query dialog. + * + * @relates type_query */ static widget_handler_status_T tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data) { @@ -1217,7 +1239,9 @@ tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data) /** @bug FIXME: We need to modify this function to take frame data * instead, as we want to use this function for frames as well (now, * when frame has content type text/plain, it is ignored and displayed - * as HTML). */ + * as HTML). + * + * @relates type_query */ void tp_display(struct type_query *type_query) { @@ -1249,7 +1273,9 @@ tp_display(struct type_query *type_query) /** The user chose "Open" when asked what to do with a file. * Or an external handler was found and it has been configured - * to run without asking. */ + * to run without asking. + * + * @relates type_query */ static void tp_open(struct type_query *type_query) { @@ -1283,6 +1309,7 @@ tp_open(struct type_query *type_query) } +/*! @relates type_query */ static void do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_handler *handler) { From b427a4f1596bee97089af696760c45fedefabcda Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 17 Jul 2009 23:11:47 +0300 Subject: [PATCH 04/30] Small Doxygen fixes --- src/network/state.h | 2 +- src/scripting/smjs/core.c | 2 +- src/session/download.c | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/network/state.h b/src/network/state.h index f8358b25..b3fa5286 100644 --- a/src/network/state.h +++ b/src/network/state.h @@ -116,7 +116,7 @@ struct connection_state { * structure holds a system error instead. */ enum connection_basic_state basic; - /** When #state is ::S_ERRNO, syserr is the saved value of + /** When #basic is ::S_ERRNO, syserr is the saved value of * errno. Otherwise, syserr should be 0. */ int syserr; }; diff --git a/src/scripting/smjs/core.c b/src/scripting/smjs/core.c index 24939040..ef46d250 100644 --- a/src/scripting/smjs/core.c +++ b/src/scripting/smjs/core.c @@ -251,7 +251,7 @@ utf8_to_jsstring(JSContext *ctx, const unsigned char *str, int length) * @param[in] utf16 * Pointer to the first element in an array of jschars. * - * @param[i] len + * @param[in] len * Number of jschars in the @a utf16 array. * * @return @a utf8 if successful, or NULL if not. */ diff --git a/src/session/download.c b/src/session/download.c index a3ac779d..dde3ded1 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -452,7 +452,7 @@ download_data(struct download *download, struct file_download *file_download) * lun_alternate(), lun_cancel(), lun_overwrite(), and lun_resume(). */ struct lun_hop { /** The terminal in which ELinks is asking the question. - * This gets passed to the callback. */ + * This gets passed to #callback. */ struct terminal *term; /** The name of the local file into which the data was @@ -658,9 +658,9 @@ lun_resume(void *lun_hop_) * not begin. The callback is responsible of doing mem_free(@a file). * * @param data - * A pointer to be passed to @a callback. Although this is a void *, - * it must always point to struct cdf_hop because the pointer can get - * passed to lun_resume(), which assumes so. + * A pointer to be passed to @a callback. If @a resume includes + * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct cdf_hop + * because the pointer can be read by lun_resume(), which assumes so. * * @relates lun_hop */ static void @@ -846,8 +846,8 @@ finish: * * @param real_file * If non-NULL, prepare to save in *@a real_file the name of the local - * file that was eventually opened. The callback must then free this - * string with mem_free(). + * file that was eventually opened. @a callback must then arrange for + * this string to be freed with mem_free(). * * @param safe * If nonzero, give only the user herself access to the file (even if @@ -871,10 +871,10 @@ finish: * will be changed to match what the user chose. * * @param data - * A pointer to be passed to #callback. If the @a resume argument - * given to create_download_file() included ::DOWNLOAD_RESUME_ALLOWED, - * this must point to struct cmdw_hop or struct codw_hop because the - * pointer can be read by lun_resume(), which assumes so. + * A pointer to be passed to @a callback. If @a resume includes + * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct cmdw_hop or + * struct codw_hop because the pointer can be read by lun_resume(), + * which assumes so. * * @relates cdf_hop */ void From 9f217ba8979d21eac9715a52c048103556058672 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 17 Jul 2009 23:16:38 +0300 Subject: [PATCH 05/30] Add typedefs for type_query-related callbacks Doxygen isn't too good at documenting the parameters of a callback within the documentation of a parameter that points to the callback. A typedef provides a better place to document the parameters. --- src/session/download.c | 73 ++++++++++++++++++++++++------------------ src/session/download.h | 32 +++++++++++++++--- src/viewer/text/view.c | 2 ++ 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index dde3ded1..4248b866 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -445,6 +445,28 @@ download_data(struct download *download, struct file_download *file_download) download_data_store(download, file_download); } +/** Type of the callback function that will be called when the user + * answers the question posed by lookup_unique_name(). + * + * @param term + * The terminal on which the callback should display any windows. + * Comes directly from the @a term argument of lookup_unique_name(). + * + * @param file + * The name of the local file to which the data should be downloaded, + * or NULL if the download should not begin. The callback is + * responsible of doing mem_free(@a file). + * + * @param data + * A pointer to any data that the callback cares about. + * Comes directly from the @a data argument of lookup_unique_name(). + * + * @param resume + * Whether the user chose to resume downloading an existing file. + * + * @relates lun_hop */ +typedef void lun_callback_T(struct terminal *term, unsigned char *file, + void *data, enum download_resume resume); /** The user is being asked what to do when the local file for * the download already exists. This structure is allocated by @@ -466,10 +488,8 @@ struct lun_hop { * of #ofile. The string must be freed with mem_free(). */ unsigned char *file; - /** This function will be called when the user answers. - * See lookup_unique_name() for more information. */ - void (*callback)(struct terminal *term, unsigned char *file, - void *data, enum download_resume resume); + /** This function will be called when the user answers. */ + lun_callback_T *callback; /** A pointer to be passed to #callback. If #resume includes * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct @@ -542,9 +562,8 @@ struct cdf_hop { int safe; /** This function will be called when the file has been opened, - * or when it is known that the file will not be opened. - * See create_download_file() for more information. */ - void (*callback)(struct terminal *, int, void *, enum download_resume); + * or when it is known that the file will not be opened. */ + cdf_callback_T *callback; /** A pointer to be passed to #callback. If the @a resume * argument given to create_download_file() included @@ -651,11 +670,7 @@ lun_resume(void *lun_hop_) * * @param callback * Will be called when the user answers, or right away if the question - * need not or cannot be asked. In the parameters of the callback, - * @a term and @a data get their values directly from the arguments of - * lookup_unique_name(). @a file is the name of the local file to - * which the data should be downloaded, or NULL if the download should - * not begin. The callback is responsible of doing mem_free(@a file). + * need not or cannot be asked. * * @param data * A pointer to be passed to @a callback. If @a resume includes @@ -666,9 +681,7 @@ lun_resume(void *lun_hop_) static void lookup_unique_name(struct terminal *term, unsigned char *ofile, enum download_resume resume, - void (*callback)(struct terminal *term, unsigned char *file, - void *data, enum download_resume resume), - void *data) + lun_callback_T *callback, void *data) { /* [gettext_accelerator_context(.lookup_unique_name)] */ struct lun_hop *lun_hop; @@ -753,11 +766,11 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, /** Now that the final name of the download file has been chosen, - * open the file and call the callback that was originally given to - * create_download_file(). + * open the file and call the ::cdf_callback_T that was originally + * given to create_download_file(). * - * create_download_file() passes this function as a callback to - * lookup_unique_name(). + * create_download_file() passes this function as a ::lun_callback_T + * to lookup_unique_name(). * * @relates cdf_hop */ static void @@ -861,14 +874,6 @@ finish: * @param callback * This function will be called when the file has been opened, * or when it is known that the file will not be opened. - * In the parameters of the callback, @a term and @a data get their - * values directly from the arguments of create_download_file(). - * @a fd is a file descriptor to the opened file, or -1 if the file - * will not be opened; the callback may read the name of this file - * from *@a real_file if @a real_file was not NULL. - * @a resume is the same as the @a resume argument of - * create_download_file(), except the ::DOWNLOAD_RESUME_SELECTED bit - * will be changed to match what the user chose. * * @param data * A pointer to be passed to @a callback. If @a resume includes @@ -881,9 +886,7 @@ void create_download_file(struct terminal *term, unsigned char *fi, unsigned char **real_file, int safe, enum download_resume resume, - void (*callback)(struct terminal *term, int fd, - void *data, enum download_resume resume), - void *data) + cdf_callback_T *callback, void *data) { struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop)); unsigned char *wd; @@ -996,7 +999,10 @@ subst_file(unsigned char *prog, unsigned char *file) -/*! @relates cmdw_hop */ +/*! common_download() passes this function as a ::cdf_callback_T to + * create_download_file(). + * + * @relates cmdw_hop */ static void common_download_do(struct terminal *term, int fd, void *data, enum download_resume resume) @@ -1062,7 +1068,10 @@ resume_download(void *ses, unsigned char *file) -/*! @relates codw_hop */ +/*! continue_download() passes this function as a ::cdf_callback_T to + * create_download_file(). + * + * @relates codw_hop */ static void continue_download_do(struct terminal *term, int fd, void *data, enum download_resume resume) diff --git a/src/session/download.h b/src/session/download.h index 9e9dfe2f..871d3737 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -129,13 +129,37 @@ enum download_resume { DOWNLOAD_RESUME_SELECTED = 2 }; +/** Type of the callback function that will be called when the file + * has been opened, or when it is known that the file will not be + * opened. + * + * @param term + * The terminal on which the callback should display any windows. + * Comes directly from the @a term argument of create_download_file(). + * + * @param fd + * A file descriptor to the opened file, or -1 if the file will not be + * opened. If the @a real_file argument of create_download_file() + * was not NULL, the callback may read the name of this file from + * *@a real_file. + * + * @param data + * A pointer to any data that the callback cares about. + * Comes directly from the @a data argument of create_download_file(). + * + * @param resume + * The same as the @a resume argument of create_download_file(), + * except the ::DOWNLOAD_RESUME_SELECTED bit will be changed to match + * what the user chose. + * + * @relates cdf_hop */ +typedef void cdf_callback_T(struct terminal *term, int fd, + void *data, enum download_resume resume); + void start_download(void *, unsigned char *); void resume_download(void *, unsigned char *); void create_download_file(struct terminal *, unsigned char *, unsigned char **, - int, enum download_resume, - void (*)(struct terminal *, int, void *, - enum download_resume), - void *); + int, enum download_resume, cdf_callback_T *, void *); void abort_all_downloads(void); void destroy_downloads(struct session *); diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c index bd72f6b1..f39693fe 100644 --- a/src/viewer/text/view.c +++ b/src/viewer/text/view.c @@ -1615,6 +1615,8 @@ save_as(struct session *ses, struct document_view *doc_view, int magic) return FRAME_EVENT_OK; } +/*! save_formatted() passes this function as a ::cdf_callback_T to + * create_download_finish(). */ static void save_formatted_finish(struct terminal *term, int h, void *data, enum download_resume resume) From 34bb3c4d9509c72c671bff4d7280b8a6ba1c7190 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 18 Jul 2009 02:00:44 +0300 Subject: [PATCH 06/30] More comments about type-query callbacks --- src/protocol/bittorrent/dialogs.c | 12 +++-- src/session/download.c | 84 ++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/src/protocol/bittorrent/dialogs.c b/src/protocol/bittorrent/dialogs.c index 89a6ecb3..ba99de54 100644 --- a/src/protocol/bittorrent/dialogs.c +++ b/src/protocol/bittorrent/dialogs.c @@ -616,8 +616,11 @@ abort_bittorrent_download_query(struct dialog_data *dlg_data) done_bittorrent_download_info(info); } -/* The download button handler. Basicly it redirects to bittorrent: - * and starts displaying the download. */ +/** The download button handler. Basicly it redirects to bittorrent: + * and starts displaying the download. + * + * bittorrent_query_callback() passes this function as a + * ::widget_handler_T to add_dlg_button(). */ static widget_handler_status_T bittorrent_download(struct dialog_data *dlg_data, struct widget_data *widget_data) { @@ -685,7 +688,10 @@ tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data) return EVENT_PROCESSED; } -/* Build a dialog querying the user on how to handle a .torrent file. */ +/** Build a dialog querying the user on how to handle a .torrent file. + * + * query_bittorrent_dialog() passes this function as a + * ::bittorrent_fetch_callback_T to init_bittorrent_fetch(). */ static void bittorrent_query_callback(void *data, struct connection_state state, struct string *response) diff --git a/src/session/download.c b/src/session/download.c index 4248b866..ae7c6978 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -509,7 +509,10 @@ struct lun_hop { * with int magic, whose value is one of these * constants. */ enum { + /** struct cmdw_hop */ COMMON_DOWNLOAD_DO = 0, + + /** struct codw_hop */ CONTINUE_DOWNLOAD_DO }; @@ -573,6 +576,13 @@ struct cdf_hop { void *data; }; +/** The use chose "Save under the alternative name" when asked where + * to download a file. + * + * lookup_unique_name() passes this function as a ::done_handler_T to + * msg_box(). + * + * @relates lun_hop */ static void lun_alternate(void *lun_hop_) { @@ -584,6 +594,12 @@ lun_alternate(void *lun_hop_) mem_free(lun_hop); } +/** The use chose "Cancel" when asked where to download a file. + * + * lookup_unique_name() passes this function as a ::done_handler_T to + * msg_box(). + * + * @relates lun_hop */ static void lun_cancel(void *lun_hop_) { @@ -596,6 +612,13 @@ lun_cancel(void *lun_hop_) mem_free(lun_hop); } +/** The use chose "Overwrite the original file" when asked where to + * download a file. + * + * lookup_unique_name() passes this function as a ::done_handler_T to + * msg_box(). + * + * @relates lun_hop */ static void lun_overwrite(void *lun_hop_) { @@ -610,7 +633,13 @@ lun_overwrite(void *lun_hop_) static void common_download_do(struct terminal *term, int fd, void *data, enum download_resume resume); -/*! @relates lun_hop */ +/** The user chose "Resume download of the original file" when asked + * where to download a file. + * + * lookup_unique_name() passes this function as a ::done_handler_T to + * msg_box(). + * + * @relates lun_hop */ static void lun_resume(void *lun_hop_) { @@ -1124,6 +1153,8 @@ cancel: * type_query.external_handler is non-NULL and @a file does not * matter because this function will generate a name. * + * tp_save() passes this function as the @c std callback to query_file(). + * * @relates codw_hop */ static void continue_download(void *data, unsigned char *file) @@ -1160,7 +1191,11 @@ continue_download(void *data, unsigned char *file) } -/*! @relates type_query */ +/** Prepare to ask the user what to do with a file, but don't display + * the window yet. To display it, do_type_query() must be called + * separately. setup_download_handler() takes care of that. + * + * @relates type_query */ static struct type_query * init_type_query(struct session *ses, struct download *download, struct cache_entry *cached) @@ -1191,7 +1226,10 @@ init_type_query(struct session *ses, struct download *download, return type_query; } -/*! @relates type_query */ +/** Cancel any download stated for @a type_query, remove the structure + * from the session.type_queries list, and free it. + * + * @relates type_query */ void done_type_query(struct type_query *type_query) { @@ -1207,7 +1245,14 @@ done_type_query(struct type_query *type_query) } -/*! @relates type_query */ +/** The user chose "Cancel" when asked what to do with a file, + * or the type query was cancelled for some other reason. + * + * do_type_query() and bittorrent_query_callback() pass this function + * as a ::done_handler_T to add_dlg_ok_button(), and tp_save() passes + * this function as a @c cancel callback to query_file(). + * + * @relates type_query */ void tp_cancel(void *data) { @@ -1222,6 +1267,9 @@ tp_cancel(void *data) /** The user chose "Save" when asked what to do with a file. * Now ask her where to save the file. * + * do_type_query() and bittorrent_query_callback() pass this function + * as a ::done_handler_T to add_dlg_ok_button(). + * * @relates type_query */ void tp_save(struct type_query *type_query) @@ -1230,8 +1278,12 @@ tp_save(struct type_query *type_query) query_file(type_query->ses, type_query->uri, type_query, continue_download, tp_cancel, 1); } -/** This button handler uses the add_dlg_button() interface so that pressing - * 'Show header' will not close the type query dialog. +/** The user chose "Show header" when asked what to do with a file. + * + * do_type_query() passes this function as a ::widget_handler_T to + * add_dlg_button(). Unlike with add_dlg_ok_button(), pressing this + * button does not close the dialog box. This way, the user can + * first examine the header and then choose what to do. * * @relates type_query */ static widget_handler_status_T @@ -1245,7 +1297,13 @@ tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data) } -/** @bug FIXME: We need to modify this function to take frame data +/** The user chose "Display" when asked what to do with a file, + * or she chose "Open" and there is no external handler. + * + * do_type_query() and bittorrent_query_callback() pass this function + * as a ::done_handler_T to add_dlg_ok_button(). + * + * @bug FIXME: We need to modify this function to take frame data * instead, as we want to use this function for frames as well (now, * when frame has content type text/plain, it is ignored and displayed * as HTML). @@ -1284,6 +1342,9 @@ tp_display(struct type_query *type_query) * Or an external handler was found and it has been configured * to run without asking. * + * do_type_query() passes this function as a ::done_handler_T to + * add_dlg_ok_button(). + * * @relates type_query */ static void tp_open(struct type_query *type_query) @@ -1318,7 +1379,13 @@ tp_open(struct type_query *type_query) } -/*! @relates type_query */ +/*! Ask the user what to do with a file. + * + * This function does not support BitTorrent downloads. + * For those, query_bittorrent_dialog() must be called instead. + * setup_download_handler() takes care of this. + * + * @relates type_query */ static void do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_handler *handler) { @@ -1500,6 +1567,7 @@ struct { { NULL, 1 }, }; +/*! @relates type_query */ int setup_download_handler(struct session *ses, struct download *loading, struct cache_entry *cached, int frame) From 519284654bbc8800b9ab186a0ac40ab96eb113ee Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 18 Jul 2009 18:09:36 +0300 Subject: [PATCH 07/30] Typo fix --- src/session/download.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session/download.c b/src/session/download.c index ae7c6978..a39ad7e4 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -1226,7 +1226,7 @@ init_type_query(struct session *ses, struct download *download, return type_query; } -/** Cancel any download stated for @a type_query, remove the structure +/** Cancel any download started for @a type_query, remove the structure * from the session.type_queries list, and free it. * * @relates type_query */ From a92bdcf02dc48d8314d282bec871a5ff8fcaefff Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 18 Jul 2009 19:37:29 +0300 Subject: [PATCH 08/30] Document add_dlg_button, add_dlg_ok_button --- src/bfu/button.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/bfu/button.h b/src/bfu/button.h index ca7b3d65..a1a46cf5 100644 --- a/src/bfu/button.h +++ b/src/bfu/button.h @@ -28,6 +28,47 @@ struct widget_info_button { /* Define to find buttons without keyboard accelerator. */ /* #define DEBUG_BUTTON_HOTKEY */ +/** @def add_dlg_ok_button + * Add a button that will close the dialog if pressed. + * + * void add_dlg_ok_button(struct dialog *dlg, unsigned char *text, int flags, + * ::done_handler_T *done, void *done_data); + * + * @param dlg + * The dialog in which the button is to be added. + * + * @param text + * Text displayed in the button. This string should contain a + * keyboard accelerator, marked with a preceding '~'. The pointer + * must remain valid as long as the dialog exists. + * + * @param flags + * Can be ::B_ENTER, ::B_ESC, or 0. + * + * @param done + * A function that BFU calls when the user presses this button. + * Before calling this, BFU checks the values of widgets. + * After the function returns, BFU closes the dialog. + * + * @param done_data + * A pointer to be passed to the @a done callback. */ + +/** @def add_dlg_button + * Add a button that need not close the dialog if pressed. + * + * void add_dlg_button(struct dialog *dlg, unsigned char *text, int flags, + * ::widget_handler_t *handler, void *data); + * + * @param handler + * A function that BFU calls when the user presses this button. + * BFU does not automatically check the values of widgets + * or close the dialog. + * + * @param data + * A pointer to any data needed by @a handler. It does not get this + * pointer as a parameter but can read it from widget_data->widget->data. + * + * The other parameters are as in ::add_dlg_ok_button. */ #ifdef DEBUG_BUTTON_HOTKEY void add_dlg_button_do(const unsigned char *file, int line, struct dialog *dlg, unsigned char *text, int flags, widget_handler_T *handler, void *data, done_handler_T *done, void *done_data); From 62316163f3110933045e83b9cb10c2410b376bf7 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 18 Jul 2009 23:31:10 +0300 Subject: [PATCH 09/30] Comment fixes --- src/bfu/button.h | 6 +++--- src/protocol/bittorrent/common.h | 2 +- src/session/download.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bfu/button.h b/src/bfu/button.h index a1a46cf5..e6e907db 100644 --- a/src/bfu/button.h +++ b/src/bfu/button.h @@ -32,7 +32,7 @@ struct widget_info_button { * Add a button that will close the dialog if pressed. * * void add_dlg_ok_button(struct dialog *dlg, unsigned char *text, int flags, - * ::done_handler_T *done, void *done_data); + * ::done_handler_T *done, void *data); * * @param dlg * The dialog in which the button is to be added. @@ -50,14 +50,14 @@ struct widget_info_button { * Before calling this, BFU checks the values of widgets. * After the function returns, BFU closes the dialog. * - * @param done_data + * @param data * A pointer to be passed to the @a done callback. */ /** @def add_dlg_button * Add a button that need not close the dialog if pressed. * * void add_dlg_button(struct dialog *dlg, unsigned char *text, int flags, - * ::widget_handler_t *handler, void *data); + * ::widget_handler_T *handler, void *data); * * @param handler * A function that BFU calls when the user presses this button. diff --git a/src/protocol/bittorrent/common.h b/src/protocol/bittorrent/common.h index 287f4ba3..5062b421 100644 --- a/src/protocol/bittorrent/common.h +++ b/src/protocol/bittorrent/common.h @@ -32,7 +32,7 @@ struct terminal; #define BITTORRENT_REQUEST_LENGTH (1 << 14) /** The length of requested blocks of pieces should not exceed 2^17 bytes. - * Used for the protocol.bittorrent.max_request_length option + * Used for the protocol.bittorrent.max_request_length option. * Bram uses 2^23 here. */ #define BITTORRENT_REQUEST_ACCEPT_LENGTH (1 << 23) diff --git a/src/session/download.h b/src/session/download.h index 871d3737..0802fac1 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -117,8 +117,8 @@ int are_there_downloads(void); /** Whether to resume downloading to a file. This is a bit mask. * Unrecognized bits should be preserved and ignored. */ enum download_resume { - /** All bits clear. Downloading cannot be resumed; do not - * offer such an option to the user. */ + /** Downloading cannot be resumed; do not offer such an option + * to the user. All bits clear. */ DOWNLOAD_RESUME_DISABLED = 0, /** Downloading can be resumed. This is the usual value. */ From 126d2d1be33df37137f488c47aac78b2cdedf9b1 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 02:09:38 +0300 Subject: [PATCH 10/30] Remove enum {main,edit,menu}_action_offset Remove enum main_action_offset, enum edit_action_offset, and enum menu_action_offset. It seems the original plan (in commit 174eabf1a448d3f084a318aab77805828f35c42e on 2005-05-16) was to include the action flags in the action IDs, perhaps with something like: ACT_##map##_##action = ACT_##map##_OFFSET_##action | flags However, this OR operation was never implemented; each ACT_*_* constant had the same value as the corresponding ACT_*_OFFSET_*, and the code that looked for flags in action IDs found only zeroes. Then on 2005-06-10, a separate action.flags member was added, and the flag checks were corrected to read that instead. So, it seems safe to say that the original plan has been discarded and the offset enumerations won't be needed. --- src/config/kbdbind.h | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/config/kbdbind.h b/src/config/kbdbind.h index e046fd8b..c24df275 100644 --- a/src/config/kbdbind.h +++ b/src/config/kbdbind.h @@ -53,42 +53,26 @@ enum action_flags { * and also update the table action_table[] in kbdbind.c. */ #define ACTION_(map, name, action, caption, flags) \ - ACT_##map##_OFFSET_##action + ACT_##map##_##action -enum main_action_offset { +enum main_action { #include "config/actions-main.inc" MAIN_ACTIONS, }; -enum edit_action_offset { +enum edit_action { #include "config/actions-edit.inc" EDIT_ACTIONS }; -enum menu_action_offset { +enum menu_action { #include "config/actions-menu.inc" MENU_ACTIONS }; -#undef ACTION_ -#define ACTION_(map, name, action, caption, flags) \ - ACT_##map##_##action - -enum main_action { -#include "config/actions-main.inc" -}; - -enum edit_action { -#include "config/actions-edit.inc" -}; - -enum menu_action { -#include "config/actions-menu.inc" -}; - #undef ACTION_ enum kbdbind_flags { From 49a8be75bbc9866d30a50cb191744d4dcb03a3fc Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 02:20:43 +0300 Subject: [PATCH 11/30] Doxyfile: Expand ACTION_ as defined This lets Doxygen generate links for ACT_MAIN_SAVE_AS and others. --- doc/Doxyfile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 480a1f9e..eaef8815 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -230,7 +230,8 @@ PREDEFINED = "LIST_OF(element_T)=element_T list" \ CONFIG_UTF8 \ HAVE_VARIADIC_MACROS EXPAND_AS_DEFINED = LIST_HEAD \ - INIT_LIST_OF + INIT_LIST_OF \ + ACTION_ SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- From c7b4d5de97fd640530355f11cf61d04630a53d1d Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 03:18:11 +0300 Subject: [PATCH 12/30] Fix file name leaks if init_file_download fails If init_file_download() succeeds (returning non-NULL), it saves the file-name pointer to file_download->file, whence abort_download() will free it. However, if init_file_download() fails, the caller is responsible of freeing the name. bittorrent_download() already did so but common_download_do() and continue_download_do() didn't. --- src/session/download.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index a39ad7e4..da14f719 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -87,6 +87,7 @@ are_there_downloads(void) static void download_data(struct download *download, struct file_download *file_download); +/*! @note If this fails, the caller is responsible of freeing @a file. */ struct file_download * init_file_download(struct uri *uri, struct session *ses, unsigned char *file, int fd) { @@ -1044,10 +1045,11 @@ common_download_do(struct terminal *term, int fd, void *data, mem_free(cmdw_hop); - if (!file || fstat(fd, &buf)) return; + if (!file || fstat(fd, &buf)) goto finish; file_download = init_file_download(ses->download_uri, ses, file, fd); - if (!file_download) return; + if (!file_download) goto finish; + file = NULL; /* init_file_download takes ownership on success */ if (resume & DOWNLOAD_RESUME_SELECTED) file_download->seek = buf.st_size; @@ -1056,6 +1058,9 @@ common_download_do(struct terminal *term, int fd, void *data, load_uri(file_download->uri, ses->referrer, &file_download->download, PRI_DOWNLOAD, CACHE_MODE_NORMAL, file_download->seek); + +finish: + mem_free_if(file); } /*! @relates cmdw_hop */ @@ -1120,6 +1125,7 @@ continue_download_do(struct terminal *term, int fd, void *data, file_download = init_file_download(type_query->uri, type_query->ses, codw_hop->real_file, fd); if (!file_download) goto cancel; + codw_hop->real_file = NULL; /* init_file_download takes ownership on success */ if (type_query->external_handler) { file_download->external_handler = subst_file(type_query->external_handler, @@ -1142,6 +1148,7 @@ continue_download_do(struct terminal *term, int fd, void *data, return; cancel: + mem_free_if(codw_hop->real_file); if (type_query->external_handler) mem_free_if(codw_hop->file); tp_cancel(type_query); mem_free(codw_hop); From 266d4df2d291ee10271fcaeb9a38a7caf2c99cd0 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 03:57:10 +0300 Subject: [PATCH 13/30] Fix file descriptor leaks if init_file_download fails If init_file_download() succeeds (returning non-NULL), it saves the file descriptor to file_download->handle, whence abort_download() will close it. However, if init_file_download() fails, the caller is responsible of closing the file, something common_download_do() and continue_download_do() failed to do. There was no problem with bittorrent_download() because that uses -1 as the fd. --- src/session/download.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index da14f719..ff48f366 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -87,7 +87,8 @@ are_there_downloads(void) static void download_data(struct download *download, struct file_download *file_download); -/*! @note If this fails, the caller is responsible of freeing @a file. */ +/*! @note If this fails, the caller is responsible of freeing @a file + * and closing @a fd. */ struct file_download * init_file_download(struct uri *uri, struct session *ses, unsigned char *file, int fd) { @@ -1049,7 +1050,10 @@ common_download_do(struct terminal *term, int fd, void *data, file_download = init_file_download(ses->download_uri, ses, file, fd); if (!file_download) goto finish; - file = NULL; /* init_file_download takes ownership on success */ + /* If init_file_download succeeds, it takes ownership of file + * and fd. */ + file = NULL; + fd = -1; if (resume & DOWNLOAD_RESUME_SELECTED) file_download->seek = buf.st_size; @@ -1061,6 +1065,7 @@ common_download_do(struct terminal *term, int fd, void *data, finish: mem_free_if(file); + if (fd != -1) close(fd); } /*! @relates cmdw_hop */ @@ -1125,7 +1130,10 @@ continue_download_do(struct terminal *term, int fd, void *data, file_download = init_file_download(type_query->uri, type_query->ses, codw_hop->real_file, fd); if (!file_download) goto cancel; - codw_hop->real_file = NULL; /* init_file_download takes ownership on success */ + /* If init_file_download succeeds, it takes ownership of + * codw_hop->real_file and fd. */ + codw_hop->real_file = NULL; + fd = -1; if (type_query->external_handler) { file_download->external_handler = subst_file(type_query->external_handler, @@ -1149,6 +1157,7 @@ continue_download_do(struct terminal *term, int fd, void *data, cancel: mem_free_if(codw_hop->real_file); + if (fd != -1) close(fd); if (type_query->external_handler) mem_free_if(codw_hop->file); tp_cancel(type_query); mem_free(codw_hop); From 38d7bffcedc2bb41155082cb2193f4510fa49899 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 02:08:50 +0300 Subject: [PATCH 14/30] Bug 770: Document session.download_uri --- src/session/download.c | 25 ++++++++++++++++++++++--- src/session/session.h | 11 +++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index ff48f366..ff14f3a2 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -1068,7 +1068,13 @@ finish: if (fd != -1) close(fd); } -/*! @relates cmdw_hop */ +/** Begin or resume downloading from session.download_uri to the + * @a file specified by the user. + * + * This function contains the code shared between start_download() and + * resume_download(). + * + * @relates cmdw_hop */ static void common_download(struct session *ses, unsigned char *file, enum download_resume resume) @@ -1088,7 +1094,14 @@ common_download(struct session *ses, unsigned char *file, resume, common_download_do, cmdw_hop); } -/*! @relates cmdw_hop */ +/** Begin downloading from session.download_uri to the @a file + * specified by the user. + * + * The ::ACT_MAIN_SAVE_AS, ::ACT_MAIN_SAVE_URL_AS, + * ::ACT_MAIN_LINK_DOWNLOAD, and ::ACT_MAIN_LINK_DOWNLOAD_IMAGE + * actions pass this function as the @c std callback to query_file(). + * + * @relates cmdw_hop */ void start_download(void *ses, unsigned char *file) { @@ -1097,7 +1110,13 @@ start_download(void *ses, unsigned char *file) } -/*! @relates cmdw_hop */ +/** Resume downloading from session.download_uri to the @a file + * specified by the user. + * + * The ::ACT_MAIN_LINK_DOWNLOAD_RESUME action passes this function as + * the @c std callback to query_file(). + * + * @relates cmdw_hop */ void resume_download(void *ses, unsigned char *file) { diff --git a/src/session/session.h b/src/session/session.h index d32c38e5..e36d655b 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -159,6 +159,17 @@ struct session { struct document_view *doc_view; LIST_OF(struct document_view) scrn_frames; + /** The URI from which start_download() or resume_download() + * should download. + * + * When the user requests a download, one of those functions + * is given as a callback to query_file(), which asks the user + * where to save the downloaded file. The URI cannot be given + * to the callback as a parameter because query_file() + * supports only one void * parameter for the callback and + * that one is already used for the struct session *. + * Instead, the URI is saved here before the query_file() + * call. */ struct uri *download_uri; /** The URI which is the referrer to the current loaded document From 2f04a38c6f2d29a5b8a484cc350a9bd648c86548 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 02:34:54 +0300 Subject: [PATCH 15/30] Bug 770: Fix URI leak in lun_resume To reproduce: - Configure with --enable-debug. - Go to http://elinks.cz/ - Set the cursor on the "About" link and press d to download, - ELinks asks where to save the file. Cancel that with Esc. This leaves session.download_uri != NULL. - Go to /etc/passwd - ELinks asks what to do with the file. Choose to download. - ELinks asks where to save the file. Type the name of a new file and press Enter. - Again go to /etc/passwd - ELinks asks what to do with the file. Choose to download. - ELinks asks where to save the file. Type the same name as before and press Enter. - ELinks asks whether to resume or overwrite. Choose to resume. This changes session.download_uri and leaks the original URI. - Quit ELinks. It reports memory leaks: 0x88936d8:28 @ alloc'd at /home/Kalle/src/elinks-0.12/src/util/hash.c:89 0x88dac00:95 @ alloc'd at /home/Kalle/src/elinks-0.12/src/protocol/uri.c:1551 0x88c33a8:4104 @ alloc'd at /home/Kalle/src/elinks-0.12/src/util/hash.c:41 This commit fixes the leak, but it's still a bug that lun_resume() can replace the session.download_uri that will be used by another pending download. In particular, this might happen if the user first presses d to download, and then while ELinks is asking for the file name, a web script changes window.location to a different URI and that causes ELinks to ask what to do with the file. So I'm leaving the FIXME comment in for now. --- src/session/download.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/session/download.c b/src/session/download.c index ff14f3a2..8a4d4100 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -663,6 +663,8 @@ lun_resume(void *lun_hop_) cmdw_hop->magic = COMMON_DOWNLOAD_DO; cmdw_hop->ses = type_query->ses; /* FIXME: Current ses->download_uri is overwritten here --witekfl */ + if (cmdw_hop->ses->download_uri) + done_uri(cmdw_hop->ses->download_uri); cmdw_hop->ses->download_uri = get_uri_reference(type_query->uri); if (type_query->external_handler) mem_free_if(codw_hop->file); From b7d03f9b044e69e712b8c66ff9a4974f6ab564a5 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 18 Jul 2009 21:57:40 +0300 Subject: [PATCH 16/30] Bug 770: Move codw->cmdw transform to outer layer Commit ff136e5116a750d7c6d8368d170d7a7f3d4920a4 on 2006-07-16 made lun_resume() check if cdf_hop->data points to struct codw_hop, and transform that to struct cmdw_hop if so. Move the transform into a separate function called from continue_download_do(). This way, the structures used with create_download_file() no longer need to begin with int magic. --- src/session/download.c | 95 +++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 8a4d4100..45185e68 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -506,24 +506,9 @@ struct lun_hop { enum download_resume resume; }; -/** To let lun_resume() detect whether cdf_hop.data points to struct - * cmdw_hop or to struct codw_hop, each of those structures begins - * with int magic, whose value is one of these - * constants. */ -enum { - /** struct cmdw_hop */ - COMMON_DOWNLOAD_DO = 0, - - /** struct codw_hop */ - CONTINUE_DOWNLOAD_DO -}; - /** Data saved by common_download() for the common_download_do() * callback. */ struct cmdw_hop { - /** Always ::COMMON_DOWNLOAD_DO. */ - int magic; /* Must be first --witekfl */ - struct session *ses; /** The name of the local file to which the data will be @@ -537,9 +522,6 @@ struct cmdw_hop { /** Data saved by continue_download() for the continue_download_do() * callback. */ struct codw_hop { - /** Always ::CONTINUE_DOWNLOAD_DO. */ - int magic; /* must be first --witekfl */ - struct type_query *type_query; /** The name of the local file to which the data will be @@ -570,11 +552,7 @@ struct cdf_hop { * or when it is known that the file will not be opened. */ cdf_callback_T *callback; - /** A pointer to be passed to #callback. If the @a resume - * argument given to create_download_file() included - * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct - * cmdw_hop or struct codw_hop because the pointer can be - * read by lun_resume(), which assumes so. */ + /** A pointer to be passed to #callback. */ void *data; }; @@ -632,9 +610,6 @@ lun_overwrite(void *lun_hop_) mem_free(lun_hop); } -static void common_download_do(struct terminal *term, int fd, void *data, - enum download_resume resume); - /** The user chose "Resume download of the original file" when asked * where to download a file. * @@ -646,36 +621,7 @@ static void lun_resume(void *lun_hop_) { struct lun_hop *lun_hop = lun_hop_; - struct cdf_hop *cdf_hop = lun_hop->data; - int magic = *(int *)cdf_hop->data; - - if (magic == CONTINUE_DOWNLOAD_DO) { - struct cmdw_hop *cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); - - if (!cmdw_hop) { - lun_cancel(lun_hop); - return; - } else { - struct codw_hop *codw_hop = cdf_hop->data; - struct type_query *type_query = codw_hop->type_query; - - cmdw_hop->magic = COMMON_DOWNLOAD_DO; - cmdw_hop->ses = type_query->ses; - /* FIXME: Current ses->download_uri is overwritten here --witekfl */ - if (cmdw_hop->ses->download_uri) - done_uri(cmdw_hop->ses->download_uri); - cmdw_hop->ses->download_uri = get_uri_reference(type_query->uri); - - if (type_query->external_handler) mem_free_if(codw_hop->file); - tp_cancel(type_query); - mem_free(codw_hop); - - cdf_hop->real_file = &cmdw_hop->real_file; - cdf_hop->data = cmdw_hop; - cdf_hop->callback = common_download_do; - } - } lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, lun_hop->resume | DOWNLOAD_RESUME_SELECTED); mem_free_if(lun_hop->file); @@ -909,10 +855,7 @@ finish: * or when it is known that the file will not be opened. * * @param data - * A pointer to be passed to @a callback. If @a resume includes - * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct cmdw_hop or - * struct codw_hop because the pointer can be read by lun_resume(), - * which assumes so. + * A pointer to be passed to @a callback. * * @relates cdf_hop */ void @@ -1088,7 +1031,6 @@ common_download(struct session *ses, unsigned char *file, cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); if (!cmdw_hop) return; cmdw_hop->ses = ses; - cmdw_hop->magic = COMMON_DOWNLOAD_DO; kill_downloads_to_file(file); @@ -1126,7 +1068,34 @@ resume_download(void *ses, unsigned char *file) DOWNLOAD_RESUME_ALLOWED | DOWNLOAD_RESUME_SELECTED); } +/** Resume downloading a file, based on information in struct + * codw_hop. This function actually starts a new download from the + * current end of the file, even though a download from the beginning + * is already in progress at codw_hop->type_query->download. The + * caller will cancel the preexisting download after this function + * returns. + * + * @relates codw_hop */ +static void +transform_codw_to_cmdw(struct terminal *term, int fd, + struct codw_hop *codw_hop, + enum download_resume resume) +{ + struct type_query *type_query = codw_hop->type_query; + struct cmdw_hop *cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); + if (!cmdw_hop) return; + + cmdw_hop->ses = type_query->ses; + /* FIXME: Current ses->download_uri is overwritten here --witekfl */ + if (cmdw_hop->ses->download_uri) + done_uri(cmdw_hop->ses->download_uri); + cmdw_hop->ses->download_uri = get_uri_reference(type_query->uri); + cmdw_hop->real_file = codw_hop->real_file; + codw_hop->real_file = NULL; + + common_download_do(term, fd, cmdw_hop, resume); +} /*! continue_download() passes this function as a ::cdf_callback_T to * create_download_file(). @@ -1148,6 +1117,11 @@ continue_download_do(struct terminal *term, int fd, void *data, type_query = codw_hop->type_query; if (!codw_hop->real_file) goto cancel; + if (resume & DOWNLOAD_RESUME_SELECTED) { + transform_codw_to_cmdw(term, fd, codw_hop, resume); + goto cancel; + } + file_download = init_file_download(type_query->uri, type_query->ses, codw_hop->real_file, fd); if (!file_download) goto cancel; @@ -1216,7 +1190,6 @@ continue_download(void *data, unsigned char *file) codw_hop->type_query = type_query; codw_hop->file = file; - codw_hop->magic = CONTINUE_DOWNLOAD_DO; kill_downloads_to_file(file); From 075171c2c8cce6fc72863fa8b0d41b7acbf31eba Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 03:24:55 +0300 Subject: [PATCH 17/30] Bug 770: Shorten lifetime of session.download_uri In common_download(), move session.download_uri to the new member cmdw_hop.download_uri, which common_download_do() then reads. This shields the download request against possible session.download_uri changes made for other downloads. And transform_codw_to_cmdw() no longer needs to touch session.download_uri at all, solving a FIXME. --- src/session/download.c | 14 +++++++++----- src/session/session.h | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 45185e68..cc516a3a 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -511,6 +511,9 @@ struct lun_hop { struct cmdw_hop { struct session *ses; + /** The URI from which the data will be downloaded. */ + struct uri *download_uri; + /** The name of the local file to which the data will be * downloaded. This is initially NULL, but its address is * given to create_download_file(), which arranges for the @@ -985,6 +988,7 @@ common_download_do(struct terminal *term, int fd, void *data, { struct file_download *file_download; struct cmdw_hop *cmdw_hop = data; + struct uri *download_uri = cmdw_hop->download_uri; unsigned char *file = cmdw_hop->real_file; struct session *ses = cmdw_hop->ses; struct stat buf; @@ -993,7 +997,7 @@ common_download_do(struct terminal *term, int fd, void *data, if (!file || fstat(fd, &buf)) goto finish; - file_download = init_file_download(ses->download_uri, ses, file, fd); + file_download = init_file_download(download_uri, ses, file, fd); if (!file_download) goto finish; /* If init_file_download succeeds, it takes ownership of file * and fd. */ @@ -1011,6 +1015,7 @@ common_download_do(struct terminal *term, int fd, void *data, finish: mem_free_if(file); if (fd != -1) close(fd); + done_uri(download_uri); } /** Begin or resume downloading from session.download_uri to the @@ -1031,6 +1036,8 @@ common_download(struct session *ses, unsigned char *file, cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); if (!cmdw_hop) return; cmdw_hop->ses = ses; + cmdw_hop->download_uri = ses->download_uri; + ses->download_uri = NULL; kill_downloads_to_file(file); @@ -1087,10 +1094,7 @@ transform_codw_to_cmdw(struct terminal *term, int fd, if (!cmdw_hop) return; cmdw_hop->ses = type_query->ses; - /* FIXME: Current ses->download_uri is overwritten here --witekfl */ - if (cmdw_hop->ses->download_uri) - done_uri(cmdw_hop->ses->download_uri); - cmdw_hop->ses->download_uri = get_uri_reference(type_query->uri); + cmdw_hop->download_uri = get_uri_reference(type_query->uri); cmdw_hop->real_file = codw_hop->real_file; codw_hop->real_file = NULL; diff --git a/src/session/session.h b/src/session/session.h index e36d655b..bbf3dcb7 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -159,8 +159,8 @@ struct session { struct document_view *doc_view; LIST_OF(struct document_view) scrn_frames; - /** The URI from which start_download() or resume_download() - * should download. + /** The URI from which the next start_download() or resume_download() + * call should download, or NULL if no such call is pending. * * When the user requests a download, one of those functions * is given as a callback to query_file(), which asks the user From 89c7e57890c534f95f7139fa682c2675ed9ee3b5 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 13:41:44 +0300 Subject: [PATCH 18/30] Bug 770: Don't close fd when resuming download I added this bug last night. continue_download_do() passed the file descriptor to transform_codw_to_cmdw(), which saved it, but continue_download_do() then closed it. --- src/session/download.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/session/download.c b/src/session/download.c index cc516a3a..8620f68a 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -1091,7 +1091,10 @@ transform_codw_to_cmdw(struct terminal *term, int fd, struct type_query *type_query = codw_hop->type_query; struct cmdw_hop *cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); - if (!cmdw_hop) return; + if (!cmdw_hop) { + close(fd); + return; + } cmdw_hop->ses = type_query->ses; cmdw_hop->download_uri = get_uri_reference(type_query->uri); @@ -1123,6 +1126,7 @@ continue_download_do(struct terminal *term, int fd, void *data, if (resume & DOWNLOAD_RESUME_SELECTED) { transform_codw_to_cmdw(term, fd, codw_hop, resume); + fd = -1; /* ownership transfer */ goto cancel; } From 23fd2d58f45f86033dc64e46876601afb01a2c96 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 20:16:42 +0300 Subject: [PATCH 19/30] Make struct action const With GCC 4.3.1 on i686, this changes the sizes of sections as follows: section before after change .text 682428 682492 +64 .rodata 212668 216352 +3684 .data 58092 54444 -3648 .debug_info 1482388 1482472 +84 .debug_abbrev 153714 153723 +9 .debug_line 272299 272319 +20 .debug_loc 540394 540372 -22 .debug_ranges 113784 113792 +8 Total 3917695 3917894 +199 The surprising .text change comes from src/config/dialogs.o. Some of that is in get_keybinding_text(), where GCC changes the order of basic blocks and apparently misses some optimizations. --- src/config/dialogs.c | 16 +++++++++------- src/config/dialogs.h | 3 ++- src/config/kbdbind.c | 34 +++++++++++++++++----------------- src/config/kbdbind.h | 16 ++++++++-------- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/config/dialogs.c b/src/config/dialogs.c index 6a11c63f..235b62f5 100644 --- a/src/config/dialogs.c +++ b/src/config/dialogs.c @@ -549,10 +549,11 @@ get_keybinding_action_box_item(enum keymap_id keymap_id, action_id_T action_id) struct listbox_item *keymap_box_item[KEYMAP_MAX]; void -init_keybinding_listboxes(struct keymap keymap_table[KEYMAP_MAX], struct action_list actions[]) +init_keybinding_listboxes(struct keymap keymap_table[KEYMAP_MAX], + const struct action_list actions[]) { struct listbox_item *root = &keybinding_browser.root; - struct action *act; + const struct action *act; enum keymap_id keymap_id; /* Do it backwards because add_listbox_item() add to front @@ -577,7 +578,8 @@ init_keybinding_listboxes(struct keymap keymap_table[KEYMAP_MAX], struct action_ assert(act->desc); #endif - item = add_listbox_item(NULL, keymap_box, BI_FOLDER, act, -1); + item = add_listbox_item(NULL, keymap_box, BI_FOLDER, + (void *) act, -1); if (!item) continue; item->expanded = 1; @@ -644,7 +646,7 @@ get_keybinding_text(struct listbox_item *item, struct terminal *term) return stracpy(keybinding_text_toggle ? keymap->str : _(keymap->desc, term)); } else if (item->depth < 2) { - struct action *action = item->udata; + const struct action *action = item->udata; return stracpy(keybinding_text_toggle ? action->str : _(action->desc, term)); @@ -686,7 +688,7 @@ get_keybinding_root(struct listbox_item *item) if (item->depth == 0) return NULL; if (item->depth == 1) { - struct action *action = item->udata; + const struct action *action = item->udata; return keymap_box_item[action->keymap_id]; } else { @@ -700,7 +702,7 @@ static enum listbox_match match_keybinding(struct listbox_item *item, struct terminal *term, unsigned char *text) { - struct action *action = item->udata; + const struct action *action = item->udata; unsigned char *desc; if (item->depth != 1) @@ -872,7 +874,7 @@ push_kbdbind_add_button(struct dialog_data *dlg_data, hop->action_id = keybinding->action_id; hop->keymap_id = keybinding->keymap_id; } else { - struct action *action = item->udata; + const struct action *action = item->udata; hop->action_id = action->num; hop->keymap_id = action->keymap_id; diff --git a/src/config/dialogs.h b/src/config/dialogs.h index e5f01ed3..60ec88f7 100644 --- a/src/config/dialogs.h +++ b/src/config/dialogs.h @@ -16,7 +16,8 @@ void options_manager(struct session *); void keybinding_manager(struct session *); struct listbox_item *get_keybinding_action_box_item(enum keymap_id keymap_id, action_id_T action_id); -void init_keybinding_listboxes(struct keymap keymap_table[], struct action_list actions[]); +void init_keybinding_listboxes(struct keymap keymap_table[], + const struct action_list actions[]); void done_keybinding_listboxes(void); #endif diff --git a/src/config/kbdbind.c b/src/config/kbdbind.c index 8c495f49..9fb00e91 100644 --- a/src/config/kbdbind.c +++ b/src/config/kbdbind.c @@ -26,7 +26,7 @@ /* Fix namespace clash on MacOS. */ #define table table_elinks -static struct action_list action_table[KEYMAP_MAX]; +static const struct action_list action_table[KEYMAP_MAX]; static struct keymap keymap_table[KEYMAP_MAX]; static LIST_OF(struct keybinding) keymaps[KEYMAP_MAX]; @@ -229,7 +229,7 @@ static struct keymap keymap_table[] = { * Config file helpers. */ -static struct action * +static const struct action * get_action_from_keystroke(enum keymap_id keymap_id, const unsigned char *keystroke_str) { @@ -243,8 +243,8 @@ unsigned char * get_action_name_from_keystroke(enum keymap_id keymap_id, const unsigned char *keystroke_str) { - struct action *action = get_action_from_keystroke(keymap_id, - keystroke_str); + const struct action *action = get_action_from_keystroke(keymap_id, + keystroke_str); return action ? action->str : NULL; } @@ -252,7 +252,7 @@ get_action_name_from_keystroke(enum keymap_id keymap_id, action_id_T get_action_from_string(enum keymap_id keymap_id, unsigned char *str) { - struct action *action; + const struct action *action; assert(keymap_id >= 0 && keymap_id < KEYMAP_MAX); @@ -263,7 +263,7 @@ get_action_from_string(enum keymap_id keymap_id, unsigned char *str) return -1; } -struct action * +const struct action * get_action(enum keymap_id keymap_id, action_id_T action_id) { assert(keymap_id >= 0 && keymap_id < KEYMAP_MAX); @@ -277,7 +277,7 @@ get_action(enum keymap_id keymap_id, action_id_T action_id) unsigned char * get_action_name(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action ? action->str : NULL; } @@ -285,7 +285,7 @@ get_action_name(enum keymap_id keymap_id, action_id_T action_id) static unsigned char * get_action_desc(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action ? (action->desc ? action->desc : action->str) : NULL; @@ -523,23 +523,23 @@ add_actions_to_string(struct string *string, action_id_T action_ids[], #undef KEYMAP_ID #define KEYMAP_ID KEYMAP_MAIN -static struct action main_action_table[MAIN_ACTIONS + 1] = { +static const struct action main_action_table[MAIN_ACTIONS + 1] = { #include "config/actions-main.inc" }; #undef KEYMAP_ID #define KEYMAP_ID KEYMAP_EDIT -static struct action edit_action_table[EDIT_ACTIONS + 1] = { +static const struct action edit_action_table[EDIT_ACTIONS + 1] = { #include "config/actions-edit.inc" }; #undef KEYMAP_ID #define KEYMAP_ID KEYMAP_MENU -static struct action menu_action_table[MENU_ACTIONS + 1] = { +static const struct action menu_action_table[MENU_ACTIONS + 1] = { #include "config/actions-menu.inc" }; -static struct action_list action_table[KEYMAP_MAX] = { +static const struct action_list action_table[KEYMAP_MAX] = { { main_action_table, sizeof_array(main_action_table) }, { edit_action_table, sizeof_array(edit_action_table) }, { menu_action_table, sizeof_array(menu_action_table) }, @@ -844,11 +844,11 @@ add_default_keybindings(void) */ struct action_alias { - unsigned char *str; + const unsigned char *str; action_id_T action_id; }; -static struct action_alias main_action_aliases[] = { +static const struct action_alias main_action_aliases[] = { { "back", ACT_MAIN_HISTORY_MOVE_BACK }, { "down", ACT_MAIN_MOVE_LINK_NEXT }, { "download", ACT_MAIN_LINK_DOWNLOAD }, @@ -869,13 +869,13 @@ static struct action_alias main_action_aliases[] = { { NULL, 0 } }; -static struct action_alias edit_action_aliases[] = { +static const struct action_alias edit_action_aliases[] = { { "edit", ACT_EDIT_OPEN_EXTERNAL }, { NULL, 0 } }; -static struct action_alias *action_aliases[KEYMAP_MAX] = { +static const struct action_alias *action_aliases[KEYMAP_MAX] = { main_action_aliases, edit_action_aliases, NULL, @@ -887,7 +887,7 @@ get_aliased_action(enum keymap_id keymap_id, unsigned char *action_str) assert(keymap_id >= 0 && keymap_id < KEYMAP_MAX); if (action_aliases[keymap_id]) { - struct action_alias *alias; + const struct action_alias *alias; for (alias = action_aliases[keymap_id]; alias->str; alias++) if (!strcmp(alias->str, action_str)) diff --git a/src/config/kbdbind.h b/src/config/kbdbind.h index c24df275..8facc190 100644 --- a/src/config/kbdbind.h +++ b/src/config/kbdbind.h @@ -30,7 +30,7 @@ struct action { }; struct action_list { - struct action *actions; + const struct action *actions; int num_actions; }; struct keymap { @@ -104,7 +104,7 @@ struct keybinding *add_keybinding(enum keymap_id keymap_id, action_id_T action_i int keybinding_exists(enum keymap_id keymap_id, struct term_event_keyboard *kbd, action_id_T *action_id); void free_keybinding(struct keybinding *); -struct action *get_action(enum keymap_id keymap_id, action_id_T action_id); +const struct action *get_action(enum keymap_id keymap_id, action_id_T action_id); unsigned char *get_action_name(enum keymap_id keymap_id, action_id_T action_id); action_id_T get_action_from_string(enum keymap_id keymap_id, unsigned char *str); unsigned char *get_action_name_from_keystroke(enum keymap_id keymap_id, @@ -113,7 +113,7 @@ unsigned char *get_action_name_from_keystroke(enum keymap_id keymap_id, static inline unsigned int action_is_anonymous_safe(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && !(action->flags & ACTION_RESTRICT_ANONYMOUS); } @@ -121,7 +121,7 @@ action_is_anonymous_safe(enum keymap_id keymap_id, action_id_T action_id) static inline unsigned int action_requires_view_state(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && (action->flags & ACTION_REQUIRE_VIEW_STATE); } @@ -129,7 +129,7 @@ action_requires_view_state(enum keymap_id keymap_id, action_id_T action_id) static inline unsigned int action_requires_location(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && (action->flags & ACTION_REQUIRE_LOCATION); } @@ -137,7 +137,7 @@ action_requires_location(enum keymap_id keymap_id, action_id_T action_id) static inline unsigned int action_prefix_is_link_number(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && (action->flags & ACTION_JUMP_TO_LINK); } @@ -145,7 +145,7 @@ action_prefix_is_link_number(enum keymap_id keymap_id, action_id_T action_id) static inline unsigned int action_requires_link(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && (action->flags & ACTION_REQUIRE_LINK); } @@ -153,7 +153,7 @@ action_requires_link(enum keymap_id keymap_id, action_id_T action_id) static inline unsigned int action_requires_form(enum keymap_id keymap_id, action_id_T action_id) { - struct action *action = get_action(keymap_id, action_id); + const struct action *action = get_action(keymap_id, action_id); return action && (action->flags & ACTION_REQUIRE_FORM); } From e6344340ddf40c3cdec884b12d05dcdbde69d337 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sun, 19 Jul 2009 19:46:16 +0300 Subject: [PATCH 20/30] Doxyfile: Expand OBJECT_HEAD as defined To stop Doxygen from parsing its uses as member functions. --- doc/Doxyfile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index eaef8815..40b4d018 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -231,7 +231,8 @@ PREDEFINED = "LIST_OF(element_T)=element_T list" \ HAVE_VARIADIC_MACROS EXPAND_AS_DEFINED = LIST_HEAD \ INIT_LIST_OF \ - ACTION_ + ACTION_ \ + OBJECT_HEAD SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- From f815d278358e2e6df00096fac8f92ea627977949 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 21 Jul 2009 00:50:44 +0300 Subject: [PATCH 21/30] lookup_unique_name: Handle NULL from expand_tilde expand_tilde() returns NULL if out of memory. Make lookup_unique_name() handle that. --- src/session/download.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/session/download.c b/src/session/download.c index 8620f68a..1884770f 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -671,6 +671,10 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int overwrite; ofile = expand_tilde(ofile); + if (!ofile) { + callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); + return; + } /* Minor code duplication to prevent useless call to get_opt_int() * if possible. --Zas */ From 71dfd47dcba4ed1f364c67a3d7ce062a28abd042 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 21 Jul 2009 00:57:17 +0300 Subject: [PATCH 22/30] lookup_unique_name: Merge error handling --- src/session/download.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 1884770f..89f522c9 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -667,14 +667,11 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, { /* [gettext_accelerator_context(.lookup_unique_name)] */ struct lun_hop *lun_hop; - unsigned char *file; + unsigned char *file = NULL; int overwrite; ofile = expand_tilde(ofile); - if (!ofile) { - callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); - return; - } + if (!ofile) goto error; /* Minor code duplication to prevent useless call to get_opt_int() * if possible. --Zas */ @@ -699,9 +696,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, N_("Download error"), ALIGN_CENTER, msg_text(term, N_("'%s' is a directory."), ofile)); - mem_free(ofile); - callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); - return; + goto error; } /* Check if the file already exists (file != ofile). */ @@ -718,12 +713,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, * exists) */ lun_hop = mem_calloc(1, sizeof(*lun_hop)); - if (!lun_hop) { - if (file != ofile) mem_free(file); - mem_free(ofile); - callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); - return; - } + if (!lun_hop) goto error; lun_hop->term = term; lun_hop->ofile = ofile; lun_hop->file = (file != ofile) ? file : stracpy(ofile); @@ -747,6 +737,12 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, : NULL), lun_resume, 0), MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC)); + return; + +error: + if (file != ofile) mem_free_if(file); + mem_free_if(ofile); + callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); } From b80c0e8a0d9f7aca210e1e0c164f3193a99fcde9 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 21 Jul 2009 01:09:37 +0300 Subject: [PATCH 23/30] lookup_unique_name: Remove always true condition Remove the stracpy(ofile) call that could never be executed. This removes the need to handle errors from that call, and makes it clear that lun_hop->file need not be separately freed if an error occurs in lookup_unique_name(). --- src/session/download.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session/download.c b/src/session/download.c index 89f522c9..30908edc 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -716,7 +716,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, if (!lun_hop) goto error; lun_hop->term = term; lun_hop->ofile = ofile; - lun_hop->file = (file != ofile) ? file : stracpy(ofile); + lun_hop->file = file; /* file != ofile verified above */ lun_hop->callback = callback; lun_hop->data = data; lun_hop->resume = resume; From 4067e5472795c1dd9152636116271b96819f5941 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 21 Jul 2009 01:06:36 +0300 Subject: [PATCH 24/30] lookup_unique_name: Handle NULL from msg_box If msg_box() runs out of memory, it returns NULL. In this case, the done_handler_T callbacks of the buttons will not be called. So lookup_unique_name() must instead free the struct lun_hop on its own. --- src/session/download.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 30908edc..0474ece4 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -666,8 +666,9 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, lun_callback_T *callback, void *data) { /* [gettext_accelerator_context(.lookup_unique_name)] */ - struct lun_hop *lun_hop; + struct lun_hop *lun_hop = NULL; unsigned char *file = NULL; + struct dialog_data *dialog_data; int overwrite; ofile = expand_tilde(ofile); @@ -721,7 +722,8 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, lun_hop->data = data; lun_hop->resume = resume; - msg_box(term, NULL, MSGBOX_FREE_TEXT, + dialog_data = msg_box( + term, NULL, MSGBOX_FREE_TEXT, N_("File exists"), ALIGN_CENTER, msg_text(term, N_("This file already exists:\n" "%s\n\n" @@ -737,9 +739,11 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, : NULL), lun_resume, 0), MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC)); + if (!dialog_data) goto error; return; error: + mem_free_if(lun_hop); if (file != ofile) mem_free_if(file); mem_free_if(ofile); callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); From 53c19e5b66a92a8278fd4f6752ceb879b616296b Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Tue, 21 Jul 2009 03:26:59 +0300 Subject: [PATCH 25/30] Bug 770: Comment updates Since commit b7d03f9b044e69e712b8c66ff9a4974f6ab564a5 on 2009-07-19, lun_resume() no longer assumes that data points to struct cdf_hop. --- src/session/download.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 0474ece4..3ffb7023 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -493,10 +493,7 @@ struct lun_hop { /** This function will be called when the user answers. */ lun_callback_T *callback; - /** A pointer to be passed to #callback. If #resume includes - * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct - * cdf_hop because the pointer can be read by lun_resume(), - * which assumes so. */ + /** A pointer to be passed to #callback. */ void *data; /** Whether the download can be resumed. @@ -655,9 +652,7 @@ lun_resume(void *lun_hop_) * need not or cannot be asked. * * @param data - * A pointer to be passed to @a callback. If @a resume includes - * ::DOWNLOAD_RESUME_ALLOWED, this must point to struct cdf_hop - * because the pointer can be read by lun_resume(), which assumes so. + * A pointer to be passed to @a callback. * * @relates lun_hop */ static void From ce89947fcf733096b29c17553a22380e15fb22f1 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Thu, 23 Jul 2009 21:25:48 +0300 Subject: [PATCH 26/30] download: Use add_dlg_checkbox --- src/session/download.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session/download.c b/src/session/download.c index 3ffb7023..9ea27dc4 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -1495,7 +1495,7 @@ do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_hand 0, 0, NULL, MAX_STR_LEN, field, NULL); type_query->external_handler = field; - add_dlg_radio(dlg, _("Block the terminal", term), 0, 0, &type_query->block); + add_dlg_checkbox(dlg, _("Block the terminal", term), &type_query->block); selected_widget = 3; } else if (handler) { From 1cca904ce6af5dd8133e26e03ec8e3e63ebd8b68 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Thu, 23 Jul 2009 22:57:11 +0300 Subject: [PATCH 27/30] download: Document the rest of struct type_query --- src/session/download.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/session/download.h b/src/session/download.h index 0802fac1..aca5c5e4 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -47,12 +47,41 @@ struct download { * destroy_session() calls done_type_query() to destroy them too. */ struct type_query { LIST_HEAD(struct type_query); + + /** After ELinks has downloaded enough of the resource to see + * that a type query is needed, it moves the download here and + * continues it while the user decides what to do. */ struct download download; + + /** Cache entry loaded from #uri. Apparently used only for + * displaying the header. */ struct cache_entry *cached; + + /** The session in which the user navigated to #uri. The + * type_query is in the session.type_queries list of this + * session. */ struct session *ses; + + /** The URI of the resource about which ELinks is asking. + * This reference must be released with done_uri(). */ struct uri *uri; + + /** The name of the frame in which the user navigated to #uri. + * If the user chooses to display the resource, it goes into + * this frame. This string must be freed with mem_free(). */ unsigned char *target_frame; + + /** Command line for an external handler, to be run when the + * download finishes. When ELinks displays the type query, + * it copies this from mime_handler.program of the default + * handler of the type. The user can then edit the string. + * This string must be freed with mem_free(). */ unsigned char *external_handler; + + /** Whether the external handler is going to use the terminal. + * When ELinks displays the type query, it copies this from + * mime_handler.block of the default handler of the type. + * The user can then change the flag with a checkbox. */ int block; /** Whether the resource was generated by ELinks running From ab72415130292f72ee6708852a10072c1835da57 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Thu, 23 Jul 2009 22:57:41 +0300 Subject: [PATCH 28/30] download: Make BitTorrent's tp_show_header static There are two identical tp_show_header() functions: one in src/session/download.c and one in src/protocol/bittorrent/dialogs.c. Neither is declared in any header, but the latter was not static. --- src/protocol/bittorrent/dialogs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/bittorrent/dialogs.c b/src/protocol/bittorrent/dialogs.c index ba99de54..9d5cc2e8 100644 --- a/src/protocol/bittorrent/dialogs.c +++ b/src/protocol/bittorrent/dialogs.c @@ -678,7 +678,7 @@ bittorrent_download(struct dialog_data *dlg_data, struct widget_data *widget_dat /* Show the protocol header. */ /* XXX: Code duplication with session/download.h */ -widget_handler_status_T +static widget_handler_status_T tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data) { struct type_query *type_query = widget_data->widget->data; From a2c8dc8c61f74c57c1e43af770dd9cda17937da5 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 24 Jul 2009 16:57:33 +0300 Subject: [PATCH 29/30] download: Rename download_resume to download_flags Bring the code closer to ELinks 0.13.GIT commit 71ccbe0f8d42912311e46a04a3e234b8bc9a08cf made on 2007-11-07. Don't define a separate download_flags_T typedef though, because Doxygen generates nicer links if the enum is used directly. --- src/session/download.c | 66 +++++++++++++++++++++--------------------- src/session/download.h | 38 ++++++++++++------------ src/viewer/text/view.c | 2 +- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 9ea27dc4..96bae387 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -463,12 +463,12 @@ download_data(struct download *download, struct file_download *file_download) * A pointer to any data that the callback cares about. * Comes directly from the @a data argument of lookup_unique_name(). * - * @param resume + * @param flags * Whether the user chose to resume downloading an existing file. * * @relates lun_hop */ typedef void lun_callback_T(struct terminal *term, unsigned char *file, - void *data, enum download_resume resume); + void *data, enum download_flags flags); /** The user is being asked what to do when the local file for * the download already exists. This structure is allocated by @@ -500,7 +500,7 @@ struct lun_hop { * The ::DOWNLOAD_RESUME_SELECTED bit should be clear * because otherwise there would have been no reason to * ask the user and initialize this structure. */ - enum download_resume resume; + enum download_flags flags; }; /** Data saved by common_download() for the common_download_do() @@ -569,7 +569,7 @@ lun_alternate(void *lun_hop_) struct lun_hop *lun_hop = lun_hop_; lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data, - lun_hop->resume); + lun_hop->flags); mem_free_if(lun_hop->ofile); mem_free(lun_hop); } @@ -586,7 +586,7 @@ lun_cancel(void *lun_hop_) struct lun_hop *lun_hop = lun_hop_; lun_hop->callback(lun_hop->term, NULL, lun_hop->data, - lun_hop->resume); + lun_hop->flags); mem_free_if(lun_hop->ofile); mem_free_if(lun_hop->file); mem_free(lun_hop); @@ -605,7 +605,7 @@ lun_overwrite(void *lun_hop_) struct lun_hop *lun_hop = lun_hop_; lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, - lun_hop->resume); + lun_hop->flags); mem_free_if(lun_hop->file); mem_free(lun_hop); } @@ -623,7 +623,7 @@ lun_resume(void *lun_hop_) struct lun_hop *lun_hop = lun_hop_; lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, - lun_hop->resume | DOWNLOAD_RESUME_SELECTED); + lun_hop->flags | DOWNLOAD_RESUME_SELECTED); mem_free_if(lun_hop->file); mem_free(lun_hop); } @@ -642,7 +642,7 @@ lun_resume(void *lun_hop_) * downloaded. "~" here refers to the home directory. * lookup_unique_name() treats this original string as read-only. * - * @param[in] resume + * @param[in] flags * Indicates if the user already chose to resume downloading, * before ELinks even asked for the file name. * See ::ACT_MAIN_LINK_DOWNLOAD_RESUME. @@ -657,7 +657,7 @@ lun_resume(void *lun_hop_) * @relates lun_hop */ static void lookup_unique_name(struct terminal *term, unsigned char *ofile, - enum download_resume resume, + enum download_flags flags, lun_callback_T *callback, void *data) { /* [gettext_accelerator_context(.lookup_unique_name)] */ @@ -671,8 +671,8 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, /* Minor code duplication to prevent useless call to get_opt_int() * if possible. --Zas */ - if (resume & DOWNLOAD_RESUME_SELECTED) { - callback(term, ofile, data, resume); + if (flags & DOWNLOAD_RESUME_SELECTED) { + callback(term, ofile, data, flags); return; } @@ -681,7 +681,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, overwrite = get_opt_int("document.download.overwrite"); if (!overwrite) { /* Nothing special to do... */ - callback(term, ofile, data, resume); + callback(term, ofile, data, flags); return; } @@ -701,7 +701,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, if (!file || overwrite == 1 || file == ofile) { /* Still nothing special to do... */ if (file != ofile) mem_free(ofile); - callback(term, file, data, resume & ~DOWNLOAD_RESUME_SELECTED); + callback(term, file, data, flags & ~DOWNLOAD_RESUME_SELECTED); return; } @@ -715,7 +715,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, lun_hop->file = file; /* file != ofile verified above */ lun_hop->callback = callback; lun_hop->data = data; - lun_hop->resume = resume; + lun_hop->flags = flags; dialog_data = msg_box( term, NULL, MSGBOX_FREE_TEXT, @@ -729,7 +729,7 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, lun_hop, 4, MSG_BOX_BUTTON(N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER), MSG_BOX_BUTTON(N_("~Overwrite the original file"), lun_overwrite, 0), - MSG_BOX_BUTTON((resume & DOWNLOAD_RESUME_ALLOWED + MSG_BOX_BUTTON((flags & DOWNLOAD_RESUME_ALLOWED ? N_("~Resume download of the original file") : NULL), lun_resume, 0), @@ -741,7 +741,7 @@ error: mem_free_if(lun_hop); if (file != ofile) mem_free_if(file); mem_free_if(ofile); - callback(term, NULL, data, resume & ~DOWNLOAD_RESUME_SELECTED); + callback(term, NULL, data, flags & ~DOWNLOAD_RESUME_SELECTED); } @@ -756,7 +756,7 @@ error: * @relates cdf_hop */ static void create_download_file_do(struct terminal *term, unsigned char *file, - void *data, enum download_resume resume) + void *data, enum download_flags flags) { struct cdf_hop *cdf_hop = data; unsigned char *wd; @@ -780,8 +780,8 @@ create_download_file_do(struct terminal *term, unsigned char *file, * thus ignoring seek()s and that can hide mysterious bugs. IMHO. * --pasky */ h = open(file, O_CREAT | O_WRONLY - | (resume & DOWNLOAD_RESUME_SELECTED ? 0 : O_TRUNC) - | (sf && !(resume & DOWNLOAD_RESUME_SELECTED) ? O_EXCL : 0), + | (flags & DOWNLOAD_RESUME_SELECTED ? 0 : O_TRUNC) + | (sf && !(flags & DOWNLOAD_RESUME_SELECTED) ? O_EXCL : 0), sf ? 0600 : 0666); saved_errno = errno; /* Saved in case of ... --Zas */ @@ -822,7 +822,7 @@ create_download_file_do(struct terminal *term, unsigned char *file, mem_free(file); finish: - cdf_hop->callback(term, h, cdf_hop->data, resume); + cdf_hop->callback(term, h, cdf_hop->data, flags); mem_free(cdf_hop); } @@ -848,7 +848,7 @@ finish: * the umask is looser), and create the file with @c O_EXCL unless * resuming. * - * @param resume + * @param flags * Whether the download can be resumed, and whether the user already * asked for it to be resumed. * @@ -863,14 +863,14 @@ finish: void create_download_file(struct terminal *term, unsigned char *fi, unsigned char **real_file, int safe, - enum download_resume resume, + enum download_flags flags, cdf_callback_T *callback, void *data) { struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop)); unsigned char *wd; if (!cdf_hop) { - callback(term, -1, data, resume & ~DOWNLOAD_RESUME_SELECTED); + callback(term, -1, data, flags & ~DOWNLOAD_RESUME_SELECTED); return; } @@ -884,7 +884,7 @@ create_download_file(struct terminal *term, unsigned char *fi, set_cwd(term->cwd); /* Also the tilde will be expanded here. */ - lookup_unique_name(term, fi, resume, create_download_file_do, cdf_hop); + lookup_unique_name(term, fi, flags, create_download_file_do, cdf_hop); if (wd) { set_cwd(wd); @@ -983,7 +983,7 @@ subst_file(unsigned char *prog, unsigned char *file) * @relates cmdw_hop */ static void common_download_do(struct terminal *term, int fd, void *data, - enum download_resume resume) + enum download_flags flags) { struct file_download *file_download; struct cmdw_hop *cmdw_hop = data; @@ -1003,7 +1003,7 @@ common_download_do(struct terminal *term, int fd, void *data, file = NULL; fd = -1; - if (resume & DOWNLOAD_RESUME_SELECTED) + if (flags & DOWNLOAD_RESUME_SELECTED) file_download->seek = buf.st_size; display_download(ses->tab->term, file_download, ses); @@ -1026,7 +1026,7 @@ finish: * @relates cmdw_hop */ static void common_download(struct session *ses, unsigned char *file, - enum download_resume resume) + enum download_flags flags) { struct cmdw_hop *cmdw_hop; @@ -1041,7 +1041,7 @@ common_download(struct session *ses, unsigned char *file, kill_downloads_to_file(file); create_download_file(ses->tab->term, file, &cmdw_hop->real_file, 0, - resume, common_download_do, cmdw_hop); + flags, common_download_do, cmdw_hop); } /** Begin downloading from session.download_uri to the @a file @@ -1085,7 +1085,7 @@ resume_download(void *ses, unsigned char *file) static void transform_codw_to_cmdw(struct terminal *term, int fd, struct codw_hop *codw_hop, - enum download_resume resume) + enum download_flags flags) { struct type_query *type_query = codw_hop->type_query; struct cmdw_hop *cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop)); @@ -1100,7 +1100,7 @@ transform_codw_to_cmdw(struct terminal *term, int fd, cmdw_hop->real_file = codw_hop->real_file; codw_hop->real_file = NULL; - common_download_do(term, fd, cmdw_hop, resume); + common_download_do(term, fd, cmdw_hop, flags); } /*! continue_download() passes this function as a ::cdf_callback_T to @@ -1109,7 +1109,7 @@ transform_codw_to_cmdw(struct terminal *term, int fd, * @relates codw_hop */ static void continue_download_do(struct terminal *term, int fd, void *data, - enum download_resume resume) + enum download_flags flags) { struct codw_hop *codw_hop = data; struct file_download *file_download = NULL; @@ -1123,8 +1123,8 @@ continue_download_do(struct terminal *term, int fd, void *data, type_query = codw_hop->type_query; if (!codw_hop->real_file) goto cancel; - if (resume & DOWNLOAD_RESUME_SELECTED) { - transform_codw_to_cmdw(term, fd, codw_hop, resume); + if (flags & DOWNLOAD_RESUME_SELECTED) { + transform_codw_to_cmdw(term, fd, codw_hop, flags); fd = -1; /* ownership transfer */ goto cancel; } diff --git a/src/session/download.h b/src/session/download.h index aca5c5e4..367355d8 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -20,6 +20,21 @@ struct download; typedef void (download_callback_T)(struct download *, void *); +/** Whether to resume downloading to a file. This is a bit mask. + * Unrecognized bits should be preserved and ignored. */ +enum download_flags { + /** Downloading cannot be resumed; do not offer such an option + * to the user. All bits clear. */ + DOWNLOAD_RESUME_DISABLED = 0, + + /** Downloading can be resumed. This is the usual value. */ + DOWNLOAD_RESUME_ALLOWED = 1, + + /** The user wants to resume downloading. This must not occur + * without DOWNLOAD_RESUME_ALLOWED. */ + DOWNLOAD_RESUME_SELECTED = 2 +}; + struct download { /* XXX: order matters there, there's some hard initialization in * src/session/session.c and src/viewer/text/view.c */ @@ -143,21 +158,6 @@ int download_is_progressing(struct download *download); int are_there_downloads(void); -/** Whether to resume downloading to a file. This is a bit mask. - * Unrecognized bits should be preserved and ignored. */ -enum download_resume { - /** Downloading cannot be resumed; do not offer such an option - * to the user. All bits clear. */ - DOWNLOAD_RESUME_DISABLED = 0, - - /** Downloading can be resumed. This is the usual value. */ - DOWNLOAD_RESUME_ALLOWED = 1, - - /** The user wants to resume downloading. This must not occur - * without DOWNLOAD_RESUME_ALLOWED. */ - DOWNLOAD_RESUME_SELECTED = 2 -}; - /** Type of the callback function that will be called when the file * has been opened, or when it is known that the file will not be * opened. @@ -176,19 +176,19 @@ enum download_resume { * A pointer to any data that the callback cares about. * Comes directly from the @a data argument of create_download_file(). * - * @param resume - * The same as the @a resume argument of create_download_file(), + * @param flags + * The same as the @a flags argument of create_download_file(), * except the ::DOWNLOAD_RESUME_SELECTED bit will be changed to match * what the user chose. * * @relates cdf_hop */ typedef void cdf_callback_T(struct terminal *term, int fd, - void *data, enum download_resume resume); + void *data, enum download_flags flags); void start_download(void *, unsigned char *); void resume_download(void *, unsigned char *); void create_download_file(struct terminal *, unsigned char *, unsigned char **, - int, enum download_resume, cdf_callback_T *, void *); + int, enum download_flags, cdf_callback_T *, void *); void abort_all_downloads(void); void destroy_downloads(struct session *); diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c index f39693fe..9238f04a 100644 --- a/src/viewer/text/view.c +++ b/src/viewer/text/view.c @@ -1619,7 +1619,7 @@ save_as(struct session *ses, struct document_view *doc_view, int magic) * create_download_finish(). */ static void save_formatted_finish(struct terminal *term, int h, - void *data, enum download_resume resume) + void *data, enum download_flags flags) { struct document *document = data; From db128fecd9e512bf61481511a0119f6f00bb2b3f Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Fri, 24 Jul 2009 18:09:59 +0300 Subject: [PATCH 30/30] download: Add DOWNLOAD_EXTERNAL flag Like in ELinks 0.13.GIT commit b3cfede1c128fdbebbb96926e5b86f02d83494bc made on 2007-11-07, only with more comments and a bit different names. --- src/session/download.c | 58 ++++++++++++++++++++++-------------------- src/session/download.h | 11 +++++--- src/viewer/text/view.c | 2 +- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/session/download.c b/src/session/download.c index 96bae387..389a3616 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -464,7 +464,9 @@ download_data(struct download *download, struct file_download *file_download) * Comes directly from the @a data argument of lookup_unique_name(). * * @param flags - * Whether the user chose to resume downloading an existing file. + * The same as the @a flags argument of create_download_file(), + * except the ::DOWNLOAD_RESUME_SELECTED bit will be changed to match + * what the user chose. * * @relates lun_hop */ typedef void lun_callback_T(struct terminal *term, unsigned char *file, @@ -496,10 +498,13 @@ struct lun_hop { /** A pointer to be passed to #callback. */ void *data; - /** Whether the download can be resumed. - * The ::DOWNLOAD_RESUME_SELECTED bit should be clear - * because otherwise there would have been no reason to - * ask the user and initialize this structure. */ + /** Saved flags to be passed to #callback. + * If the user chooses to resume, then lun_resume() sets + * ::DOWNLOAD_RESUME_SELECTED when it calls #callback. + * + * @invariant The ::DOWNLOAD_RESUME_SELECTED bit should be + * clear here because otherwise there would have been no + * reason to ask the user and initialize this structure. */ enum download_flags flags; }; @@ -543,11 +548,6 @@ struct cdf_hop { * #callback does not care about the name. */ unsigned char **real_file; - /** If nonzero, give only the user herself access to the file - * (even if the umask is looser), and create the file with - * @c O_EXCL unless resuming. */ - int safe; - /** This function will be called when the file has been opened, * or when it is known that the file will not be opened. */ cdf_callback_T *callback; @@ -643,9 +643,13 @@ lun_resume(void *lun_hop_) * lookup_unique_name() treats this original string as read-only. * * @param[in] flags - * Indicates if the user already chose to resume downloading, - * before ELinks even asked for the file name. - * See ::ACT_MAIN_LINK_DOWNLOAD_RESUME. + * Flags controlling how to download the file. + * ::DOWNLOAD_RESUME_ALLOWED adds a "Resume" button to the dialog. + * ::DOWNLOAD_RESUME_SELECTED means the user already chose to resume + * downloading (with ::ACT_MAIN_LINK_DOWNLOAD_RESUME), before ELinks + * even asked for the file name; thus don't ask whether to overwrite. + * Other flags, such as ::DOWNLOAD_EXTERNAL, have no effect at this + * level but they get passed to @a callback. * * @param callback * Will be called when the user answers, or right away if the question @@ -765,7 +769,7 @@ create_download_file_do(struct terminal *term, unsigned char *file, #ifdef NO_FILE_SECURITY int sf = 0; #else - int sf = cdf_hop->safe; + int sf = !!(flags & DOWNLOAD_EXTERNAL); #endif if (!file) goto finish; @@ -802,7 +806,7 @@ create_download_file_do(struct terminal *term, unsigned char *file, } else { set_bin(h); - if (!cdf_hop->safe) { + if (!(flags & DOWNLOAD_EXTERNAL)) { unsigned char *download_dir = get_opt_str("document.download.directory"); int i; @@ -843,14 +847,14 @@ finish: * file that was eventually opened. @a callback must then arrange for * this string to be freed with mem_free(). * - * @param safe - * If nonzero, give only the user herself access to the file (even if - * the umask is looser), and create the file with @c O_EXCL unless - * resuming. - * * @param flags - * Whether the download can be resumed, and whether the user already - * asked for it to be resumed. + * Flags controlling how to download the file. + * ::DOWNLOAD_RESUME_ALLOWED adds a "Resume" button to the dialog. + * ::DOWNLOAD_RESUME_SELECTED skips the dialog entirely. + * ::DOWNLOAD_EXTERNAL causes the file to be created with settings + * suitable for a temporary file: give only the user herself access to + * the file (even if the umask is looser), and create the file with + * @c O_EXCL unless resuming. * * @param callback * This function will be called when the file has been opened, @@ -862,7 +866,7 @@ finish: * @relates cdf_hop */ void create_download_file(struct terminal *term, unsigned char *fi, - unsigned char **real_file, int safe, + unsigned char **real_file, enum download_flags flags, cdf_callback_T *callback, void *data) { @@ -875,7 +879,6 @@ create_download_file(struct terminal *term, unsigned char *fi, } cdf_hop->real_file = real_file; - cdf_hop->safe = safe; cdf_hop->callback = callback; cdf_hop->data = data; @@ -1040,7 +1043,7 @@ common_download(struct session *ses, unsigned char *file, kill_downloads_to_file(file); - create_download_file(ses->tab->term, file, &cmdw_hop->real_file, 0, + create_download_file(ses->tab->term, file, &cmdw_hop->real_file, flags, common_download_do, cmdw_hop); } @@ -1202,8 +1205,9 @@ continue_download(void *data, unsigned char *file) create_download_file(type_query->ses->tab->term, file, &codw_hop->real_file, - !!type_query->external_handler, - DOWNLOAD_RESUME_ALLOWED, + type_query->external_handler + ? DOWNLOAD_RESUME_ALLOWED | DOWNLOAD_EXTERNAL + : DOWNLOAD_RESUME_ALLOWED, continue_download_do, codw_hop); } diff --git a/src/session/download.h b/src/session/download.h index 367355d8..39716054 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -20,7 +20,7 @@ struct download; typedef void (download_callback_T)(struct download *, void *); -/** Whether to resume downloading to a file. This is a bit mask. +/** Flags controlling how to download a file. This is a bit mask. * Unrecognized bits should be preserved and ignored. */ enum download_flags { /** Downloading cannot be resumed; do not offer such an option @@ -31,8 +31,11 @@ enum download_flags { DOWNLOAD_RESUME_ALLOWED = 1, /** The user wants to resume downloading. This must not occur - * without DOWNLOAD_RESUME_ALLOWED. */ - DOWNLOAD_RESUME_SELECTED = 2 + * without #DOWNLOAD_RESUME_ALLOWED. */ + DOWNLOAD_RESUME_SELECTED = 2, + + /** The file will be opened in an external handler. */ + DOWNLOAD_EXTERNAL = 4 }; struct download { @@ -188,7 +191,7 @@ typedef void cdf_callback_T(struct terminal *term, int fd, void start_download(void *, unsigned char *); void resume_download(void *, unsigned char *); void create_download_file(struct terminal *, unsigned char *, unsigned char **, - int, enum download_flags, cdf_callback_T *, void *); + enum download_flags, cdf_callback_T *, void *); void abort_all_downloads(void); void destroy_downloads(struct session *); diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c index 9238f04a..13a61f50 100644 --- a/src/viewer/text/view.c +++ b/src/viewer/text/view.c @@ -1646,7 +1646,7 @@ save_formatted(void *data, unsigned char *file) assert(doc_view && doc_view->document); if_assert_failed return; - create_download_file(ses->tab->term, file, NULL, 0, + create_download_file(ses->tab->term, file, NULL, DOWNLOAD_RESUME_DISABLED, save_formatted_finish, doc_view->document); }