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

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 197 lines · 144 code · 19 blank · 34 comment · 11 complexity · a54d8b379384aabf99abe13f0cfe7db8 MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
  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 over_box : public box {
  20. private:
  21. int reduce_size;
  22. box *num;
  23. box *den;
  24. public:
  25. over_box(int small, box *, box *);
  26. ~over_box();
  27. void debug_print();
  28. int compute_metrics(int);
  29. void output();
  30. void check_tabs(int);
  31. };
  32. box *make_over_box(box *pp, box *qq)
  33. {
  34. return new over_box(0, pp, qq);
  35. }
  36. box *make_small_over_box(box *pp, box *qq)
  37. {
  38. return new over_box(1, pp, qq);
  39. }
  40. over_box::over_box(int is_small, box *pp, box *qq)
  41. : reduce_size(is_small), num(pp), den(qq)
  42. {
  43. spacing_type = INNER_TYPE;
  44. }
  45. over_box::~over_box()
  46. {
  47. delete num;
  48. delete den;
  49. }
  50. int over_box::compute_metrics(int style)
  51. {
  52. if (reduce_size) {
  53. style = script_style(style);
  54. printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
  55. set_script_size();
  56. printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
  57. }
  58. int mark_uid = 0;
  59. int res = num->compute_metrics(style);
  60. if (res)
  61. mark_uid = num->uid;
  62. int r = den->compute_metrics(cramped_style(style));
  63. if (r && res)
  64. error("multiple marks and lineups");
  65. else {
  66. mark_uid = den->uid;
  67. res = r;
  68. }
  69. if (reduce_size)
  70. printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
  71. printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
  72. uid, num->uid, den->uid);
  73. // allow for \(ru being wider than both the numerator and denominator
  74. if (!draw_flag)
  75. fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
  76. printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
  77. // 15b
  78. printf(".nr " SUP_RAISE_FORMAT " %dM\n",
  79. uid, (reduce_size ? num2 : num1));
  80. printf(".nr " SUB_LOWER_FORMAT " %dM\n",
  81. uid, (reduce_size ? denom2 : denom1));
  82. // 15d
  83. printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
  84. "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
  85. uid, num->uid, uid, axis_height, default_rule_thickness,
  86. default_rule_thickness*(reduce_size ? 1 : 3));
  87. printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
  88. "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
  89. uid, den->uid, uid, axis_height, default_rule_thickness,
  90. default_rule_thickness*(reduce_size ? 1 : 3));
  91. printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
  92. HEIGHT_FORMAT "]\n",
  93. uid, uid, num->uid);
  94. printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
  95. DEPTH_FORMAT "]\n",
  96. uid, uid, den->uid);
  97. if (res)
  98. printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
  99. WIDTH_FORMAT "]/2)\n", uid, mark_uid);
  100. return res;
  101. }
  102. #define USE_Z
  103. void over_box::output()
  104. {
  105. if (reduce_size)
  106. printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
  107. #ifdef USE_Z
  108. printf("\\Z" DELIMITER_CHAR);
  109. #endif
  110. // move up to the numerator baseline
  111. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  112. // move across so that it's centered
  113. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
  114. uid, num->uid);
  115. // print the numerator
  116. num->output();
  117. #ifdef USE_Z
  118. printf(DELIMITER_CHAR);
  119. #else
  120. // back again
  121. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
  122. printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
  123. uid, num->uid);
  124. // down again
  125. printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
  126. #endif
  127. #ifdef USE_Z
  128. printf("\\Z" DELIMITER_CHAR);
  129. #endif
  130. // move down to the denominator baseline
  131. printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
  132. // move across so that it's centered
  133. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
  134. uid, den->uid);
  135. // print the the denominator
  136. den->output();
  137. #ifdef USE_Z
  138. printf(DELIMITER_CHAR);
  139. #else
  140. // back again
  141. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
  142. printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
  143. uid, den->uid);
  144. // up again
  145. printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
  146. #endif
  147. if (reduce_size)
  148. printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
  149. // draw the line
  150. printf("\\h'%dM'", null_delimiter_space);
  151. printf("\\v'-%dM'", axis_height);
  152. fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
  153. printf("\\n[" WIDTH_FORMAT "]u-%dM",
  154. uid, 2*null_delimiter_space);
  155. fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
  156. printf("\\v'%dM'", axis_height);
  157. printf("\\h'%dM'", null_delimiter_space);
  158. }
  159. void over_box::debug_print()
  160. {
  161. fprintf(stderr, "{ ");
  162. num->debug_print();
  163. if (reduce_size)
  164. fprintf(stderr, " } smallover { ");
  165. else
  166. fprintf(stderr, " } over { ");
  167. den->debug_print();
  168. fprintf(stderr, " }");
  169. }
  170. void over_box::check_tabs(int level)
  171. {
  172. num->check_tabs(level + 1);
  173. den->check_tabs(level + 1);
  174. }