home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / eqn / script.cc < prev    next >
C/C++ Source or Header  |  1995-06-22  |  6KB  |  222 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  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 2, 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 COPYING.  If not, write to the Free Software
  19. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  20.  
  21. #include "eqn.h"
  22. #include "pbox.h"
  23.  
  24. class script_box : public pointer_box {
  25. private:
  26.   box *sub;
  27.   box *sup;
  28. public:
  29.   script_box(box *, box *, box *);
  30.   ~script_box();
  31.   int compute_metrics(int);
  32.   void output();
  33.   void debug_print();
  34.   int left_is_italic();
  35.   void hint(unsigned);
  36.   void check_tabs(int);
  37. };
  38.  
  39. /* The idea is that the script should attach to the rightmost box
  40. of a list. For example, given `2x sup 3', the superscript should
  41. attach to `x' rather than `2x'. */
  42.  
  43. box *make_script_box(box *nuc, box *sub, box *sup)
  44. {
  45.   list_box *b = nuc->to_list_box();
  46.   if (b != 0) {
  47.     b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
  48.                            sub,
  49.                            sup);
  50.     return b;
  51.   }
  52.   else
  53.     return new script_box(nuc, sub, sup);
  54. }
  55.  
  56. script_box::script_box(box *pp, box *qq, box *rr)
  57. : pointer_box(pp), sub(qq), sup(rr)
  58. {
  59. }
  60.  
  61. script_box::~script_box()
  62. {
  63.   delete sub;
  64.   delete sup;
  65. }
  66.  
  67. int script_box::left_is_italic()
  68. {
  69.   return p->left_is_italic();
  70. }
  71.  
  72. int script_box::compute_metrics(int style)
  73. {
  74.   int res = p->compute_metrics(style);
  75.   p->compute_subscript_kern();
  76.   printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
  77.   if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
  78.     set_script_size();
  79.   printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
  80.   if (sub != 0)
  81.     sub->compute_metrics(cramped_style(script_style(style)));
  82.   if (sup != 0)
  83.     sup->compute_metrics(script_style(style));
  84.   // 18a
  85.   if (p->is_char()) {
  86.     printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
  87.     printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
  88.   }
  89.   else {
  90.     printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
  91.        uid, p->uid, sup_drop);
  92.     printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
  93.        uid, p->uid, sub_drop);
  94.   }
  95.   printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
  96.   if (sup == 0) {
  97.     assert(sub != 0);
  98.     // 18b
  99.     printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
  100.        HEIGHT_FORMAT "]-(%dM*4/5))\n",
  101.        uid, uid, sub1, sub->uid, x_height);
  102.   }
  103.   else {
  104.     // sup != 0
  105.     // 18c
  106.     int p;
  107.     if (style == DISPLAY_STYLE)
  108.       p = sup1;
  109.     else if (style & 1)        // not cramped
  110.       p = sup2;
  111.     else
  112.       p = sup3;
  113.     printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
  114.        "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
  115.        uid, uid, p, sup->uid, x_height);
  116.     // 18d
  117.     if (sub != 0) {
  118.       printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
  119.        uid, uid, sub2);
  120.       // 18e
  121.       printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
  122.          SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
  123.          SUB_LOWER_FORMAT "]+(4*%dM)\n",
  124.          sup->uid, uid, sub->uid, uid, default_rule_thickness);
  125.       printf(".if \\n[" TEMP_REG "] \\{");
  126.       printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
  127.       printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
  128.          "]+\\n[" DEPTH_FORMAT "]>?0\n",
  129.          x_height, uid, sup->uid);
  130.       printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
  131.       printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
  132.       printf(".\\}\n");
  133.     }
  134.   }
  135.   printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
  136.   if (sub != 0 && sup != 0)
  137.     printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
  138.        WIDTH_FORMAT "])+%dM)>?0\n",
  139.        sub->uid, p->uid, sup->uid, script_space);
  140.   else if (sub != 0)
  141.     printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
  142.        sub->uid, p->uid, script_space);
  143.   else if (sup != 0)
  144.     printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
  145.   else
  146.     printf("\n");
  147.   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
  148.      uid, p->uid);
  149.   if (sup != 0)
  150.     printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
  151.        uid, sup->uid);
  152.   if (sub != 0)
  153.     printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
  154.        uid, sub->uid);
  155.   printf("\n");
  156.   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
  157.      uid, p->uid);
  158.   if (sub != 0)
  159.     printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
  160.        uid, sub->uid);
  161.   if (sup != 0)
  162.     printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
  163.        uid, sup->uid);
  164.   printf("\n");
  165.   return res;
  166. }
  167.  
  168. void script_box::output()
  169. {
  170.   p->output();
  171.   if (sup != 0) {
  172.     printf("\\Z" DELIMITER_CHAR);
  173.     printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  174.     printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
  175.     sup->output();
  176.     printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
  177.     printf(DELIMITER_CHAR);
  178.   }
  179.   if (sub != 0) {
  180.     printf("\\Z" DELIMITER_CHAR);
  181.     printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
  182.     printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
  183.     printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
  184.     sub->output();
  185.     printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
  186.     printf(DELIMITER_CHAR);
  187.   }
  188.   printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
  189.      uid, p->uid);
  190. }
  191.  
  192. void script_box::hint(unsigned flags)
  193. {
  194.   p->hint(flags & ~HINT_NEXT_IS_ITALIC);
  195. }
  196.  
  197. void script_box::debug_print()
  198. {
  199.   fprintf(stderr, "{ ");
  200.   p->debug_print();
  201.   fprintf(stderr, " }");
  202.   if (sub) {
  203.     fprintf(stderr, " sub { ");
  204.     sub->debug_print();
  205.     fprintf(stderr, " }");
  206.   }
  207.   if (sup) {
  208.     fprintf(stderr, " sup { ");
  209.     sup->debug_print();
  210.     fprintf(stderr, " }");
  211.   }
  212. }
  213.  
  214. void script_box::check_tabs(int level)
  215. {
  216.   if (sup)
  217.     sup->check_tabs(level + 1);
  218.   if (sub)
  219.     sub->check_tabs(level + 1);
  220.   p->check_tabs(level);
  221. }
  222.