Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of Hubbub.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2008 Andrew Sidwell <takkaria@netsurf-browser.org>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <string.h>
  10.  
  11. #include "treebuilder/modes.h"
  12. #include "treebuilder/internal.h"
  13. #include "treebuilder/treebuilder.h"
  14. #include "utils/utils.h"
  15. #include "utils/string.h"
  16.  
  17.  
  18. /**
  19.  * Clear the stack back to a table context: "the UA must, while the current
  20.  * node is not a table element or an html element, pop elements from the stack
  21.  * of open elements."
  22.  */
  23. static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder)
  24. {
  25.         hubbub_ns ns;
  26.         element_type type = current_node(treebuilder);
  27.         void *node;
  28.  
  29.         while (type != TABLE && type != HTML) {
  30.                 element_stack_pop(treebuilder, &ns, &type, &node);
  31.  
  32.                 treebuilder->tree_handler->unref_node(
  33.                                 treebuilder->tree_handler->ctx,
  34.                                 node);
  35.  
  36.                 type = current_node(treebuilder);
  37.         }
  38. }
  39.  
  40.  
  41. /**
  42.  * Process an input start tag in the "in table" insertion mode.
  43.  */
  44. static inline hubbub_error process_input_in_table(
  45.                 hubbub_treebuilder *treebuilder,
  46.                 const hubbub_token *token)
  47. {
  48.         hubbub_error err = HUBBUB_REPROCESS;
  49.         size_t i;
  50.  
  51.         for (i = 0; i < token->data.tag.n_attributes; i++) {
  52.                 hubbub_attribute *attr = &token->data.tag.attributes[i];
  53.  
  54.                 if (!hubbub_string_match_ci(attr->value.ptr, attr->value.len,
  55.                                 (uint8_t *) "hidden", SLEN("hidden"))) {
  56.                         continue;
  57.                 }
  58.  
  59.                 /** \todo parse error */
  60.                 err = insert_element(treebuilder, &token->data.tag, true);
  61.         }
  62.  
  63.         return err;
  64. }
  65.  
  66.  
  67. /**
  68.  * Handle token in "in table" insertion mode
  69.  *
  70.  * \param treebuilder  The treebuilder instance
  71.  * \param token        The token to handle
  72.  * \return True to reprocess token, false otherwise
  73.  */
  74. hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
  75.                 const hubbub_token *token)
  76. {
  77.         hubbub_error err = HUBBUB_OK;
  78.         bool handled = true;
  79.  
  80.         switch (token->type) {
  81.         case HUBBUB_TOKEN_CHARACTER:
  82.                 if (treebuilder->context.element_stack[
  83.                                 current_table(treebuilder)
  84.                                 ].tainted) {
  85.                         handled = false;
  86.                 } else {
  87.                         err = process_characters_expect_whitespace(
  88.                                         treebuilder, token, true);
  89.                         handled = (err == HUBBUB_OK);
  90.                 }
  91.                 break;
  92.         case HUBBUB_TOKEN_COMMENT:
  93.                 err = process_comment_append(treebuilder, token,
  94.                                 treebuilder->context.element_stack[
  95.                                 treebuilder->context.current_node].node);
  96.                 break;
  97.         case HUBBUB_TOKEN_DOCTYPE:
  98.                 /** \todo parse error */
  99.                 break;
  100.         case HUBBUB_TOKEN_START_TAG:
  101.         {
  102.                 element_type type = element_type_from_name(treebuilder,
  103.                                 &token->data.tag.name);
  104.                 bool tainted = treebuilder->context.element_stack[
  105.                                         current_table(treebuilder)
  106.                                         ].tainted;
  107.  
  108.                 if (type == CAPTION) {
  109.                         clear_stack_table_context(treebuilder);
  110.  
  111.                         treebuilder->tree_handler->ref_node(
  112.                                 treebuilder->tree_handler->ctx,
  113.                                 treebuilder->context.element_stack[
  114.                                 treebuilder->context.current_node].node);
  115.  
  116.                         err = formatting_list_append(treebuilder,
  117.                                         token->data.tag.ns, type,
  118.                                         treebuilder->context.element_stack[
  119.                                         treebuilder->context.current_node].node,
  120.                                         treebuilder->context.current_node);
  121.                         if (err != HUBBUB_OK) {
  122.                                 treebuilder->tree_handler->unref_node(
  123.                                         treebuilder->tree_handler->ctx,
  124.                                         treebuilder->context.element_stack[
  125.                                         treebuilder->context.current_node].node);
  126.  
  127.                                 return err;
  128.                         }
  129.  
  130.                         err = insert_element(treebuilder, &token->data.tag,
  131.                                         true);
  132.                         if (err != HUBBUB_OK) {
  133.                                 hubbub_ns ns;
  134.                                 element_type type;
  135.                                 void *node;
  136.                                 uint32_t index;
  137.  
  138.                                 formatting_list_remove(treebuilder,
  139.                                         treebuilder->context.formatting_list_end,
  140.                                         &ns, &type, &node, &index);
  141.  
  142.                                 treebuilder->tree_handler->unref_node(
  143.                                         treebuilder->tree_handler->ctx,
  144.                                         node);
  145.  
  146.                                 return err;
  147.                         }
  148.  
  149.                         treebuilder->context.mode = IN_CAPTION;
  150.                 } else if (type == COLGROUP || type == COL) {
  151.                         hubbub_error e;
  152.                         hubbub_tag tag = token->data.tag;
  153.  
  154.                         if (type == COL) {
  155.                                 /* Insert colgroup and reprocess */
  156.                                 tag.name.ptr = (const uint8_t *) "colgroup";
  157.                                 tag.name.len = SLEN("colgroup");
  158.                                 tag.n_attributes = 0;
  159.                                 tag.attributes = NULL;
  160.  
  161.                                 err = HUBBUB_REPROCESS;
  162.                         }
  163.  
  164.                         clear_stack_table_context(treebuilder);
  165.  
  166.                         e = insert_element(treebuilder, &tag, true);
  167.                         if (e != HUBBUB_OK)
  168.                                 return e;
  169.  
  170.                         treebuilder->context.mode = IN_COLUMN_GROUP;
  171.                 } else if (type == TBODY || type == TFOOT || type == THEAD ||
  172.                                 type == TD || type == TH || type == TR) {
  173.                         hubbub_error e;
  174.                         hubbub_tag tag = token->data.tag;
  175.  
  176.                         if (type == TD || type == TH || type == TR) {
  177.                                 /* Insert tbody and reprocess */
  178.                                 tag.name.ptr = (const uint8_t *) "tbody";
  179.                                 tag.name.len = SLEN("tbody");
  180.                                 tag.n_attributes = 0;
  181.                                 tag.attributes = NULL;
  182.  
  183.                                 err = HUBBUB_REPROCESS;
  184.                         }
  185.  
  186.                         clear_stack_table_context(treebuilder);
  187.  
  188.                         e = insert_element(treebuilder, &tag, true);
  189.                         if (e != HUBBUB_OK)
  190.                                 return e;
  191.  
  192.                         treebuilder->context.mode = IN_TABLE_BODY;
  193.                 } else if (type == TABLE) {
  194.                         /** \todo parse error */
  195.  
  196.                         /* This should match "</table>" handling */
  197.                         element_stack_pop_until(treebuilder, TABLE);
  198.  
  199.                         reset_insertion_mode(treebuilder);
  200.  
  201.                         err = HUBBUB_REPROCESS;
  202.                 } else if (!tainted && (type == STYLE || type == SCRIPT)) {
  203.                         err = handle_in_head(treebuilder, token);
  204.                 } else if (!tainted && type == INPUT) {
  205.                         err = process_input_in_table(treebuilder, token);
  206.                         handled = (err == HUBBUB_OK);
  207.                 } else {
  208.                         handled = false;
  209.                 }
  210.         }
  211.                 break;
  212.         case HUBBUB_TOKEN_END_TAG:
  213.         {
  214.                 element_type type = element_type_from_name(treebuilder,
  215.                                 &token->data.tag.name);
  216.  
  217.                 if (type == TABLE) {
  218.                         /** \todo fragment case */
  219.  
  220.                         element_stack_pop_until(treebuilder, TABLE);
  221.  
  222.                         reset_insertion_mode(treebuilder);
  223.                 } else if (type == BODY || type == CAPTION || type == COL ||
  224.                                 type == COLGROUP || type == HTML ||
  225.                                 type == TBODY || type == TD || type == TFOOT ||
  226.                                 type == TH || type == THEAD || type == TR) {
  227.                         /** \todo parse error */
  228.                 } else {
  229.                         handled = false;
  230.                 }
  231.         }
  232.                 break;
  233.         case HUBBUB_TOKEN_EOF:
  234.                 break;
  235.         }
  236.  
  237.         if (!handled) {
  238.                 treebuilder->context.in_table_foster = true;
  239.  
  240.                 /** \todo parse error */
  241.                 err = handle_in_body(treebuilder, token);
  242.  
  243.                 treebuilder->context.in_table_foster = false;
  244.         }
  245.  
  246.  
  247.         return err;
  248. }
  249.