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.  
  16.  
  17. /**
  18.  * Clear the stack back to a table body context.
  19.  *
  20.  * \param treebuilder   The treebuilder instance
  21.  */
  22. static void table_clear_stack(hubbub_treebuilder *treebuilder)
  23. {
  24.         element_type cur_node = current_node(treebuilder);
  25.  
  26.         while (cur_node != TBODY && cur_node != TFOOT &&
  27.                         cur_node != THEAD && cur_node != HTML) {
  28.                 hubbub_ns ns;
  29.                 element_type type;
  30.                 void *node;
  31.  
  32.                 element_stack_pop(treebuilder, &ns, &type, &node);
  33.  
  34.                 treebuilder->tree_handler->unref_node(
  35.                                 treebuilder->tree_handler->ctx,
  36.                                 node);
  37.  
  38.                 cur_node = current_node(treebuilder);
  39.         }
  40.  
  41.         return;
  42. }
  43.  
  44.  
  45. /**
  46.  * Handle the case common to some start tag and the table end tag cases.
  47.  *
  48.  * \param treebuilder   The treebuilder instance
  49.  * \return Whether to reprocess the current token
  50.  */
  51. static hubbub_error table_sub_start_or_table_end(hubbub_treebuilder *treebuilder)
  52. {
  53.         if (element_in_scope(treebuilder, TBODY, true) ||
  54.                         element_in_scope(treebuilder, THEAD, true) ||
  55.                         element_in_scope(treebuilder, TFOOT, true)) {
  56.                 hubbub_ns ns;
  57.                 element_type otype;
  58.                 void *node;
  59.  
  60.                 table_clear_stack(treebuilder);
  61.  
  62.                 /* "Act as if an end tag with the same name as the current
  63.                  * node had been seen" -- this behaviour should be identical
  64.                  * to handling for (tbody/tfoot/thead) end tags in this mode */
  65.                 element_stack_pop(treebuilder, &ns, &otype, &node);
  66.  
  67.                 treebuilder->tree_handler->unref_node(
  68.                                 treebuilder->tree_handler->ctx,
  69.                                 node);
  70.  
  71.                 treebuilder->context.mode = IN_TABLE;
  72.  
  73.                 return HUBBUB_REPROCESS;
  74.         } else {
  75.                 /** \todo parse error */
  76.         }
  77.  
  78.         return HUBBUB_OK;
  79. }
  80.  
  81.  
  82. /**
  83.  * Handle tokens in "in table body" insertion mode
  84.  *
  85.  * \param treebuilder  The treebuilder instance
  86.  * \param token        The token to process
  87.  * \return True to reprocess the token, false otherwise
  88.  */
  89. hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder,
  90.                 const hubbub_token *token)
  91. {
  92.         hubbub_error err = HUBBUB_OK;
  93.  
  94.         switch (token->type) {
  95.         case HUBBUB_TOKEN_START_TAG:
  96.         {
  97.                 element_type type = element_type_from_name(treebuilder,
  98.                                 &token->data.tag.name);
  99.  
  100.                 if (type == TR) {
  101.                         table_clear_stack(treebuilder);
  102.  
  103.                         err = insert_element(treebuilder, &token->data.tag,
  104.                                         true);
  105.                         if (err == HUBBUB_OK)
  106.                                 treebuilder->context.mode = IN_ROW;
  107.                 } else if (type == TH || type == TD) {
  108.                         hubbub_tag tag;
  109.  
  110.                         /** \todo parse error */
  111.  
  112.                         /* Manufacture tr tag */
  113.                         tag.ns = HUBBUB_NS_HTML;
  114.                         tag.name.ptr = (const uint8_t *) "tr";
  115.                         tag.name.len = SLEN("tr");
  116.  
  117.                         tag.n_attributes = 0;
  118.                         tag.attributes = NULL;
  119.  
  120.                         table_clear_stack(treebuilder);
  121.  
  122.                         err = insert_element(treebuilder, &tag, true);
  123.                         if (err == HUBBUB_OK) {
  124.                                 treebuilder->context.mode = IN_ROW;
  125.  
  126.                                 err = HUBBUB_REPROCESS;
  127.                         }
  128.                 } else if (type == CAPTION || type == COL ||
  129.                                 type == COLGROUP || type == TBODY ||
  130.                                 type == TFOOT || type == THEAD) {
  131.                         err = table_sub_start_or_table_end(treebuilder);
  132.                 } else {
  133.                         err = handle_in_table(treebuilder, token);
  134.                 }
  135.         }
  136.                 break;
  137.         case HUBBUB_TOKEN_END_TAG:
  138.         {
  139.                 element_type type = element_type_from_name(treebuilder,
  140.                                 &token->data.tag.name);
  141.  
  142.                 if (type == TBODY || type == TFOOT || type == THEAD) {
  143.                         if (!element_in_scope(treebuilder, type, true)) {
  144.                                 /** \todo parse error */
  145.                                 /* Ignore the token */
  146.                         } else {
  147.                                 hubbub_ns ns;
  148.                                 element_type otype;
  149.                                 void *node;
  150.  
  151.                                 table_clear_stack(treebuilder);
  152.  
  153.                                 element_stack_pop(treebuilder, &ns,
  154.                                                 &otype, &node);
  155.  
  156.                                 treebuilder->tree_handler->unref_node(
  157.                                                 treebuilder->tree_handler->ctx,
  158.                                                 node);
  159.  
  160.                                 treebuilder->context.mode = IN_TABLE;
  161.                         }
  162.                 } else if (type == TABLE) {
  163.                         err = table_sub_start_or_table_end(treebuilder);
  164.                 } else if (type == BODY || type == CAPTION || type == COL ||
  165.                                 type == COLGROUP || type == HTML ||
  166.                                 type == TD || type == TH || type == TR) {
  167.                         /** \todo parse error */
  168.                         /* Ignore the token */
  169.                 } else {
  170.                         err = handle_in_table(treebuilder, token);
  171.                 }
  172.         }
  173.                 break;
  174.         case HUBBUB_TOKEN_CHARACTER:
  175.         case HUBBUB_TOKEN_COMMENT:
  176.         case HUBBUB_TOKEN_DOCTYPE:
  177.         case HUBBUB_TOKEN_EOF:
  178.                 err = handle_in_table(treebuilder, token);
  179.                 break;
  180.         }
  181.  
  182.         return err;
  183. }
  184.  
  185.