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

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 293 lines · 249 code · 20 blank · 24 comment · 35 complexity · dc8ad411300a1ab51ee1d3129bf2e096 MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
  3. Written by James Clark (jjc@jclark.com)
  4. This file is part of groff.
  5. groff is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 2, or (at your option) any later
  8. version.
  9. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License along
  14. with groff; see the file COPYING. If not, write to the Free Software
  15. Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
  16. // piles and matrices
  17. #include "eqn.h"
  18. #include "pbox.h"
  19. // SUP_RAISE_FORMAT gives the first baseline
  20. // BASELINE_SEP_FORMAT gives the separation between baselines
  21. int pile_box::compute_metrics(int style)
  22. {
  23. int i;
  24. for (i = 0; i < col.len; i++)
  25. col.p[i]->compute_metrics(style);
  26. printf(".nr " WIDTH_FORMAT " 0", uid);
  27. for (i = 0; i < col.len; i++)
  28. printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
  29. printf("\n");
  30. printf(".nr " BASELINE_SEP_FORMAT " %dM",
  31. uid, baseline_sep+col.space);
  32. for (i = 1; i < col.len; i++)
  33. printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
  34. col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
  35. // round it so that it's a multiple of the vertical resolution
  36. printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
  37. printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
  38. "+%dM\n",
  39. uid, uid, col.len-1, axis_height - shift_down);
  40. printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
  41. HEIGHT_FORMAT "]\n",
  42. uid, uid, col.p[0]->uid);
  43. printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
  44. DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
  45. uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
  46. return FOUND_NOTHING;
  47. }
  48. void pile_box::output()
  49. {
  50. int i;
  51. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  52. for (i = 0; i < col.len; i++) {
  53. switch (col.align) {
  54. case LEFT_ALIGN:
  55. break;
  56. case CENTER_ALIGN:
  57. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
  58. uid, col.p[i]->uid);
  59. break;
  60. case RIGHT_ALIGN:
  61. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
  62. uid, col.p[i]->uid);
  63. break;
  64. default:
  65. assert(0);
  66. }
  67. col.p[i]->output();
  68. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
  69. switch (col.align) {
  70. case LEFT_ALIGN:
  71. break;
  72. case CENTER_ALIGN:
  73. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
  74. col.p[i]->uid, uid);
  75. break;
  76. case RIGHT_ALIGN:
  77. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
  78. col.p[i]->uid, uid);
  79. break;
  80. default:
  81. assert(0);
  82. }
  83. if (i != col.len - 1)
  84. printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
  85. }
  86. printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
  87. printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
  88. printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
  89. }
  90. pile_box::pile_box(box *pp) : col(pp)
  91. {
  92. }
  93. void pile_box::check_tabs(int level)
  94. {
  95. col.list_check_tabs(level);
  96. }
  97. void pile_box::debug_print()
  98. {
  99. col.debug_print("pile");
  100. }
  101. int matrix_box::compute_metrics(int style)
  102. {
  103. int i, j;
  104. int max_len = 0;
  105. int space = 0;
  106. for (i = 0; i < len; i++) {
  107. for (j = 0; j < p[i]->len; j++)
  108. p[i]->p[j]->compute_metrics(style);
  109. if (p[i]->len > max_len)
  110. max_len = p[i]->len;
  111. if (p[i]->space > space)
  112. space = p[i]->space;
  113. }
  114. for (i = 0; i < len; i++) {
  115. printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
  116. for (j = 0; j < p[i]->len; j++)
  117. printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
  118. printf("\n");
  119. }
  120. printf(".nr " WIDTH_FORMAT " %dM",
  121. uid, column_sep*(len-1)+2*matrix_side_sep);
  122. for (i = 0; i < len; i++)
  123. printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
  124. printf("\n");
  125. printf(".nr " BASELINE_SEP_FORMAT " %dM",
  126. uid, baseline_sep+space);
  127. for (i = 0; i < len; i++)
  128. for (j = 1; j < p[i]->len; j++)
  129. printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
  130. p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
  131. // round it so that it's a multiple of the vertical resolution
  132. printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
  133. printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
  134. "+%dM\n",
  135. uid, uid, max_len-1, axis_height - shift_down);
  136. printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
  137. uid, uid);
  138. for (i = 0; i < len; i++)
  139. printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
  140. printf(")>?0\n");
  141. printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
  142. SUP_RAISE_FORMAT "]+(0",
  143. uid, uid, max_len-1, uid);
  144. for (i = 0; i < len; i++)
  145. if (p[i]->len == max_len)
  146. printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
  147. printf(")>?0\n");
  148. return FOUND_NOTHING;
  149. }
  150. void matrix_box::output()
  151. {
  152. printf("\\h'%dM'", matrix_side_sep);
  153. for (int i = 0; i < len; i++) {
  154. int j;
  155. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  156. for (j = 0; j < p[i]->len; j++) {
  157. switch (p[i]->align) {
  158. case LEFT_ALIGN:
  159. break;
  160. case CENTER_ALIGN:
  161. printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
  162. uid, i, p[i]->p[j]->uid);
  163. break;
  164. case RIGHT_ALIGN:
  165. printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
  166. uid, i, p[i]->p[j]->uid);
  167. break;
  168. default:
  169. assert(0);
  170. }
  171. p[i]->p[j]->output();
  172. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
  173. switch (p[i]->align) {
  174. case LEFT_ALIGN:
  175. break;
  176. case CENTER_ALIGN:
  177. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
  178. p[i]->p[j]->uid, uid, i);
  179. break;
  180. case RIGHT_ALIGN:
  181. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
  182. p[i]->p[j]->uid, uid, i);
  183. break;
  184. default:
  185. assert(0);
  186. }
  187. if (j != p[i]->len - 1)
  188. printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
  189. }
  190. printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
  191. printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
  192. printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
  193. if (i != len - 1)
  194. printf("\\h'%dM'", column_sep);
  195. }
  196. printf("\\h'%dM'", matrix_side_sep);
  197. }
  198. matrix_box::matrix_box(column *pp)
  199. {
  200. p = new column*[10];
  201. for (int i = 0; i < 10; i++)
  202. p[i] = 0;
  203. maxlen = 10;
  204. len = 1;
  205. p[0] = pp;
  206. }
  207. matrix_box::~matrix_box()
  208. {
  209. for (int i = 0; i < len; i++)
  210. delete p[i];
  211. a_delete p;
  212. }
  213. void matrix_box::append(column *pp)
  214. {
  215. if (len + 1 > maxlen) {
  216. column **oldp = p;
  217. maxlen *= 2;
  218. p = new column*[maxlen];
  219. memcpy(p, oldp, sizeof(column*)*len);
  220. a_delete oldp;
  221. }
  222. p[len++] = pp;
  223. }
  224. void matrix_box::check_tabs(int level)
  225. {
  226. for (int i = 0; i < len; i++)
  227. p[i]->list_check_tabs(level);
  228. }
  229. void matrix_box::debug_print()
  230. {
  231. fprintf(stderr, "matrix { ");
  232. p[0]->debug_print("col");
  233. for (int i = 1; i < len; i++) {
  234. fprintf(stderr, " ");
  235. p[i]->debug_print("col");
  236. }
  237. fprintf(stderr, " }");
  238. }
  239. column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
  240. {
  241. }
  242. void column::set_alignment(alignment a)
  243. {
  244. align = a;
  245. }
  246. void column::set_space(int n)
  247. {
  248. space = n;
  249. }
  250. void column::debug_print(const char *s)
  251. {
  252. char c = '\0'; // shut up -Wall
  253. switch (align) {
  254. case LEFT_ALIGN:
  255. c = 'l';
  256. break;
  257. case RIGHT_ALIGN:
  258. c = 'r';
  259. break;
  260. case CENTER_ALIGN:
  261. c = 'c';
  262. break;
  263. default:
  264. assert(0);
  265. }
  266. fprintf(stderr, "%c%s %d { ", c, s, space);
  267. list_debug_print(" above ");
  268. fprintf(stderr, " }");
  269. }