summaryrefslogtreecommitdiff
path: root/src/treebuilder/in_foreign_content.c
diff options
context:
space:
mode:
authorAndrew Sidwell <andy@entai.co.uk>2008-06-30 10:45:26 +0000
committerAndrew Sidwell <andy@entai.co.uk>2008-06-30 10:45:26 +0000
commit833ee4b1f01b5da2327ab79777219b88528162c6 (patch)
tree6e740940753b73513528c6cc932361008af3860b /src/treebuilder/in_foreign_content.c
parent17447f074c102bdac9fdf3e1e0308c1b2e9718b6 (diff)
downloadlibhubbub-833ee4b1f01b5da2327ab79777219b88528162c6.tar.gz
libhubbub-833ee4b1f01b5da2327ab79777219b88528162c6.tar.bz2
Add "in foreign content" handling. Not convinced this is the best way.
svn path=/trunk/hubbub/; revision=4475
Diffstat (limited to 'src/treebuilder/in_foreign_content.c')
-rw-r--r--src/treebuilder/in_foreign_content.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/treebuilder/in_foreign_content.c b/src/treebuilder/in_foreign_content.c
new file mode 100644
index 0000000..d1338e7
--- /dev/null
+++ b/src/treebuilder/in_foreign_content.c
@@ -0,0 +1,139 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 Andrew Sidwell
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+
+static bool element_in_scope_in_non_html_ns(hubbub_treebuilder *treebuilder)
+{
+ uint32_t node;
+
+ if (treebuilder->context.element_stack == NULL)
+ return false;
+
+ for (node = treebuilder->context.current_node; node > 0; node--) {
+ element_type node_ns =
+ treebuilder->context.element_stack[node].ns;
+
+ if (node_ns != HTML)
+ return true;
+ }
+
+ return false;
+}
+
+
+
+/**
+ * Handle tokens in "in foreign content" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to process
+ * \return True to reprocess the token, false otherwise
+ */
+bool handle_in_foreign_content(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ append_text(treebuilder, &token->data.character);
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ element_type cur_node = current_node(treebuilder);
+ hubbub_ns cur_node_ns = current_node_ns(treebuilder);
+
+ if (cur_node_ns == HUBBUB_NS_HTML ||
+ (cur_node_ns == HUBBUB_NS_MATHML &&
+ (type != MGLYPH && type != MALIGNMARK) &&
+ (cur_node == MI || cur_node == MO ||
+ cur_node == MN || cur_node == MS ||
+ cur_node == MTEXT))) {
+ treebuilder->context.mode =
+ treebuilder->context.second_mode;
+ hubbub_treebuilder_token_handler(token, treebuilder);
+
+ if (treebuilder->context.mode == IN_FOREIGN_CONTENT &&
+ !element_in_scope_in_non_html_ns(treebuilder)) {
+ treebuilder->context.mode =
+ treebuilder->context.second_mode;
+ }
+ } else if (type == B || type == BIG || type == BLOCKQUOTE ||
+ type == BODY || type == BR || type == CENTER ||
+ type == CODE || type == DD || type == DIV ||
+ type == DL || type == DT || type == EM ||
+ type == EMBED || type == FONT || type == H1 ||
+ type == H2 || type == H3 || type == H4 ||
+ type == H5 || type == H6 || type == HEAD ||
+ type == HR || type == I || type == IMG ||
+ type == LI || type == LISTING ||
+ type == MENU || type == META || type == NOBR ||
+ type == OL || type == P || type == PRE ||
+ type == RUBY || type == S || type == SMALL ||
+ type == SPAN || type == STRONG ||
+ type == STRIKE || type == SUB || type == SUP ||
+ type == TABLE || type == TT || type == U ||
+ type == UL || type == VAR) {
+ /** \todo parse error */
+
+ while (cur_node_ns != HUBBUB_NS_HTML) {
+ void *node;
+ element_stack_pop(treebuilder, &cur_node_ns,
+ &cur_node, &node);
+ cur_node_ns = current_node_ns(treebuilder);
+ }
+
+ treebuilder->context.mode =
+ treebuilder->context.second_mode;
+ } else {
+ hubbub_tag tag = token->data.tag;
+
+ adjust_foreign_attributes(treebuilder, &tag);
+
+ /* Set to the right namespace and insert */
+ tag.ns = cur_node_ns;
+
+ if (token->data.tag.self_closing) {
+ insert_element_no_push(treebuilder, &tag);
+ /** \todo ack sc flag */
+ } else {
+ insert_element(treebuilder, &tag);
+ }
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ /** \parse error */
+ break;
+ case HUBBUB_TOKEN_EOF:
+ reprocess = true;
+ break;
+ }
+
+ return reprocess;
+}
+