1/*	$NetBSD$	*/
2
3// -*- C++ -*-
4/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
5   Free Software Foundation, Inc.
6     Written by James Clark (jjc@jclark.com)
7
8This file is part of groff.
9
10groff is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
12Software Foundation; either version 2, or (at your option) any later
13version.
14
15groff is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License along
21with groff; see the file COPYING.  If not, write to the Free Software
22Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23
24#include "eqn.h"
25#include "pbox.h"
26
27class over_box : public box {
28private:
29  int reduce_size;
30  box *num;
31  box *den;
32public:
33  over_box(int small, box *, box *);
34  ~over_box();
35  void debug_print();
36  int compute_metrics(int);
37  void output();
38  void check_tabs(int);
39};
40
41box *make_over_box(box *pp, box *qq)
42{
43  return new over_box(0, pp, qq);
44}
45
46box *make_small_over_box(box *pp, box *qq)
47{
48  return new over_box(1, pp, qq);
49}
50
51over_box::over_box(int is_small, box *pp, box *qq)
52: reduce_size(is_small), num(pp), den(qq)
53{
54  spacing_type = INNER_TYPE;
55}
56
57over_box::~over_box()
58{
59  delete num;
60  delete den;
61}
62
63int over_box::compute_metrics(int style)
64{
65  if (reduce_size) {
66    style = script_style(style);
67    printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
68    set_script_size();
69    printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
70  }
71  int mark_uid = 0;
72  int res = num->compute_metrics(style);
73  if (res)
74    mark_uid = num->uid;
75  int r = den->compute_metrics(cramped_style(style));
76  if (r && res)
77    error("multiple marks and lineups");
78  else {
79    mark_uid = den->uid;
80    res = r;
81  }
82  if (reduce_size)
83    printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
84  printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
85	 uid, num->uid, den->uid);
86  // allow for \(ru being wider than both the numerator and denominator
87  if (!draw_flag)
88    fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
89  printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
90  // 15b
91  printf(".nr " SUP_RAISE_FORMAT " %dM\n",
92	 uid, (reduce_size ? num2 : num1));
93  printf(".nr " SUB_LOWER_FORMAT " %dM\n",
94	 uid, (reduce_size ? denom2 : denom1));
95
96  // 15d
97  printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
98	 "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
99	 uid, num->uid, uid, axis_height, default_rule_thickness,
100	 default_rule_thickness*(reduce_size ? 1 : 3));
101  printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
102	 "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
103	 uid, den->uid, uid, axis_height, default_rule_thickness,
104	 default_rule_thickness*(reduce_size ? 1 : 3));
105
106
107  printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
108	 HEIGHT_FORMAT "]\n",
109	 uid, uid, num->uid);
110  printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
111	 DEPTH_FORMAT "]\n",
112	 uid, uid, den->uid);
113  if (res)
114    printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
115	   WIDTH_FORMAT "]/2)\n", uid, mark_uid);
116  return res;
117}
118
119#define USE_Z
120
121void over_box::output()
122{
123  if (reduce_size)
124    printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
125#ifdef USE_Z
126  printf("\\Z" DELIMITER_CHAR);
127#endif
128  // move up to the numerator baseline
129  printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
130  // move across so that it's centered
131  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
132	 uid, num->uid);
133
134  // print the numerator
135  num->output();
136
137#ifdef USE_Z
138  printf(DELIMITER_CHAR);
139#else
140  // back again
141  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
142  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
143	 uid, num->uid);
144  // down again
145  printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
146#endif
147#ifdef USE_Z
148  printf("\\Z" DELIMITER_CHAR);
149#endif
150  // move down to the denominator baseline
151  printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
152
153  // move across so that it's centered
154  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
155	 uid, den->uid);
156
157  // print the the denominator
158  den->output();
159
160#ifdef USE_Z
161  printf(DELIMITER_CHAR);
162#else
163  // back again
164  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
165  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
166	 uid, den->uid);
167  // up again
168  printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
169#endif
170  if (reduce_size)
171    printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
172  // draw the line
173  printf("\\h'%dM'", null_delimiter_space);
174  printf("\\v'-%dM'", axis_height);
175  fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
176  printf("\\n[" WIDTH_FORMAT "]u-%dM",
177	 uid, 2*null_delimiter_space);
178  fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
179  printf("\\v'%dM'", axis_height);
180  printf("\\h'%dM'", null_delimiter_space);
181}
182
183void over_box::debug_print()
184{
185  fprintf(stderr, "{ ");
186  num->debug_print();
187  if (reduce_size)
188    fprintf(stderr, " } smallover { ");
189  else
190    fprintf(stderr, " } over { ");
191  den->debug_print();
192  fprintf(stderr, " }");
193}
194
195void over_box::check_tabs(int level)
196{
197  num->check_tabs(level + 1);
198  den->check_tabs(level + 1);
199}
200