From 734028277c0b20b7d779401dad921884e9a6e83a Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 26 Jul 2021 21:28:19 +0200 Subject: [PATCH] [iframe] Small progress. --- src/document/html/iframes.c | 174 +++++++++++++++++++++++++++++++- src/document/html/iframes.h | 4 +- src/document/html/parser/link.c | 13 ++- src/document/html/renderer.c | 4 +- src/document/renderer.c | 4 + src/network/state.h | 1 + src/session/location.c | 3 +- src/session/session.c | 12 ++- src/session/session.h | 1 + src/session/task.c | 31 +++++- src/viewer/text/draw.c | 11 +- test/iframe.html | 9 ++ 12 files changed, 253 insertions(+), 14 deletions(-) create mode 100644 test/iframe.html diff --git a/src/document/html/iframes.c b/src/document/html/iframes.c index c61540c8..e8804d0c 100644 --- a/src/document/html/iframes.c +++ b/src/document/html/iframes.c @@ -18,6 +18,7 @@ #include "document/renderer.h" #include "document/view.h" #include "protocol/uri.h" +#include "session/location.h" #include "session/session.h" #include "terminal/draw.h" #include "util/color.h" @@ -25,7 +26,7 @@ #include "util/time.h" void add_iframeset_entry(struct iframeset_desc **parent, - char *url, int y, int height) + char *url, char *name, int y, int width, int height) { struct iframeset_desc *iframeset_desc; struct iframe_desc *iframe_desc; @@ -35,7 +36,7 @@ void add_iframeset_entry(struct iframeset_desc **parent, if_assert_failed return; if (!*parent) { - *parent = mem_calloc(1, sizeof(iframeset_desc)); + *parent = mem_calloc(1, sizeof(struct iframeset_desc)); } else { *parent = mem_realloc(*parent, sizeof(struct iframeset_desc) + ((*parent)->n + 1) * sizeof(struct iframe_desc)); } @@ -45,11 +46,178 @@ void add_iframeset_entry(struct iframeset_desc **parent, offset = iframeset_desc->n; iframe_desc = &iframeset_desc->iframe_desc[offset]; - iframe_desc->name = stracpy(""); + iframe_desc->name = stracpy(name); iframe_desc->uri = get_uri(url, 0); + iframe_desc->width = width; iframe_desc->height = height; if (!iframe_desc->uri) iframe_desc->uri = get_uri("about:blank", 0); iframeset_desc->n++; } + +static void +add_iframe_to_list(struct session *ses, struct document_view *doc_view) +{ + struct document_view *ses_doc_view; + + assert(ses && doc_view); + if_assert_failed return; + + foreach (ses_doc_view, ses->scrn_iframes) { + int sx = ses_doc_view->box.x; + int sy = ses_doc_view->box.y; + int x = doc_view->box.x; + int y = doc_view->box.y; + + if (sy > y || (sy == y && sx > x)) { + add_at_pos(ses_doc_view->prev, doc_view); + return; + } + } + + add_to_list_end(ses->scrn_iframes, doc_view); +} + +static struct document_view * +find_ifd(struct session *ses, char *name, + int depth, int x, int y) +{ + struct document_view *doc_view; + + assert(ses && name); + if_assert_failed return NULL; + + foreachback (doc_view, ses->scrn_iframes) { + if (doc_view->used) continue; + if (c_strcasecmp(doc_view->name, name)) continue; + + doc_view->used = 1; + doc_view->depth = 0;//depth; + return doc_view; + } + + doc_view = mem_calloc(1, sizeof(*doc_view)); + if (!doc_view) return NULL; + + doc_view->used = 1; + doc_view->name = stracpy(name); + if (!doc_view->name) { + mem_free(doc_view); + return NULL; + } + doc_view->depth = 0;//depth; + doc_view->session = ses; + doc_view->search_word = &ses->search_word; + set_box(&doc_view->box, x, y, 0, 0); + + add_iframe_to_list(ses, doc_view); + + return doc_view; +} + + +static struct document_view * +format_iframe(struct session *ses, struct iframe_desc *iframe_desc, + struct document_options *o, int j) +{ + struct view_state *vs; + struct document_view *doc_view; + struct frame *iframe = NULL; + struct cache_entry *cached; + int plain; + int i; + + assert(ses && iframe_desc && o); + if_assert_failed return NULL; + + struct location *loc = cur_loc(ses); + + if (!loc) { + return NULL; + } + + i = 0; + foreach (iframe, loc->iframes) { + if (i == j) break; + i++; + } + + if (!iframe) { + return NULL; + } + + vs = &iframe->vs; + cached = find_in_cache(vs->uri); + if (!cached) { + return NULL; + } + + plain = o->plain; + if (vs->plain != -1) o->plain = vs->plain; + + if (!cached->redirect || iframe->redirect_cnt >= MAX_REDIRECTS) { + goto redir; + } + + iframe->redirect_cnt++; + done_uri(vs->uri); + vs->uri = get_uri_reference(cached->redirect); +#ifdef CONFIG_ECMASCRIPT + vs->ecmascript_fragile = 1; +#endif + o->plain = plain; +redir: + doc_view = find_ifd(ses, iframe_desc->name, j, o->box.x, o->box.y); + if (doc_view) { + render_document(vs, doc_view, o); + assert(doc_view->document); + //doc_view->document->iframe = frame_desc; + } + o->plain = plain; + + return doc_view; +} + + +void +format_iframes(struct session *ses, struct iframeset_desc *ifsd, + struct document_options *op, int depth) +{ + struct document_options o; + int j; + + assert(ses && ifsd && op); + if_assert_failed return; + + if (depth > HTML_MAX_FRAME_DEPTH) { + return; + } + + copy_struct(&o, op); + + o.margin = !!o.margin; + + for (j = 0; j < ifsd->n; j++) { + struct iframe_desc *iframe_desc = &ifsd->iframe_desc[j]; + struct document_view *doc_view; + + o.box.x = op->box.x; + + o.box.width = iframe_desc->width; + o.box.height = iframe_desc->height; + o.framename = iframe_desc->name; + + doc_view = format_iframe(ses, iframe_desc, &o, j); + o.box.x += o.box.width + 1; + o.box.y += o.box.height + 1; +#ifdef CONFIG_DEBUG + /* This makes this ugly loop actually at least remotely + * debuggable by gdb, otherwise the compiler happily */ + do_not_optimize_here(&j); + do_not_optimize_here(&ifsd); + do_not_optimize_here(&iframe_desc); + do_not_optimize_here(doc_view); +#endif + } +} diff --git a/src/document/html/iframes.h b/src/document/html/iframes.h index 34e3a8bb..c4f41713 100644 --- a/src/document/html/iframes.h +++ b/src/document/html/iframes.h @@ -6,6 +6,7 @@ extern "C" { #endif +struct document_options; struct iframeset_desc; struct iframe_desc { @@ -22,7 +23,8 @@ struct iframeset_desc { struct iframe_desc iframe_desc[1]; /* must be last of struct. --Zas */ }; -void add_iframeset_entry(struct iframeset_desc **parent, char *url, int y, int height); +void add_iframeset_entry(struct iframeset_desc **parent, char *url, char *name, int y, int width, int height); +void format_iframes(struct session *ses, struct iframeset_desc *ifsd, struct document_options *op, int depth); #ifdef __cplusplus } diff --git a/src/document/html/parser/link.c b/src/document/html/parser/link.c index b46ec396..cd8ae4d4 100644 --- a/src/document/html/parser/link.c +++ b/src/document/html/parser/link.c @@ -468,8 +468,9 @@ html_iframe_do(char *a, char *object_src, struct html_context *html_context) { char *name, *url = NULL; - char *hstr; + char *hstr, *wstr; int height; + int width; url = null_or_stracpy(object_src); if (!url) url = get_url_val(a, "src", html_context->doc_cp); @@ -483,6 +484,7 @@ html_iframe_do(char *a, char *object_src, return; } hstr = get_attr_val(a, "height", html_context->doc_cp); + wstr = get_attr_val(a, "width", html_context->doc_cp); html_focusable(html_context, a); @@ -501,6 +503,13 @@ html_iframe_do(char *a, char *object_src, mem_free(hstr); } + if (!wstr) { + width = (300 + HTML_CHAR_WIDTH - 1) / HTML_CHAR_WIDTH; + } else { + width = (atoi(wstr) + HTML_CHAR_WIDTH - 1) / HTML_CHAR_WIDTH; + mem_free(wstr); + } + if (height > 0) { int y = html_context->part->cy; char *url2; @@ -509,7 +518,7 @@ html_iframe_do(char *a, char *object_src, url2 = join_urls(html_context->base_href, url); if (url2) { - html_context->special_f(html_context, SP_IFRAME, url2, y, height); + html_context->special_f(html_context, SP_IFRAME, url2, name, y, width, height); mem_free(url2); } } diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 5df8f018..996958e7 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -2361,10 +2361,12 @@ html_special(struct html_context *html_context, enum html_special_type c, ...) { if (document) { char *url = va_arg(l, char *); + char *name = va_arg(l, char *); int y = va_arg(l, int); + int width = va_arg(l, int); int height = va_arg(l, int); - add_iframeset_entry(&document->iframe_desc, url, y, height); + add_iframeset_entry(&document->iframe_desc, url, name, y, width, height); } break; } diff --git a/src/document/renderer.c b/src/document/renderer.c index 9771178c..0ccc883c 100644 --- a/src/document/renderer.c +++ b/src/document/renderer.c @@ -515,6 +515,10 @@ render_document_frames(struct session *ses, int no_cache) format_frames(ses, ses->doc_view->document->frame_desc, &doc_opts, 0); } + if (document_has_iframes(ses->doc_view->document)) { + format_iframes(ses, ses->doc_view->document->iframe_desc, &doc_opts, 0); + } + foreach (doc_view, ses->scrn_frames) { struct document_view *prev_doc_view = doc_view->prev; diff --git a/src/network/state.h b/src/network/state.h index c1b8be2a..13071516 100644 --- a/src/network/state.h +++ b/src/network/state.h @@ -13,6 +13,7 @@ enum connection_priority { PRI_MAIN = 0, PRI_DOWNLOAD = 0, PRI_FRAME, + PRI_IFRAME, PRI_CSS, PRI_NEED_IMG, PRI_IMG, diff --git a/src/session/location.c b/src/session/location.c index e48dca40..521985d1 100644 --- a/src/session/location.c +++ b/src/session/location.c @@ -14,7 +14,6 @@ #include "util/memory.h" #include "util/string.h" - /** @relates location */ void copy_location(struct location *dst, struct location *src) @@ -23,6 +22,7 @@ copy_location(struct location *dst, struct location *src) struct frame *iframe, *new_iframe; init_list(dst->frames); + init_list(dst->iframes); foreachback (frame, src->frames) { new_frame = mem_calloc(1, sizeof(*new_frame)); if (new_frame) { @@ -37,7 +37,6 @@ copy_location(struct location *dst, struct location *src) } } - init_list(dst->iframes); foreachback (iframe, src->iframes) { new_iframe = mem_calloc(1, sizeof(*new_iframe)); if (new_iframe) { diff --git a/src/session/session.c b/src/session/session.c index ac63db04..7784b623 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -437,7 +437,7 @@ request_iframe(struct session *ses, char *name, if (c_strcasecmp(iframe->name, name)) continue; - request_additional_file(ses, name, iframe->vs.uri, PRI_FRAME); + request_additional_file(ses, name, iframe->vs.uri, PRI_IFRAME); return; } @@ -454,7 +454,7 @@ request_iframe(struct session *ses, char *name, add_to_list(loc->iframes, iframe); - request_additional_file(ses, name, iframe->vs.uri, PRI_FRAME); + request_additional_file(ses, name, iframe->vs.uri, PRI_IFRAME); } static void @@ -818,7 +818,7 @@ file_loading_callback(struct download *download, struct file_to_load *ftl) ses->loading_uri = ftl->uri; mem_free_set(&ses->task.target.frame, null_or_stracpy(ftl->target_frame)); - setup_download_handler(ses, &ftl->download, ftl->cached, 1); + setup_download_handler(ses, &ftl->download, ftl->cached, 1 + (download->pri == PRI_IFRAME)); ses->loading_uri = loading_uri; mem_free_set(&ses->task.target.frame, target_frame); } @@ -1048,6 +1048,7 @@ init_session(struct session *base_session, struct terminal *term, CO_SHALLOW | CO_NO_LISTBOX_ITEM); create_history(&ses->history); init_list(ses->scrn_frames); + init_list(ses->scrn_iframes); init_list(ses->more_files); init_list(ses->type_queries); ses->task.type = TASK_NONE; @@ -1369,6 +1370,11 @@ destroy_session(struct session *ses) free_list(ses->scrn_frames); + foreach (doc_view, ses->scrn_iframes) + detach_formatted(doc_view); + + free_list(ses->scrn_iframes); + destroy_history(&ses->history); set_session_referrer(ses, NULL); diff --git a/src/session/session.h b/src/session/session.h index 639b8b5b..c8eb6fbb 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -196,6 +196,7 @@ struct session { struct document_view *doc_view; LIST_OF(struct document_view) scrn_frames; + LIST_OF(struct document_view) scrn_iframes; /** The URI from which the next start_download() or resume_download() * call should download, or NULL if no such call is pending. diff --git a/src/session/task.c b/src/session/task.c index dd2e6ea6..81f6575c 100644 --- a/src/session/task.c +++ b/src/session/task.c @@ -324,7 +324,35 @@ x: copy_struct(&loc->download, &ses->loading); } - if (ses->task.target.frame && *ses->task.target.frame) { + if (loaded_in_frame == 2) { + struct frame *iframe; + + assertm(have_location(ses), "no location yet"); + if_assert_failed return NULL; + + struct location *loc = cur_loc(ses); + + iframe = loc->iframes.next; + + if (!iframe) { + return NULL; + } + + vs = &iframe->vs; + + done_uri(vs->uri); + vs->uri = get_uri_reference(ses->loading_uri); + if (vs->doc_view) { + /* vs->doc_view itself will get detached in + * render_document_frames(), but that's too + * late for us. */ + vs->doc_view->vs = NULL; + vs->doc_view = NULL; + } +#ifdef CONFIG_ECMASCRIPT + vs->ecmascript_fragile = 1; +#endif + } else if (ses->task.target.frame && *ses->task.target.frame) { struct frame *frame; assertm(have_location(ses), "no location yet"); @@ -369,6 +397,7 @@ x: if_assert_failed return NULL; init_list(loc->frames); + init_list(loc->iframes); vs = &loc->vs; init_vs(vs, ses->loading_uri, vs->plain); add_to_history(&ses->history, loc); diff --git a/src/viewer/text/draw.c b/src/viewer/text/draw.c index a2e7703e..119c1c68 100644 --- a/src/viewer/text/draw.c +++ b/src/viewer/text/draw.c @@ -374,13 +374,19 @@ draw_frames(struct session *ses) assert(ses && ses->doc_view && ses->doc_view->document); if_assert_failed return; - if (!document_has_frames(ses->doc_view->document)) return; + if (!document_has_frames(ses->doc_view->document) + && !document_has_iframes(ses->doc_view->document)) return; n = 0; foreach (doc_view, ses->scrn_frames) { doc_view->last_x = doc_view->last_y = -1; n++; } + foreach (doc_view, ses->scrn_iframes) { + doc_view->last_x = doc_view->last_y = -1; + n++; + } + l = &cur_loc(ses)->vs.current_link; *l = int_max(*l, 0) % int_max(n, 1); @@ -395,6 +401,9 @@ draw_frames(struct session *ses) else if (doc_view->depth > d) more = 1; } + if (d == 0) foreach (doc_view, ses->scrn_iframes) { + draw_doc(ses, doc_view, 0); + } if (!more) break; d++; diff --git a/test/iframe.html b/test/iframe.html new file mode 100644 index 00000000..e0c1756f --- /dev/null +++ b/test/iframe.html @@ -0,0 +1,9 @@ + + +TESTY1 +
+TESTY2 +
+TESTY3 + + \ No newline at end of file