1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

[document] Added function scan document

This function must calculate dimensions of nodes in document.
Every node has a rectangle. x0,y0 is the left up corner, x1,y1 - the right bottom.
In theory every child of given node is contained in this rectangle.
This commit is contained in:
Witold Filipczyk 2024-01-26 18:43:33 +01:00
parent 5c8b62247a
commit 9e3d874577
5 changed files with 364 additions and 3 deletions

View File

@ -21,6 +21,7 @@ struct ecmascript_timeout;
struct el_form_control;
struct frame_desc;
struct frameset_desc;
struct hash;
struct image;
struct module;
struct screen_char;
@ -241,6 +242,7 @@ struct document {
void *element_map_rev;
struct string text;
void *forms_nodeset;
struct hash *hh;
#endif
#ifdef CONFIG_CSS

View File

@ -274,8 +274,8 @@ get_format_screen_char(struct html_context *html_context,
&& html_context->options->underline_links) {
schar_cache.attr |= SCREEN_ATTR_UNDERLINE;
}
schar_cache.element_offset = (html_top->name && html_context->document && html_context->document->text.source) ? html_top->name - html_context->document->text.source : 0;
schar_cache.element_offset = (elformat.top_name && html_context->document && html_context->document->text.source) ? elformat.top_name - html_context->document->text.source : 0;
return &schar_cache;
}

View File

@ -19,7 +19,9 @@
#include "document/libdom/doc.h"
#include "document/libdom/mapa.h"
#include "document/libdom/renderer2.h"
#include "document/view.h"
#include "ecmascript/libdom/parse.h"
#include "util/hash.h"
#include "util/string.h"
static int in_script = 0;
@ -289,6 +291,172 @@ render_xhtml_document(struct cache_entry *cached, struct document *document, str
dump_xhtml(cached, document, 0);
}
static struct node_rect *get_element(struct document *doc, int offset);
static void
walk_tree2(struct document *document, dom_node *node)
{
dom_node *child = NULL;
/* Get the node's first child */
dom_exception exc = dom_node_get_first_child(node, &child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_first_child\n");
return;
}
while (child != NULL) {
/* Loop though all node's children */
dom_node *next_child;
/* Visit node's descendents */
walk_tree2(document, child);
/* Go to next sibling */
exc = dom_node_get_next_sibling(child, &next_child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_next_sibling\n");
dom_node_unref(child);
return;
}
dom_node_unref(child);
child = next_child;
}
int offset = find_offset(document->element_map_rev, node);
if (offset <= 0) {
return;
}
struct node_rect *tab = get_element(document, offset);
if (!tab) {
return;
}
exc = dom_node_get_first_child(node, &child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_first_child\n");
return;
}
while (child != NULL) {
/* Loop though all node's children */
dom_node *next_child;
int offset_i = find_offset(document->element_map_rev, child);
if (offset_i <= 0) {
goto next;
}
struct node_rect *rect_i = get_element(document, offset_i);
if (!rect_i) {
goto next;
}
if (rect_i->x0 == INT_MAX) {
goto next;
}
if (tab->x0 > rect_i->x0) {
tab->x0 = rect_i->x0;
}
if (tab->y0 > rect_i->y0) {
tab->y0 = rect_i->y0;
}
if (tab->x1 < rect_i->x1) {
tab->x1 = rect_i->x1;
}
if (tab->y1 < rect_i->y1) {
tab->y1 = rect_i->y1;
}
next:
/* Go to next sibling */
exc = dom_node_get_next_sibling(child, &next_child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_next_sibling\n");
dom_node_unref(child);
return;
}
dom_node_unref(child);
child = next_child;
}
}
static void
walk_tree2_color(struct terminal *term, struct el_box *box, struct document *document, int vx, int vy, dom_node *node)
{
dom_node *child = NULL;
/* Get the node's first child */
dom_exception exc = dom_node_get_first_child(node, &child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_first_child\n");
return;
}
int offset = find_offset(document->element_map_rev, node);
if (offset <= 0) {
return;
}
struct node_rect *tab = get_element(document, offset);
if (!tab) {
return;
}
if (tab->y0 >= document->height) {
return;
}
if (tab->x0 >= document->data[tab->y0].length) {
return;
}
struct screen_char *sc = &document->data[tab->y0].ch.chars[tab->x0];
int ymax = int_min(document->height, tab->y1 + 1);
int y, x;
for (y = int_max(vy, tab->y0);
y < int_min(ymax, box->height + vy);
y++) {
int st = int_max(vx, tab->x0);
int xmax = int_min(box->width + vx, tab->x1 + 1);
for (x = st; x < xmax; x++) {
if (x >= document->data[y].length || (document->data[y].ch.chars[x].data == ' ' && document->data[y].ch.chars[x].element_offset == 0)) {
draw_space(term, box->x + x - vx, box->y + y - vy, sc);
}
}
}
exc = dom_node_get_first_child(node, &child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_first_child\n");
return;
}
while (child != NULL) {
/* Loop though all node's children */
dom_node *next_child;
/* Visit node's descendents */
walk_tree2_color(term, box, document, vx, vy, child);
/* Go to next sibling */
exc = dom_node_get_next_sibling(child, &next_child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_next_sibling\n");
dom_node_unref(child);
return;
}
dom_node_unref(child);
child = next_child;
}
}
void
dump_xhtml(struct cache_entry *cached, struct document *document, int parse)
{
@ -301,7 +469,6 @@ dump_xhtml(struct cache_entry *cached, struct document *document, int parse)
if (!document->dom) {
return;
}
doc = document->dom;
in_script = 0;
@ -372,3 +539,172 @@ dump_xhtml(struct cache_entry *cached, struct document *document, int parse)
render_html_document(cached, document, &document->text);
}
}
void
walk2(struct document *document)
{
dom_exception exc; /* returned by libdom functions */
dom_document *doc = NULL; /* document, loaded into libdom */
dom_node *root = NULL; /* root element of document */
if (!document->dom) {
return;
}
doc = document->dom;
/* Get root element */
exc = dom_document_get_document_element(doc, &root);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for get_document_element\n");
//dom_node_unref(doc);
return;
} else if (root == NULL) {
fprintf(stderr, "Broken: root == NULL\n");
//dom_node_unref(doc);
return;
}
walk_tree2(document, root);
dom_node_unref(root);
}
static int prev_offset = 0;
static struct node_rect *prev_element = NULL;
static struct node_rect *
get_element(struct document *document, int offset)
{
if (offset == prev_offset) {
return prev_element;
}
struct hash_item *item = get_hash_item(document->hh, (const char *)&offset, sizeof(offset));
if (item) {
prev_offset = offset;
prev_element = item->value;
return prev_element;
}
struct node_rect *n = mem_alloc(sizeof(*n));
if (!n) {
return NULL;
}
n->x0 = INT_MAX;
n->y0 = INT_MAX;
n->x1 = 0;
n->y1 = 0;
n->offset = offset;
char *key = memacpy((const char *)&offset, sizeof(offset));
if (key) {
item = add_hash_item(document->hh, key, sizeof(offset), n);
}
if (!item) {
mem_free(n);
return NULL;
}
prev_offset = offset;
prev_element = n;
return n;
}
//static void dump_results(struct document *document);
void
scan_document(struct document_view *doc_view)
{
int y, x;
if (doc_view->document->hh) {
free_hash(&doc_view->document->hh);
}
doc_view->document->hh = init_hash8();
if (!doc_view->document->hh) {
return;
}
if (!doc_view || !doc_view->document) {
return;
}
prev_offset = 0;
prev_element = NULL;
for (y = 0; y < doc_view->document->height; y++) {
for (x = 0; x < doc_view->document->data[y].length; x++) {
int offset = doc_view->document->data[y].ch.chars[x].element_offset;
if (!offset) {
continue;
}
struct node_rect *tab = get_element(doc_view->document, offset);
if (!tab) {
continue;
}
if (tab->x0 > x) {
tab->x0 = x;
}
if (tab->y0 > y) {
tab->y0 = y;
}
if (tab->x1 < x) {
tab->x1 = x;
}
if (tab->y1 < y) {
tab->y1 = x;
}
}
}
// dump_results(doc_view->document);
prev_offset = 0;
prev_element = NULL;
walk2(doc_view->document);
// dump_results(doc_view->document);
}
#if 0
static void
dump_results(struct document *document)
{
struct hash_item *item;
int i;
foreach_hash_item(item, *(document->hh), i) {
struct node_rect *rect = item->value;
fprintf(stderr, "%d:(%d,%d):(%d,%d)\n", rect->offset, rect->x0, rect->y0, rect->x1, rect->y1);
}
fprintf(stderr, "=============================\n");
}
#endif
void
try_to_color(struct terminal *term, struct el_box *box, struct document *document, int vx, int vy)
{
dom_exception exc; /* returned by libdom functions */
dom_document *doc = NULL; /* document, loaded into libdom */
dom_node *root = NULL; /* root element of document */
if (!document->dom) {
return;
}
doc = document->dom;
/* Get root element */
exc = dom_document_get_document_element(doc, &root);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for get_document_element\n");
//dom_node_unref(doc);
return;
} else if (root == NULL) {
fprintf(stderr, "Broken: root == NULL\n");
//dom_node_unref(doc);
return;
}
walk_tree2_color(term, box, document, vx, vy, root);
dom_node_unref(root);
}

View File

@ -7,10 +7,20 @@ extern "C" {
struct cache_entry;
struct document;
struct document_view;
struct el_box;
struct string;
struct terminal;
struct node_rect {
int x0, y0, x1, y1, offset;
};
void render_xhtml_document(struct cache_entry *cached, struct document *document, struct string *buffer);
void dump_xhtml(struct cache_entry *cached, struct document *document, int parse);
void walk2(struct document *document);
void scan_document(struct document_view *doc_view);
void try_to_color(struct terminal *term, struct el_box *box, struct document *document, int vx, int vy);
#ifdef __cplusplus
}

View File

@ -19,6 +19,7 @@
#include "document/document.h"
#include "document/html/frames.h"
#include "document/html/iframes.h"
#include "document/libdom/renderer2.h"
#include "document/options.h"
#include "document/refresh.h"
#include "document/renderer.h"
@ -36,6 +37,7 @@
#include "terminal/tab.h"
#include "terminal/terminal.h"
#include "util/error.h"
#include "util/hash.h"
#include "util/lists.h"
#include "util/memory.h"
#include "util/string.h"
@ -417,6 +419,7 @@ draw_doc(struct session *ses, struct document_view *doc_view, int active)
if (ses->navigate_mode == NAVIGATE_LINKWISE)
check_vs(doc_view);
}
for (y = int_max(vy, 0);
y < int_min(doc_view->document->height, box->height + vy);
y++) {
@ -441,6 +444,7 @@ draw_doc(struct session *ses, struct document_view *doc_view, int active)
}
}
}
for (i = st; i < max; i++) {
if (doc_view->document->data[y].ch.chars[i].data != ' ') {
first = &doc_view->document->data[y].ch.chars[i];
@ -458,6 +462,10 @@ draw_doc(struct session *ses, struct document_view *doc_view, int active)
last);
}
}
#if 0
try_to_color(term, box, doc_view->document, vx, vy);
#endif
draw_view_status(ses, doc_view, active);
if (has_search_word(doc_view))
doc_view->last_x = doc_view->last_y = -1;
@ -618,11 +626,16 @@ refresh_view(struct session *ses, struct document_view *doc_view, int frames)
* form field has changed, @ses might not be in the current
* tab: consider SELECT pop-ups behind which -remote loads
* another tab, or setTimeout in ECMAScript. */
if (ses->tab == get_current_tab(ses->tab->term)) {
if (doc_view->parent_doc_view) {
#ifdef CONFIG_LIBDOM
scan_document(doc_view->parent_doc_view);
#endif
draw_doc(ses, doc_view->parent_doc_view, 0);
} else {
#ifdef CONFIG_LIBDOM
scan_document(doc_view);
#endif
draw_doc(ses, doc_view, 1);
}
if (frames) draw_frames(ses);