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