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

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 601 lines · 499 code · 75 blank · 27 comment · 11 complexity · 106f6386de855514a8f2717353525ade MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2002 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. #include "eqn.h"
  17. #include "pbox.h"
  18. class accent_box : public pointer_box {
  19. private:
  20. box *ab;
  21. public:
  22. accent_box(box *, box *);
  23. ~accent_box();
  24. int compute_metrics(int);
  25. void output();
  26. void debug_print();
  27. void check_tabs(int);
  28. };
  29. box *make_accent_box(box *p, box *q)
  30. {
  31. return new accent_box(p, q);
  32. }
  33. accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq)
  34. {
  35. }
  36. accent_box::~accent_box()
  37. {
  38. delete ab;
  39. }
  40. #if 0
  41. int accent_box::compute_metrics(int style)
  42. {
  43. int r = p->compute_metrics(style);
  44. p->compute_skew();
  45. ab->compute_metrics(style);
  46. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  47. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  48. printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
  49. uid, p->uid, x_height);
  50. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
  51. SUP_RAISE_FORMAT "]\n",
  52. uid, ab->uid, uid);
  53. return r;
  54. }
  55. void accent_box::output()
  56. {
  57. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
  58. SKEW_FORMAT "]u'",
  59. p->uid, ab->uid, p->uid);
  60. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  61. ab->output();
  62. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid);
  63. printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
  64. printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
  65. SKEW_FORMAT "]u)'",
  66. p->uid, ab->uid, p->uid);
  67. p->output();
  68. }
  69. #endif
  70. /* This version copes with the possibility of an accent's being wider
  71. than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
  72. left edge of the resulting box to the middle of the accentee's box.*/
  73. int accent_box::compute_metrics(int style)
  74. {
  75. int r = p->compute_metrics(style);
  76. p->compute_skew();
  77. ab->compute_metrics(style);
  78. printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
  79. ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n",
  80. uid, p->uid, ab->uid, p->uid);
  81. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
  82. ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])"
  83. "+\\n[" LEFT_WIDTH_FORMAT "]\n",
  84. uid, p->uid, ab->uid, p->uid, uid);
  85. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  86. printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
  87. uid, p->uid, x_height);
  88. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
  89. SUP_RAISE_FORMAT "]\n",
  90. uid, ab->uid, uid);
  91. if (r)
  92. printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
  93. "-(\\n[" WIDTH_FORMAT "]/2)'\n",
  94. uid, p->uid);
  95. return r;
  96. }
  97. void accent_box::output()
  98. {
  99. printf("\\Z" DELIMITER_CHAR);
  100. printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u"
  101. "-(\\n[" WIDTH_FORMAT "]u/2u)'",
  102. uid, p->uid, ab->uid);
  103. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  104. ab->output();
  105. printf(DELIMITER_CHAR);
  106. printf("\\Z" DELIMITER_CHAR);
  107. printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
  108. uid, p->uid);
  109. p->output();
  110. printf(DELIMITER_CHAR);
  111. printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
  112. }
  113. void accent_box::check_tabs(int level)
  114. {
  115. ab->check_tabs(level + 1);
  116. p->check_tabs(level + 1);
  117. }
  118. void accent_box::debug_print()
  119. {
  120. fprintf(stderr, "{ ");
  121. p->debug_print();
  122. fprintf(stderr, " } accent { ");
  123. ab->debug_print();
  124. fprintf(stderr, " }");
  125. }
  126. class overline_char_box : public simple_box {
  127. public:
  128. overline_char_box();
  129. void output();
  130. void debug_print();
  131. };
  132. overline_char_box::overline_char_box()
  133. {
  134. }
  135. void overline_char_box::output()
  136. {
  137. printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
  138. printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
  139. accent_width);
  140. printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
  141. }
  142. void overline_char_box::debug_print()
  143. {
  144. fprintf(stderr, "<overline char>");
  145. }
  146. class overline_box : public pointer_box {
  147. public:
  148. overline_box(box *);
  149. int compute_metrics(int);
  150. void output();
  151. void debug_print();
  152. };
  153. box *make_overline_box(box *p)
  154. {
  155. if (p->is_char())
  156. return new accent_box(p, new overline_char_box);
  157. else
  158. return new overline_box(p);
  159. }
  160. overline_box::overline_box(box *pp) : pointer_box(pp)
  161. {
  162. }
  163. int overline_box::compute_metrics(int style)
  164. {
  165. int r = p->compute_metrics(cramped_style(style));
  166. // 9
  167. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
  168. uid, p->uid, default_rule_thickness*5);
  169. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  170. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  171. return r;
  172. }
  173. void overline_box::output()
  174. {
  175. // 9
  176. printf("\\Z" DELIMITER_CHAR);
  177. printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
  178. p->uid, 7*default_rule_thickness);
  179. if (draw_flag)
  180. printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
  181. else
  182. printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
  183. printf(DELIMITER_CHAR);
  184. p->output();
  185. }
  186. void overline_box::debug_print()
  187. {
  188. fprintf(stderr, "{ ");
  189. p->debug_print();
  190. fprintf(stderr, " } bar");
  191. }
  192. class uaccent_box : public pointer_box {
  193. box *ab;
  194. public:
  195. uaccent_box(box *, box *);
  196. ~uaccent_box();
  197. int compute_metrics(int);
  198. void output();
  199. void compute_subscript_kern();
  200. void check_tabs(int);
  201. void debug_print();
  202. };
  203. box *make_uaccent_box(box *p, box *q)
  204. {
  205. return new uaccent_box(p, q);
  206. }
  207. uaccent_box::uaccent_box(box *pp, box *qq)
  208. : pointer_box(pp), ab(qq)
  209. {
  210. }
  211. uaccent_box::~uaccent_box()
  212. {
  213. delete ab;
  214. }
  215. int uaccent_box::compute_metrics(int style)
  216. {
  217. int r = p->compute_metrics(style);
  218. ab->compute_metrics(style);
  219. printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
  220. ">?(\\n[" WIDTH_FORMAT "]/2)\n",
  221. uid, p->uid, ab->uid);
  222. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
  223. ">?(\\n[" WIDTH_FORMAT "]/2)"
  224. "+\\n[" LEFT_WIDTH_FORMAT "]\n",
  225. uid, p->uid, ab->uid, uid);
  226. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  227. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
  228. "+\\n[" DEPTH_FORMAT "]\n",
  229. uid, p->uid, ab->uid);
  230. if (r)
  231. printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
  232. "-(\\n[" WIDTH_FORMAT "]/2)'\n",
  233. uid, p->uid);
  234. return r;
  235. }
  236. void uaccent_box::output()
  237. {
  238. printf("\\Z" DELIMITER_CHAR);
  239. printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
  240. uid, ab->uid);
  241. printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
  242. ab->output();
  243. printf(DELIMITER_CHAR);
  244. printf("\\Z" DELIMITER_CHAR);
  245. printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
  246. uid, p->uid);
  247. p->output();
  248. printf(DELIMITER_CHAR);
  249. printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
  250. }
  251. void uaccent_box::check_tabs(int level)
  252. {
  253. ab->check_tabs(level + 1);
  254. p->check_tabs(level + 1);
  255. }
  256. void uaccent_box::compute_subscript_kern()
  257. {
  258. box::compute_subscript_kern(); // want 0 subscript kern
  259. }
  260. void uaccent_box::debug_print()
  261. {
  262. fprintf(stderr, "{ ");
  263. p->debug_print();
  264. fprintf(stderr, " } uaccent { ");
  265. ab->debug_print();
  266. fprintf(stderr, " }");
  267. }
  268. class underline_char_box : public simple_box {
  269. public:
  270. underline_char_box();
  271. void output();
  272. void debug_print();
  273. };
  274. underline_char_box::underline_char_box()
  275. {
  276. }
  277. void underline_char_box::output()
  278. {
  279. printf("\\v'%dM/2u'", 7*default_rule_thickness);
  280. printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
  281. accent_width);
  282. printf("\\v'-%dM/2u'", 7*default_rule_thickness);
  283. }
  284. void underline_char_box::debug_print()
  285. {
  286. fprintf(stderr, "<underline char>");
  287. }
  288. class underline_box : public pointer_box {
  289. public:
  290. underline_box(box *);
  291. int compute_metrics(int);
  292. void output();
  293. void compute_subscript_kern();
  294. void debug_print();
  295. };
  296. box *make_underline_box(box *p)
  297. {
  298. if (p->is_char())
  299. return new uaccent_box(p, new underline_char_box);
  300. else
  301. return new underline_box(p);
  302. }
  303. underline_box::underline_box(box *pp) : pointer_box(pp)
  304. {
  305. }
  306. int underline_box::compute_metrics(int style)
  307. {
  308. int r = p->compute_metrics(style);
  309. // 10
  310. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
  311. uid, p->uid, default_rule_thickness*5);
  312. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  313. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  314. return r;
  315. }
  316. void underline_box::output()
  317. {
  318. // 10
  319. printf("\\Z" DELIMITER_CHAR);
  320. printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
  321. p->uid, 7*default_rule_thickness);
  322. if (draw_flag)
  323. printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
  324. else
  325. printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
  326. printf(DELIMITER_CHAR);
  327. p->output();
  328. }
  329. // we want an underline box to have 0 subscript kern
  330. void underline_box::compute_subscript_kern()
  331. {
  332. box::compute_subscript_kern();
  333. }
  334. void underline_box::debug_print()
  335. {
  336. fprintf(stderr, "{ ");
  337. p->debug_print();
  338. fprintf(stderr, " } under");
  339. }
  340. size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s)
  341. {
  342. }
  343. int size_box::compute_metrics(int style)
  344. {
  345. printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
  346. printf(".ps %s\n", size);
  347. printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
  348. int r = p->compute_metrics(style);
  349. printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
  350. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  351. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  352. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  353. return r;
  354. }
  355. void size_box::output()
  356. {
  357. printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
  358. p->output();
  359. printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
  360. }
  361. size_box::~size_box()
  362. {
  363. a_delete size;
  364. }
  365. void size_box::debug_print()
  366. {
  367. fprintf(stderr, "size %s { ", size);
  368. p->debug_print();
  369. fprintf(stderr, " }");
  370. }
  371. font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
  372. {
  373. }
  374. font_box::~font_box()
  375. {
  376. a_delete f;
  377. }
  378. int font_box::compute_metrics(int style)
  379. {
  380. const char *old_roman_font = current_roman_font;
  381. current_roman_font = f;
  382. printf(".nr " FONT_FORMAT " \\n[.f]\n", uid);
  383. printf(".ft %s\n", f);
  384. int r = p->compute_metrics(style);
  385. current_roman_font = old_roman_font;
  386. printf(".ft \\n[" FONT_FORMAT "]\n", uid);
  387. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  388. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  389. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  390. return r;
  391. }
  392. void font_box::output()
  393. {
  394. printf("\\f[%s]", f);
  395. const char *old_roman_font = current_roman_font;
  396. current_roman_font = f;
  397. p->output();
  398. current_roman_font = old_roman_font;
  399. printf("\\f[\\n[" FONT_FORMAT "]]", uid);
  400. }
  401. void font_box::debug_print()
  402. {
  403. fprintf(stderr, "font %s { ", f);
  404. p->debug_print();
  405. fprintf(stderr, " }");
  406. }
  407. fat_box::fat_box(box *pp) : pointer_box(pp)
  408. {
  409. }
  410. int fat_box::compute_metrics(int style)
  411. {
  412. int r = p->compute_metrics(style);
  413. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
  414. uid, p->uid, fat_offset);
  415. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  416. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  417. return r;
  418. }
  419. void fat_box::output()
  420. {
  421. p->output();
  422. printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
  423. printf("\\h'%dM'", fat_offset);
  424. p->output();
  425. }
  426. void fat_box::debug_print()
  427. {
  428. fprintf(stderr, "fat { ");
  429. p->debug_print();
  430. fprintf(stderr, " }");
  431. }
  432. vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i)
  433. {
  434. }
  435. int vmotion_box::compute_metrics(int style)
  436. {
  437. int r = p->compute_metrics(style);
  438. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  439. if (n > 0) {
  440. printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
  441. uid, n, p->uid);
  442. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  443. }
  444. else {
  445. printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
  446. uid, -n, p->uid);
  447. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
  448. uid, p->uid);
  449. }
  450. return r;
  451. }
  452. void vmotion_box::output()
  453. {
  454. printf("\\v'%dM'", -n);
  455. p->output();
  456. printf("\\v'%dM'", n);
  457. }
  458. void vmotion_box::debug_print()
  459. {
  460. if (n >= 0)
  461. fprintf(stderr, "up %d { ", n);
  462. else
  463. fprintf(stderr, "down %d { ", -n);
  464. p->debug_print();
  465. fprintf(stderr, " }");
  466. }
  467. hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i)
  468. {
  469. }
  470. int hmotion_box::compute_metrics(int style)
  471. {
  472. int r = p->compute_metrics(style);
  473. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
  474. uid, p->uid, n);
  475. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  476. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  477. if (r)
  478. printf(".nr " MARK_REG " +%dM\n", n);
  479. return r;
  480. }
  481. void hmotion_box::output()
  482. {
  483. printf("\\h'%dM'", n);
  484. p->output();
  485. }
  486. void hmotion_box::debug_print()
  487. {
  488. if (n >= 0)
  489. fprintf(stderr, "fwd %d { ", n);
  490. else
  491. fprintf(stderr, "back %d { ", -n);
  492. p->debug_print();
  493. fprintf(stderr, " }");
  494. }
  495. vcenter_box::vcenter_box(box *pp) : pointer_box(pp)
  496. {
  497. }
  498. int vcenter_box::compute_metrics(int style)
  499. {
  500. int r = p->compute_metrics(style);
  501. printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  502. printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
  503. HEIGHT_FORMAT "]/2+%dM\n",
  504. uid, p->uid, p->uid, axis_height);
  505. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
  506. SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
  507. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
  508. SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
  509. return r;
  510. }
  511. void vcenter_box::output()
  512. {
  513. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  514. p->output();
  515. printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
  516. }
  517. void vcenter_box::debug_print()
  518. {
  519. fprintf(stderr, "vcenter { ");
  520. p->debug_print();
  521. fprintf(stderr, " }");
  522. }