PageRenderTime 52ms CodeModel.GetById 34ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/groff/src/preproc/eqn/script.cpp

https://bitbucket.org/freebsd/freebsd-head/
C++ | 222 lines | 181 code | 12 blank | 29 comment | 46 complexity | e17d9f900a68edaef1aa0bb8e3274412 MD5 | raw file
  1// -*- C++ -*-
  2/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
  3   Free Software Foundation, Inc.
  4     Written by James Clark (jjc@jclark.com)
  5
  6This file is part of groff.
  7
  8groff is free software; you can redistribute it and/or modify it under
  9the terms of the GNU General Public License as published by the Free
 10Software Foundation; either version 2, or (at your option) any later
 11version.
 12
 13groff is distributed in the hope that it will be useful, but WITHOUT ANY
 14WARRANTY; without even the implied warranty of MERCHANTABILITY or
 15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 16for more details.
 17
 18You should have received a copy of the GNU General Public License along
 19with groff; see the file COPYING.  If not, write to the Free Software
 20Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
 21
 22#include "eqn.h"
 23#include "pbox.h"
 24
 25class script_box : public pointer_box {
 26private:
 27  box *sub;
 28  box *sup;
 29public:
 30  script_box(box *, box *, box *);
 31  ~script_box();
 32  int compute_metrics(int);
 33  void output();
 34  void debug_print();
 35  int left_is_italic();
 36  void hint(unsigned);
 37  void check_tabs(int);
 38};
 39
 40/* The idea is that the script should attach to the rightmost box
 41of a list. For example, given `2x sup 3', the superscript should
 42attach to `x' rather than `2x'. */
 43
 44box *make_script_box(box *nuc, box *sub, box *sup)
 45{
 46  list_box *b = nuc->to_list_box();
 47  if (b != 0) {
 48    b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
 49					       sub,
 50					       sup);
 51    return b;
 52  }
 53  else
 54    return new script_box(nuc, sub, sup);
 55}
 56
 57script_box::script_box(box *pp, box *qq, box *rr)
 58: pointer_box(pp), sub(qq), sup(rr)
 59{
 60}
 61
 62script_box::~script_box()
 63{
 64  delete sub;
 65  delete sup;
 66}
 67
 68int script_box::left_is_italic()
 69{
 70  return p->left_is_italic();
 71}
 72
 73int script_box::compute_metrics(int style)
 74{
 75  int res = p->compute_metrics(style);
 76  p->compute_subscript_kern();
 77  printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
 78  if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
 79    set_script_size();
 80  printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
 81  if (sub != 0)
 82    sub->compute_metrics(cramped_style(script_style(style)));
 83  if (sup != 0)
 84    sup->compute_metrics(script_style(style));
 85  // 18a
 86  if (p->is_char()) {
 87    printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
 88    printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
 89  }
 90  else {
 91    printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
 92	   uid, p->uid, sup_drop);
 93    printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
 94	   uid, p->uid, sub_drop);
 95  }
 96  printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
 97  if (sup == 0) {
 98    assert(sub != 0);
 99    // 18b
100    printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
101	   HEIGHT_FORMAT "]-(%dM*4/5))\n",
102	   uid, uid, sub1, sub->uid, x_height);
103  }
104  else {
105    // sup != 0
106    // 18c
107    int pos;
108    if (style == DISPLAY_STYLE)
109      pos = sup1;
110    else if (style & 1)		// not cramped
111      pos = sup2;
112    else
113      pos = sup3;
114    printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
115	   "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
116	   uid, uid, pos, sup->uid, x_height);
117    // 18d
118    if (sub != 0) {
119      printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
120	     uid, uid, sub2);
121      // 18e
122      printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
123	     SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
124	     SUB_LOWER_FORMAT "]+(4*%dM)\n",
125	     sup->uid, uid, sub->uid, uid, default_rule_thickness);
126      printf(".if \\n[" TEMP_REG "] \\{");
127      printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
128      printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
129	     "]+\\n[" DEPTH_FORMAT "]>?0\n",
130	     x_height, uid, sup->uid);
131      printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
132      printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
133      printf(".\\}\n");
134    }
135  }
136  printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
137  if (sub != 0 && sup != 0)
138    printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
139	   WIDTH_FORMAT "])+%dM)>?0\n",
140	   sub->uid, p->uid, sup->uid, script_space);
141  else if (sub != 0)
142    printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
143	   sub->uid, p->uid, script_space);
144  else if (sup != 0)
145    printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
146  else
147    printf("\n");
148  printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
149	 uid, p->uid);
150  if (sup != 0)
151    printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
152	   uid, sup->uid);
153  if (sub != 0)
154    printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
155	   uid, sub->uid);
156  printf("\n");
157  printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
158	 uid, p->uid);
159  if (sub != 0)
160    printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
161	   uid, sub->uid);
162  if (sup != 0)
163    printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
164	   uid, sup->uid);
165  printf("\n");
166  return res;
167}
168
169void script_box::output()
170{
171  p->output();
172  if (sup != 0) {
173    printf("\\Z" DELIMITER_CHAR);
174    printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
175    printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
176    sup->output();
177    printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
178    printf(DELIMITER_CHAR);
179  }
180  if (sub != 0) {
181    printf("\\Z" DELIMITER_CHAR);
182    printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
183    printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
184    printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
185    sub->output();
186    printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
187    printf(DELIMITER_CHAR);
188  }
189  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
190	 uid, p->uid);
191}
192
193void script_box::hint(unsigned flags)
194{
195  p->hint(flags & ~HINT_NEXT_IS_ITALIC);
196}
197
198void script_box::debug_print()
199{
200  fprintf(stderr, "{ ");
201  p->debug_print();
202  fprintf(stderr, " }");
203  if (sub) {
204    fprintf(stderr, " sub { ");
205    sub->debug_print();
206    fprintf(stderr, " }");
207  }
208  if (sup) {
209    fprintf(stderr, " sup { ");
210    sup->debug_print();
211    fprintf(stderr, " }");
212  }
213}
214
215void script_box::check_tabs(int level)
216{
217  if (sup)
218    sup->check_tabs(level + 1);
219  if (sub)
220    sub->check_tabs(level + 1);
221  p->check_tabs(level);
222}