/contrib/groff/src/preproc/eqn/script.cpp

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 222 lines · 181 code · 12 blank · 29 comment · 46 complexity · e17d9f900a68edaef1aa0bb8e3274412 MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
  3. Free Software Foundation, Inc.
  4. Written by James Clark (jjc@jclark.com)
  5. This file is part of groff.
  6. groff is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 2, or (at your option) any later
  9. version.
  10. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with groff; see the file COPYING. If not, write to the Free Software
  16. Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
  17. #include "eqn.h"
  18. #include "pbox.h"
  19. class script_box : public pointer_box {
  20. private:
  21. box *sub;
  22. box *sup;
  23. public:
  24. script_box(box *, box *, box *);
  25. ~script_box();
  26. int compute_metrics(int);
  27. void output();
  28. void debug_print();
  29. int left_is_italic();
  30. void hint(unsigned);
  31. void check_tabs(int);
  32. };
  33. /* The idea is that the script should attach to the rightmost box
  34. of a list. For example, given `2x sup 3', the superscript should
  35. attach to `x' rather than `2x'. */
  36. box *make_script_box(box *nuc, box *sub, box *sup)
  37. {
  38. list_box *b = nuc->to_list_box();
  39. if (b != 0) {
  40. b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
  41. sub,
  42. sup);
  43. return b;
  44. }
  45. else
  46. return new script_box(nuc, sub, sup);
  47. }
  48. script_box::script_box(box *pp, box *qq, box *rr)
  49. : pointer_box(pp), sub(qq), sup(rr)
  50. {
  51. }
  52. script_box::~script_box()
  53. {
  54. delete sub;
  55. delete sup;
  56. }
  57. int script_box::left_is_italic()
  58. {
  59. return p->left_is_italic();
  60. }
  61. int script_box::compute_metrics(int style)
  62. {
  63. int res = p->compute_metrics(style);
  64. p->compute_subscript_kern();
  65. printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
  66. if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
  67. set_script_size();
  68. printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
  69. if (sub != 0)
  70. sub->compute_metrics(cramped_style(script_style(style)));
  71. if (sup != 0)
  72. sup->compute_metrics(script_style(style));
  73. // 18a
  74. if (p->is_char()) {
  75. printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
  76. printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
  77. }
  78. else {
  79. printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
  80. uid, p->uid, sup_drop);
  81. printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
  82. uid, p->uid, sub_drop);
  83. }
  84. printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
  85. if (sup == 0) {
  86. assert(sub != 0);
  87. // 18b
  88. printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
  89. HEIGHT_FORMAT "]-(%dM*4/5))\n",
  90. uid, uid, sub1, sub->uid, x_height);
  91. }
  92. else {
  93. // sup != 0
  94. // 18c
  95. int pos;
  96. if (style == DISPLAY_STYLE)
  97. pos = sup1;
  98. else if (style & 1) // not cramped
  99. pos = sup2;
  100. else
  101. pos = sup3;
  102. printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
  103. "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
  104. uid, uid, pos, sup->uid, x_height);
  105. // 18d
  106. if (sub != 0) {
  107. printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
  108. uid, uid, sub2);
  109. // 18e
  110. printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
  111. SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
  112. SUB_LOWER_FORMAT "]+(4*%dM)\n",
  113. sup->uid, uid, sub->uid, uid, default_rule_thickness);
  114. printf(".if \\n[" TEMP_REG "] \\{");
  115. printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
  116. printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
  117. "]+\\n[" DEPTH_FORMAT "]>?0\n",
  118. x_height, uid, sup->uid);
  119. printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
  120. printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
  121. printf(".\\}\n");
  122. }
  123. }
  124. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
  125. if (sub != 0 && sup != 0)
  126. printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
  127. WIDTH_FORMAT "])+%dM)>?0\n",
  128. sub->uid, p->uid, sup->uid, script_space);
  129. else if (sub != 0)
  130. printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
  131. sub->uid, p->uid, script_space);
  132. else if (sup != 0)
  133. printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
  134. else
  135. printf("\n");
  136. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
  137. uid, p->uid);
  138. if (sup != 0)
  139. printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
  140. uid, sup->uid);
  141. if (sub != 0)
  142. printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
  143. uid, sub->uid);
  144. printf("\n");
  145. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
  146. uid, p->uid);
  147. if (sub != 0)
  148. printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
  149. uid, sub->uid);
  150. if (sup != 0)
  151. printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
  152. uid, sup->uid);
  153. printf("\n");
  154. return res;
  155. }
  156. void script_box::output()
  157. {
  158. p->output();
  159. if (sup != 0) {
  160. printf("\\Z" DELIMITER_CHAR);
  161. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  162. printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
  163. sup->output();
  164. printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
  165. printf(DELIMITER_CHAR);
  166. }
  167. if (sub != 0) {
  168. printf("\\Z" DELIMITER_CHAR);
  169. printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
  170. printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
  171. printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
  172. sub->output();
  173. printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
  174. printf(DELIMITER_CHAR);
  175. }
  176. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
  177. uid, p->uid);
  178. }
  179. void script_box::hint(unsigned flags)
  180. {
  181. p->hint(flags & ~HINT_NEXT_IS_ITALIC);
  182. }
  183. void script_box::debug_print()
  184. {
  185. fprintf(stderr, "{ ");
  186. p->debug_print();
  187. fprintf(stderr, " }");
  188. if (sub) {
  189. fprintf(stderr, " sub { ");
  190. sub->debug_print();
  191. fprintf(stderr, " }");
  192. }
  193. if (sup) {
  194. fprintf(stderr, " sup { ");
  195. sup->debug_print();
  196. fprintf(stderr, " }");
  197. }
  198. }
  199. void script_box::check_tabs(int level)
  200. {
  201. if (sup)
  202. sup->check_tabs(level + 1);
  203. if (sub)
  204. sub->check_tabs(level + 1);
  205. p->check_tabs(level);
  206. }