multitable.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* Copyright 2010, 2011, 2012, 2013, 2014, 2015
  2. Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #include "parser.h"
  14. #include "errors.h"
  15. /* Return the parent if in an item_line command, @*table */
  16. ELEMENT *
  17. item_line_parent (ELEMENT *current)
  18. {
  19. if (current->cmd == CM_item || current->cmd == CM_itemx)
  20. current = current->parent->parent;
  21. else if (current->type == ET_before_item && current->parent)
  22. current = current->parent;
  23. if (item_line_command (current->cmd))
  24. return current;
  25. return 0;
  26. }
  27. /* Return the parent if in a multitable. */
  28. ELEMENT *
  29. item_multitable_parent (ELEMENT *current)
  30. {
  31. if (current->cmd == CM_headitem
  32. || current->cmd == CM_item
  33. || current->cmd == CM_tab)
  34. {
  35. if (current->parent && current->parent->parent)
  36. current = current->parent->parent;
  37. }
  38. else if (current->type == ET_before_item)
  39. {
  40. current = current->parent;
  41. }
  42. if (current->cmd == CM_multitable)
  43. return current;
  44. return 0;
  45. }
  46. // 1381
  47. /* Put the contents of a @table row in a ET_table_entry container, containing
  48. a ET_table_term element and a ET_table_item element. The elements of
  49. this row currently occur the end of the contents of CURRENT as immediate
  50. children.
  51. NEXT_COMMAND is the command that ends this row, usually CM_item. It is null
  52. at the end of a @table. If NEXT_COMMAND is given as CM_itemx, gather a
  53. ET_inter_item container instead. */
  54. void
  55. gather_previous_item (ELEMENT *current, enum command_id next_command)
  56. {
  57. ELEMENT *gathered;
  58. enum command_id type;
  59. int i, contents_count;
  60. if (last_contents_child(current)
  61. && last_contents_child(current)->type == ET_before_item)
  62. {
  63. if (next_command == CM_itemx)
  64. line_warn ("@itemx should not begin @%s", command_name(current->cmd));
  65. return;
  66. }
  67. type = next_command != CM_itemx ? ET_table_item : ET_inter_item;
  68. gathered = new_element (type);
  69. /* Starting from the end, collect everything that is not a ET_item
  70. or ET_itemx and put it into the ET_table_item. */
  71. contents_count = current->contents.number;
  72. for (i = 0; i < contents_count; i++)
  73. {
  74. ELEMENT *e;
  75. if (last_contents_child(current)->cmd == CM_item
  76. || last_contents_child(current)->cmd == CM_itemx)
  77. break;
  78. e = pop_element_from_contents (current);
  79. insert_into_contents (gathered, e, 0);
  80. }
  81. /* TODO: A similar algorithm is is in gather_def_item in def.c. If
  82. speed is an issue then we could move all the elements at once instead
  83. of calling insert_into_contents multiple times. */
  84. if (type == ET_table_item) // 1423
  85. {
  86. ELEMENT *table_entry = new_element (ET_table_entry);
  87. ELEMENT *table_term = new_element (ET_table_term);
  88. add_to_element_contents (table_entry, table_term);
  89. /* We previously collected elements into a ET_table_item. Now
  90. do the same for ET_table_term. */
  91. contents_count = current->contents.number;
  92. for (i = 0; i < contents_count; i++)
  93. {
  94. ELEMENT *e;
  95. if (last_contents_child(current)->type == ET_before_item
  96. || last_contents_child(current)->type == ET_table_entry)
  97. break;
  98. e = pop_element_from_contents (current);
  99. insert_into_contents (table_term, e, 0);
  100. }
  101. add_to_element_contents (current, table_entry);
  102. if (gathered->contents.number > 0)
  103. add_to_element_contents (table_entry, gathered);
  104. else
  105. destroy_element (gathered);
  106. }
  107. else /* Gathering ET_inter_item between @item and @itemx */ // 1457
  108. {
  109. /* Text between @item and @itemx is only allowed in a few cases:
  110. comments, empty lines, or index entries. */
  111. if (check_no_text (gathered))
  112. line_error ("@itemx must follow @item");
  113. if (gathered->contents.number > 0)
  114. add_to_element_contents (current, gathered);
  115. else
  116. destroy_element (gathered);
  117. }
  118. }