home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / groff / eqn / box.cc next >
Encoding:
C/C++ Source or Header  |  1991-04-30  |  10.7 KB  |  554 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.uucp)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file LICENSE.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include "eqn.h"
  22. #include "pbox.h"
  23.  
  24. const char *current_roman_font;
  25.  
  26. char *gfont = 0;
  27. char *grfont = 0;
  28. char *gbfont = 0;
  29.  
  30. int gsize = 0;
  31. int script_size_reduction = -1;    // negative means reduce by a percentage 
  32.  
  33. int positive_space = -1;
  34. int negative_space = -1;
  35.  
  36. int minimum_size = 5;
  37.  
  38. int fat_offset = 4;
  39. int body_height = 75;
  40. int body_depth = 25;
  41.  
  42. int over_hang = 0;
  43. int accent_width = 31;
  44. int delimiter_factor = 900;
  45. int delimiter_shortfall = 50;
  46.  
  47. int null_delimiter_space = 12;
  48. int script_space = 5;
  49. int thin_space = 17;
  50. int medium_space = 22;
  51. int thick_space = 28;
  52.  
  53. int num1 = 70;
  54. int num2 = 40;
  55. // we don't use num3, because we don't have \atop
  56. int denom1 = 70;
  57. int denom2 = 36;
  58. int axis_height = 26;        // in 100ths of an em
  59. int sup1 = 42;
  60. int sup2 = 37;
  61. int sup3 = 28;
  62. int default_rule_thickness = 4;
  63. int sub1 = 20;
  64. int sub2 = 23;
  65. int sup_drop = 38;
  66. int sub_drop = 5;
  67. int x_height = 45;
  68. int big_op_spacing1 = 11;
  69. int big_op_spacing2 = 17;
  70. int big_op_spacing3 = 20;
  71. int big_op_spacing4 = 60;
  72. int big_op_spacing5 = 10;
  73.  
  74. // These are for piles and matrices.
  75.  
  76. int baseline_sep = 140;        // = num1 + denom1
  77. int shift_down = 26;        // = axis_height
  78. int column_sep = 100;        // = em space
  79. int matrix_side_sep = 17;    // = thin space
  80.  
  81.  
  82. struct {
  83.   const char *name;
  84.   int *ptr;
  85. } param_table[] = {
  86. "fat_offset", &fat_offset,
  87. "over_hang", &over_hang,
  88. "accent_width", &accent_width,
  89. "delimiter_factor", &delimiter_factor,
  90. "delimiter_shortfall", &delimiter_shortfall,
  91. "null_delimiter_space", &null_delimiter_space,
  92. "script_space", &script_space,
  93. "thin_space", &thin_space,
  94. "medium_space", &medium_space,
  95. "thick_space", &thick_space,
  96. "num1", &num1,
  97. "num2", &num2,
  98. "denom1", &denom1,
  99. "denom2", &denom2,
  100. "axis_height", &axis_height,
  101. "sup1", ¹,
  102. "sup2", ²,
  103. "sup3", ³,
  104. "default_rule_thickness", &default_rule_thickness,
  105. "sub1", &sub1,
  106. "sub2", &sub2,
  107. "sup_drop", &sup_drop,
  108. "sub_drop", &sub_drop,
  109. "x_height", &x_height,
  110. "big_op_spacing1", &big_op_spacing1,
  111. "big_op_spacing2", &big_op_spacing2,
  112. "big_op_spacing3", &big_op_spacing3,
  113. "big_op_spacing4", &big_op_spacing4,
  114. "big_op_spacing5", &big_op_spacing5,
  115. "minimum_size", &minimum_size,
  116. "baseline_sep", &baseline_sep,
  117. "shift_down", &shift_down,
  118. "column_sep", &column_sep,
  119. "matrix_side_sep", &matrix_side_sep,
  120. 0, 0
  121. };
  122.  
  123. void set_param(const char *name, int value)
  124. {
  125.   for (int i = 0; param_table[i].name != 0; i++)
  126.     if (strcmp(param_table[i].name, name) == 0) {
  127.       *param_table[i].ptr = value;
  128.       return;
  129.     }
  130.   error("unrecognised parameter `%1'", name);
  131. }
  132.  
  133. int script_style(int style)
  134. {
  135.   return style > SCRIPT_STYLE ? style - 2 : style;
  136. }
  137.  
  138. int cramped_style(int style)
  139. {
  140.   return (style & 1) ? style - 1 : style;
  141. }
  142.  
  143. void set_space(int n)
  144. {
  145.   if (n < 0)
  146.     negative_space = -n;
  147.   else
  148.     positive_space = n;
  149. }
  150.  
  151. void set_gsize(int n)
  152. {
  153.   gsize = n;
  154. }
  155.  
  156. void set_script_reduction(int n)
  157. {
  158.   script_size_reduction = n;
  159. }
  160.  
  161. const char *get_gfont()
  162. {
  163.   return gfont ? gfont : "I";
  164. }
  165.  
  166. const char *get_grfont()
  167. {
  168.   return grfont ? grfont : "R";
  169. }
  170.  
  171. const char *get_gbfont()
  172. {
  173.   return gbfont ? gbfont : "B";
  174. }
  175.  
  176. void set_gfont(const char *s)
  177. {
  178.   delete gfont;
  179.   gfont = strsave(s);
  180. }
  181.  
  182. void set_grfont(const char *s)
  183. {
  184.   delete grfont;
  185.   grfont = strsave(s);
  186. }
  187.  
  188. void set_gbfont(const char *s)
  189. {
  190.   delete gbfont;
  191.   gbfont = strsave(s);
  192. }
  193.  
  194. // this must be precisely 2 characters in length
  195. #define COMPATIBLE_REG "0C"
  196.  
  197. void start_string()
  198. {
  199.   printf(".nr " COMPATIBLE_REG " \\n(.C\n");
  200.   printf(".cp 0\n");
  201.   printf(".ds " LINE_STRING "\n");
  202. }
  203.  
  204. void output_string()
  205. {
  206.   printf("\\*[" LINE_STRING "]\n");
  207. }
  208.  
  209. void restore_compatibility()
  210. {
  211.   printf(".cp \\n(" COMPATIBLE_REG "\n");
  212. }
  213.  
  214. void do_text(const char *s)
  215. {
  216.   printf(".eo\n");
  217.   printf(".as " LINE_STRING " \"%s\n", s);
  218.   printf(".ec\n");
  219. }
  220.  
  221. void set_minimum_size(int n)
  222. {
  223.   minimum_size = n;
  224. }
  225.  
  226. void set_script_size()
  227. {
  228.   if (minimum_size < 0)
  229.     minimum_size = 0;
  230.   if (script_size_reduction >= 0)
  231.     printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size);
  232.   else
  233.     printf(".ps (u;\\n[.s]*7+5/10>?%d)*1z\n", minimum_size);
  234. }
  235.  
  236. int box::next_uid = 0;
  237.  
  238. box::box() : uid(next_uid++), spacing_type(ORDINARY_TYPE)
  239. {
  240. }
  241.  
  242. box::~box()
  243. {
  244. }
  245.  
  246. void box::top_level()
  247. {
  248.   // debug_print();
  249.   // putc('\n', stderr);
  250.   box *b = this;
  251.   printf(".nr " SAVED_FONT_REG " \\n[.f]\n");
  252.   printf(".ft %s\n", get_gfont());
  253.   if (gsize > 0)
  254.     b = new size_box(strsave(itoa(gsize)), b);
  255.   current_roman_font = get_grfont();
  256.   // This catches tabs used within \Z (which aren't allowed).
  257.   b->check_tabs(0);
  258.   int r = b->compute_metrics(DISPLAY_STYLE);
  259.   printf(".ft \\n[" SAVED_FONT_REG "]\n");
  260.   printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r);
  261.   if (r == FOUND_MARK) {
  262.     printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n");
  263.     printf(".nr " MARK_WIDTH_REG " \\n[" WIDTH_FORMAT "]\n", b->uid);
  264.   }
  265.   else if (r == FOUND_LINEUP)
  266.     printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
  267.        SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n");
  268.   else
  269.     assert(r == FOUND_NOTHING);
  270.   printf(".as " LINE_STRING " \\f[%s]", get_gfont());
  271.   current_roman_font = get_grfont();
  272.   b->output();
  273.   printf("\\f[\\n[" SAVED_FONT_REG "]]\n");
  274.   if (r == FOUND_LINEUP)
  275.     printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
  276.        MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n["
  277.        WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n",
  278.        b->uid);
  279.   b->extra_space();
  280.   if (!inline_flag)
  281.     printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n["
  282.        DEPTH_FORMAT "]u-%dM>?0)\n",
  283.        b->uid, body_height, b->uid, body_depth);
  284.   delete b;
  285.   next_uid = 0;
  286. }
  287.  
  288. // gpic defines this register so as to make geqn not produce `\x's
  289. #define EQN_NO_EXTRA_SPACE_REG "0x"
  290.  
  291. void box::extra_space()
  292. {
  293.   if (positive_space >= 0 || negative_space >= 0) {
  294.     if (positive_space > 0)
  295.       printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
  296.          ".as " LINE_STRING " \\x'-%dM'\n", positive_space);
  297.     if (negative_space > 0)
  298.       printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
  299.          ".as " LINE_STRING " \\x'%dM'\n", negative_space);
  300.     positive_space = negative_space = -1;
  301.   }
  302.   else {
  303.     printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
  304.        ".if \\n[" HEIGHT_FORMAT "]>%dM .as " LINE_STRING
  305.        " \\x'-(\\n[" HEIGHT_FORMAT
  306.        "]u-%dM)'\n",
  307.        uid, body_height, uid, body_height);
  308.     printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
  309.        ".if \\n[" DEPTH_FORMAT "]>%dM .as " LINE_STRING
  310.        " \\x'\\n[" DEPTH_FORMAT
  311.        "]u-%dM'\n",
  312.        uid, body_depth, uid, body_depth);
  313.   }
  314. }
  315.  
  316. int box::compute_metrics(int)
  317. {
  318.   printf(".nr " WIDTH_FORMAT " 0\n", uid);
  319.   printf(".nr " HEIGHT_FORMAT " 0\n", uid);
  320.   printf(".nr " DEPTH_FORMAT " 0\n", uid);
  321.   return FOUND_NOTHING;
  322. }
  323.  
  324. void box::compute_subscript_kern()
  325. {
  326.   printf(".nr " SUB_KERN_FORMAT " 0\n", uid);
  327. }
  328.  
  329. void box::compute_skew()
  330. {
  331.   printf(".nr " SKEW_FORMAT " 0\n", uid);
  332. }
  333.  
  334. void box::output()
  335. {
  336. }
  337.  
  338. void box::check_tabs(int)
  339. {
  340. }
  341.  
  342. int box::is_char()
  343. {
  344.   return 0;
  345. }
  346.  
  347. int box::left_is_italic()
  348. {
  349.   return 0;
  350. }
  351.  
  352. int box::right_is_italic()
  353. {
  354.   return 0;
  355. }
  356.  
  357. void box::hint(unsigned)
  358. {
  359. }
  360.   
  361. void box::handle_char_type(int, int)
  362. {
  363. }
  364.  
  365.  
  366. box_list::box_list(box *pp)
  367. {
  368.   p = new box*[10];
  369.   for (int i = 0; i < 10; i++)
  370.     p[i] = 0;
  371.   maxlen = 10;
  372.   len = 1;
  373.   p[0] = pp;
  374. }
  375.  
  376. void box_list::append(box *pp)
  377. {
  378.   if (len + 1 > maxlen) {
  379.     box **oldp = p;
  380.     maxlen *= 2;
  381.     p = new box*[maxlen];
  382.     memcpy(p, oldp, sizeof(box*)*len);
  383.     delete oldp;
  384.   }
  385.   p[len++] = pp;
  386. }
  387.  
  388. box_list::~box_list()
  389. {
  390.   for (int i = 0; i < len; i++)
  391.     delete p[i];
  392.   delete p;
  393. }
  394.  
  395. void box_list::list_check_tabs(int level)
  396. {
  397.   for (int i = 0; i < len; i++)
  398.     p[i]->check_tabs(level);
  399. }
  400.  
  401.  
  402. pointer_box::pointer_box(box *pp) : p(pp)
  403. {
  404.   spacing_type = p->spacing_type;
  405. }
  406.  
  407. pointer_box::~pointer_box()
  408. {
  409.   delete p;
  410. }
  411.  
  412. int pointer_box::compute_metrics(int style)
  413. {
  414.   int r = p->compute_metrics(style);
  415.   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
  416.   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
  417.   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  418.   return r;
  419. }
  420.  
  421. void pointer_box::compute_subscript_kern()
  422. {
  423.   p->compute_subscript_kern();
  424.   printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", uid, p->uid);
  425. }
  426.  
  427. void pointer_box::compute_skew()
  428. {
  429.   p->compute_skew();
  430.   printf(".nr " SKEW_FORMAT " \\n[" SKEW_FORMAT "]\n",
  431.      uid, p->uid);
  432. }
  433.  
  434. void pointer_box::check_tabs(int level)
  435. {
  436.   p->check_tabs(level);
  437. }
  438.  
  439. int simple_box::compute_metrics(int)
  440. {
  441.   printf(".nr " WIDTH_FORMAT " \\w" DELIMITER_CHAR, uid);
  442.   output();
  443.   printf(DELIMITER_CHAR "\n");
  444.   printf(".nr " HEIGHT_FORMAT " \\n[rst]>?0\n", uid);
  445.   printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?0\n", uid);
  446.   printf(".nr " SUB_KERN_FORMAT " 0-\\n[ssc]>?0\n", uid);
  447.   printf(".nr " SKEW_FORMAT " \\n[skw]\n", uid);
  448.   return FOUND_NOTHING;
  449. }
  450.  
  451. void simple_box::compute_subscript_kern()
  452. {
  453.   // do nothing, we already computed it in do_metrics
  454. }
  455.  
  456. void simple_box::compute_skew()
  457. {
  458.   // do nothing, we already computed it in do_metrics
  459. }
  460.  
  461. int box::is_simple()
  462. {
  463.   return 0;
  464. }
  465.  
  466. int simple_box::is_simple()
  467. {
  468.   return 1;
  469. }
  470.  
  471. quoted_text_box::quoted_text_box(char *s) : text(s)
  472. {
  473. }
  474.  
  475. quoted_text_box::~quoted_text_box()
  476. {
  477.   delete text;
  478. }
  479.  
  480. void quoted_text_box::output()
  481. {
  482.   if (text)
  483.     fputs(text, stdout);
  484. }
  485.  
  486. tab_box::tab_box() : disabled(0)
  487. {
  488. }
  489.  
  490. // We treat a tab_box as having width 0 for width computations.
  491.  
  492. void tab_box::output()
  493. {
  494.   if (!disabled)
  495.     printf("\\t");
  496. }
  497.  
  498. void tab_box::check_tabs(int level)
  499. {
  500.   if (level > 0) {
  501.     error("tabs allowed only at outermost level");
  502.     disabled = 1;
  503.   }
  504. }
  505.  
  506. space_box::space_box()
  507. {
  508.   spacing_type = SUPPRESS_TYPE;
  509. }
  510.  
  511. void space_box::output()
  512. {
  513.   printf("\\h'%dM'", thick_space);
  514. }
  515.  
  516. half_space_box::half_space_box()
  517. {
  518.   spacing_type = SUPPRESS_TYPE;
  519. }
  520.  
  521. void half_space_box::output()
  522. {
  523.   printf("\\h'%dM'", thin_space);
  524. }
  525.  
  526. void box_list::list_debug_print(const char *sep)
  527. {
  528.   p[0]->debug_print();
  529.   for (int i = 1; i < len; i++) {
  530.     fprintf(stderr, "%s", sep);
  531.     p[i]->debug_print();
  532.   }
  533. }
  534.  
  535. void quoted_text_box::debug_print()
  536. {
  537.   fprintf(stderr, "\"%s\"", (text ? text : ""));
  538. }
  539.  
  540. void half_space_box::debug_print()
  541. {
  542.   fprintf(stderr, "^");
  543. }
  544.  
  545. void space_box::debug_print()
  546. {
  547.   fprintf(stderr, "~");
  548. }
  549.  
  550. void tab_box::debug_print()
  551. {
  552.   fprintf(stderr, "<tab>");
  553. }
  554.