1114402Sru// -*- C++ -*-
2114402Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
3114402Sru   Free Software Foundation, Inc.
4114402Sru     Written by James Clark (jjc@jclark.com)
5114402Sru
6114402SruThis file is part of groff.
7114402Sru
8114402Srugroff is free software; you can redistribute it and/or modify it under
9114402Sruthe terms of the GNU General Public License as published by the Free
10114402SruSoftware Foundation; either version 2, or (at your option) any later
11114402Sruversion.
12114402Sru
13114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
14114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
15114402SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16114402Srufor more details.
17114402Sru
18114402SruYou should have received a copy of the GNU General Public License along
19114402Sruwith groff; see the file COPYING.  If not, write to the Free Software
20151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21114402Sru
22114402Sru#include "eqn.h"
23114402Sru#include "pbox.h"
24114402Sru
25114402Sruclass over_box : public box {
26114402Sruprivate:
27114402Sru  int reduce_size;
28114402Sru  box *num;
29114402Sru  box *den;
30114402Srupublic:
31114402Sru  over_box(int small, box *, box *);
32114402Sru  ~over_box();
33114402Sru  void debug_print();
34114402Sru  int compute_metrics(int);
35114402Sru  void output();
36114402Sru  void check_tabs(int);
37114402Sru};
38114402Sru
39114402Srubox *make_over_box(box *pp, box *qq)
40114402Sru{
41114402Sru  return new over_box(0, pp, qq);
42114402Sru}
43114402Sru
44114402Srubox *make_small_over_box(box *pp, box *qq)
45114402Sru{
46114402Sru  return new over_box(1, pp, qq);
47114402Sru}
48114402Sru
49114402Sruover_box::over_box(int is_small, box *pp, box *qq)
50114402Sru: reduce_size(is_small), num(pp), den(qq)
51114402Sru{
52114402Sru  spacing_type = INNER_TYPE;
53114402Sru}
54114402Sru
55114402Sruover_box::~over_box()
56114402Sru{
57114402Sru  delete num;
58114402Sru  delete den;
59114402Sru}
60114402Sru
61114402Sruint over_box::compute_metrics(int style)
62114402Sru{
63114402Sru  if (reduce_size) {
64114402Sru    style = script_style(style);
65114402Sru    printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
66114402Sru    set_script_size();
67114402Sru    printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
68114402Sru  }
69114402Sru  int mark_uid = 0;
70114402Sru  int res = num->compute_metrics(style);
71114402Sru  if (res)
72114402Sru    mark_uid = num->uid;
73114402Sru  int r = den->compute_metrics(cramped_style(style));
74114402Sru  if (r && res)
75114402Sru    error("multiple marks and lineups");
76114402Sru  else {
77114402Sru    mark_uid = den->uid;
78114402Sru    res = r;
79114402Sru  }
80114402Sru  if (reduce_size)
81114402Sru    printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
82114402Sru  printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
83114402Sru	 uid, num->uid, den->uid);
84114402Sru  // allow for \(ru being wider than both the numerator and denominator
85114402Sru  if (!draw_flag)
86114402Sru    fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
87114402Sru  printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
88114402Sru  // 15b
89114402Sru  printf(".nr " SUP_RAISE_FORMAT " %dM\n",
90114402Sru	 uid, (reduce_size ? num2 : num1));
91114402Sru  printf(".nr " SUB_LOWER_FORMAT " %dM\n",
92114402Sru	 uid, (reduce_size ? denom2 : denom1));
93114402Sru
94114402Sru  // 15d
95114402Sru  printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
96114402Sru	 "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
97114402Sru	 uid, num->uid, uid, axis_height, default_rule_thickness,
98114402Sru	 default_rule_thickness*(reduce_size ? 1 : 3));
99114402Sru  printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
100114402Sru	 "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
101114402Sru	 uid, den->uid, uid, axis_height, default_rule_thickness,
102114402Sru	 default_rule_thickness*(reduce_size ? 1 : 3));
103114402Sru
104114402Sru
105114402Sru  printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
106114402Sru	 HEIGHT_FORMAT "]\n",
107114402Sru	 uid, uid, num->uid);
108114402Sru  printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
109114402Sru	 DEPTH_FORMAT "]\n",
110114402Sru	 uid, uid, den->uid);
111114402Sru  if (res)
112114402Sru    printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
113114402Sru	   WIDTH_FORMAT "]/2)\n", uid, mark_uid);
114114402Sru  return res;
115114402Sru}
116114402Sru
117114402Sru#define USE_Z
118114402Sru
119114402Sruvoid over_box::output()
120114402Sru{
121114402Sru  if (reduce_size)
122114402Sru    printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
123114402Sru#ifdef USE_Z
124114402Sru  printf("\\Z" DELIMITER_CHAR);
125114402Sru#endif
126114402Sru  // move up to the numerator baseline
127114402Sru  printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
128114402Sru  // move across so that it's centered
129114402Sru  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
130114402Sru	 uid, num->uid);
131114402Sru
132114402Sru  // print the numerator
133114402Sru  num->output();
134114402Sru
135114402Sru#ifdef USE_Z
136114402Sru  printf(DELIMITER_CHAR);
137114402Sru#else
138114402Sru  // back again
139114402Sru  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
140114402Sru  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
141114402Sru	 uid, num->uid);
142114402Sru  // down again
143114402Sru  printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
144114402Sru#endif
145114402Sru#ifdef USE_Z
146114402Sru  printf("\\Z" DELIMITER_CHAR);
147114402Sru#endif
148114402Sru  // move down to the denominator baseline
149114402Sru  printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
150114402Sru
151114402Sru  // move across so that it's centered
152114402Sru  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
153114402Sru	 uid, den->uid);
154114402Sru
155114402Sru  // print the the denominator
156114402Sru  den->output();
157114402Sru
158114402Sru#ifdef USE_Z
159114402Sru  printf(DELIMITER_CHAR);
160114402Sru#else
161114402Sru  // back again
162114402Sru  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
163114402Sru  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
164114402Sru	 uid, den->uid);
165114402Sru  // up again
166114402Sru  printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
167114402Sru#endif
168114402Sru  if (reduce_size)
169114402Sru    printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
170114402Sru  // draw the line
171114402Sru  printf("\\h'%dM'", null_delimiter_space);
172114402Sru  printf("\\v'-%dM'", axis_height);
173114402Sru  fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
174114402Sru  printf("\\n[" WIDTH_FORMAT "]u-%dM",
175114402Sru	 uid, 2*null_delimiter_space);
176114402Sru  fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
177114402Sru  printf("\\v'%dM'", axis_height);
178114402Sru  printf("\\h'%dM'", null_delimiter_space);
179114402Sru}
180114402Sru
181114402Sruvoid over_box::debug_print()
182114402Sru{
183114402Sru  fprintf(stderr, "{ ");
184114402Sru  num->debug_print();
185114402Sru  if (reduce_size)
186114402Sru    fprintf(stderr, " } smallover { ");
187114402Sru  else
188114402Sru    fprintf(stderr, " } over { ");
189114402Sru  den->debug_print();
190114402Sru  fprintf(stderr, " }");
191114402Sru}
192114402Sru
193114402Sruvoid over_box::check_tabs(int level)
194114402Sru{
195114402Sru  num->check_tabs(level + 1);
196114402Sru  den->check_tabs(level + 1);
197114402Sru}
198