diff --git a/src/document/dom/select.c b/src/document/dom/select.c index f2f17aa2..10c0728e 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -376,7 +376,7 @@ parse_dom_select(struct dom_select *select, unsigned char *string, int length) struct dom_select_node sel; init_scanner(&scanner, &css_scanner_info, string, string + length); - init_dom_stack(&stack, select, NULL, 0, 1); + init_dom_stack(&stack, select, 0, 1); memset(&sel, 0, sizeof(sel)); @@ -830,8 +830,10 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root) select_data.select = select;; - init_dom_stack(&stack, &select_data, &dom_select_callbacks, 0, 1); - init_dom_stack(&select_data.stack, &select_data, NULL, obj_size, 1); + init_dom_stack(&stack, &select_data, 0, 1); + add_dom_stack_callbacks(&stack, &dom_select_callbacks); + + init_dom_stack(&select_data.stack, &select_data, obj_size, 1); if (push_dom_node(&select_data.stack, &select->selector->node)) { get_dom_stack_top(&select_data.stack)->immutable = 1; diff --git a/src/document/dom/stack.c b/src/document/dom/stack.c index c2cbdea3..327ef0bd 100644 --- a/src/document/dom/stack.c +++ b/src/document/dom/stack.c @@ -46,7 +46,6 @@ realloc_dom_stack_state_objects(struct dom_stack *stack) void init_dom_stack(struct dom_stack *stack, void *data, - struct dom_stack_callbacks *callbacks, size_t object_size, int keep_nodes) { assert(stack); @@ -56,7 +55,6 @@ init_dom_stack(struct dom_stack *stack, void *data, stack->data = data; stack->object_size = object_size; stack->keep_nodes = !!keep_nodes; - stack->callbacks = callbacks; } void @@ -64,12 +62,26 @@ done_dom_stack(struct dom_stack *stack) { assert(stack); + mem_free_if(stack->callbacks); mem_free_if(stack->states); mem_free_if(stack->state_objects); memset(stack, 0, sizeof(*stack)); } +void +add_dom_stack_callbacks(struct dom_stack *stack, + struct dom_stack_callbacks *callbacks) +{ + struct dom_stack_callbacks **list; + + list = mem_realloc(stack->callbacks, sizeof(*list) * (stack->callbacks_size + 1)); + if (!list) return; + + stack->callbacks = list; + stack->callbacks[stack->callbacks_size++] = callbacks; +} + enum dom_stack_action { DOM_STACK_PUSH, DOM_STACK_POP, @@ -79,19 +91,21 @@ static void call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state, enum dom_stack_action action) { - dom_stack_callback_T callback; + /* FIME: Variable stack data, so the parse/selector/renderer/etc. can + * really work in parallel. */ + void *state_data = get_dom_stack_state_data(stack, state); + int i; - if (!stack->callbacks) - callback = NULL; - else if (action == DOM_STACK_PUSH) - callback = stack->callbacks->push[state->node->type]; - else - callback = stack->callbacks->pop[state->node->type]; + for (i = 0; i < stack->callbacks_size; i++) { + dom_stack_callback_T callback; - if (callback) { - void *state_data = get_dom_stack_state_data(stack, state); + if (action == DOM_STACK_PUSH) + callback = stack->callbacks[i]->push[state->node->type]; + else + callback = stack->callbacks[i]->pop[state->node->type]; - callback(stack, state->node, state_data); + if (callback) + callback(stack, state->node, state_data); } } diff --git a/src/document/dom/stack.h b/src/document/dom/stack.h index 5c964de4..31bd23d3 100644 --- a/src/document/dom/stack.h +++ b/src/document/dom/stack.h @@ -54,7 +54,8 @@ struct dom_stack { size_t object_size; /* Callbacks which should be called for the pushed and popped nodes. */ - struct dom_stack_callbacks *callbacks; + struct dom_stack_callbacks **callbacks; + size_t callbacks_size; /* Data specific to the parser and renderer. */ void *data; @@ -115,10 +116,13 @@ search_dom_stack(struct dom_stack *stack, enum dom_node_type type, * state to be assigned to the state's @data member. Zero means no state data should * be allocated. */ void init_dom_stack(struct dom_stack *stack, void *data, - struct dom_stack_callbacks *callbacks, size_t object_size, int keep_nodes); void done_dom_stack(struct dom_stack *stack); +/* Add a callback collection to the stack. */ +void add_dom_stack_callbacks(struct dom_stack *stack, + struct dom_stack_callbacks *callbacks); + /* Decends down to the given node making it the current parent */ /* If an error occurs the node is free()d and NULL is returned */ struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node); diff --git a/src/document/sgml/parser.c b/src/document/sgml/parser.c index 9a083066..84d0250c 100644 --- a/src/document/sgml/parser.c +++ b/src/document/sgml/parser.c @@ -319,8 +319,11 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype, parser->info = get_sgml_info(doctype); parser->data = data; - init_dom_stack(&parser->stack, parser, callbacks, obj_size, + init_dom_stack(&parser->stack, parser, obj_size, type != SGML_PARSER_STREAM); + /* FIXME: Some sgml backend specific callbacks? Handle HTML script tags, + * and feed document.write() data back to the parser. */ + add_dom_stack_callbacks(&parser->stack, callbacks); parser->root = add_sgml_document(&parser->stack, parser->uri); if (!parser->root) {