PageRenderTime 47ms CodeModel.GetById 15ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/freebsd/freebsd-head/
C++ | 237 lines | 200 code | 13 blank | 24 comment | 99 complexity | 41d1a4f1e9f3749d73f5fe7c31897ab6 MD5 | raw file
  1// -*- C++ -*-
  2/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3     Written by James Clark (jjc@jclark.com)
  4
  5This file is part of groff.
  6
  7groff is free software; you can redistribute it and/or modify it under
  8the terms of the GNU General Public License as published by the Free
  9Software Foundation; either version 2, or (at your option) any later
 10version.
 11
 12groff is distributed in the hope that it will be useful, but WITHOUT ANY
 13WARRANTY; without even the implied warranty of MERCHANTABILITY or
 14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 15for more details.
 16
 17You should have received a copy of the GNU General Public License along
 18with groff; see the file COPYING.  If not, write to the Free Software
 19Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
 20
 21#include "eqn.h"
 22#include "pbox.h"
 23
 24list_box *box::to_list_box()
 25{
 26  return 0;
 27}
 28
 29list_box *list_box::to_list_box()
 30{
 31  return this;
 32}
 33
 34void list_box::append(box *pp)
 35{
 36  list_box *q = pp->to_list_box();
 37  if (q == 0)
 38    list.append(pp);
 39  else {
 40    for (int i = 0; i < q->list.len; i++) {
 41      list.append(q->list.p[i]);
 42      q->list.p[i] = 0;
 43    }
 44    q->list.len = 0;
 45    delete q;
 46  }
 47}
 48
 49list_box::list_box(box *pp) : list(pp), sty(-1)
 50{
 51  list_box *q = pp->to_list_box();
 52  if (q != 0) {
 53    // flatten it
 54    list.p[0] = q->list.p[0];
 55    for (int i = 1; i < q->list.len; i++) {
 56      list.append(q->list.p[i]);
 57      q->list.p[i] = 0;
 58    }
 59    q->list.len = 0;
 60    delete q;
 61  }
 62}
 63
 64static int compute_spacing(int is_script, int left, int right)
 65{
 66  if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
 67    return 0;
 68  if (left == PUNCTUATION_TYPE)
 69    return is_script ? 0 : thin_space;
 70  if (left == OPENING_TYPE || right == CLOSING_TYPE)
 71    return 0;
 72  if (right == BINARY_TYPE || left == BINARY_TYPE)
 73    return is_script ? 0 : medium_space;
 74  if (right == RELATION_TYPE) {
 75    if (left == RELATION_TYPE)
 76      return 0;
 77    else
 78      return is_script ? 0 : thick_space;
 79  }
 80  if (left == RELATION_TYPE)
 81    return is_script ? 0 : thick_space;
 82  if (right == OPERATOR_TYPE)
 83    return thin_space;
 84  if (left == INNER_TYPE || right == INNER_TYPE)
 85    return is_script ? 0 : thin_space;
 86  if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
 87    return thin_space;
 88  return 0;
 89}
 90
 91int list_box::compute_metrics(int style)
 92{
 93  sty = style;
 94  int i;
 95  for (i = 0; i < list.len; i++) {
 96    int t = list.p[i]->spacing_type; 
 97    // 5
 98    if (t == BINARY_TYPE) {
 99      int prevt;
100      if (i == 0
101	  || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
102	  || prevt == OPERATOR_TYPE
103	  || prevt == RELATION_TYPE
104	  || prevt == OPENING_TYPE
105	  || prevt == PUNCTUATION_TYPE)
106	list.p[i]->spacing_type = ORDINARY_TYPE;
107    }
108    // 7
109    else if ((t == RELATION_TYPE || t == CLOSING_TYPE 
110	      || t == PUNCTUATION_TYPE)
111	     && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
112      list.p[i-1]->spacing_type = ORDINARY_TYPE;
113  }
114  for (i = 0; i < list.len; i++) {
115    unsigned flags = 0;
116    if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
117      flags |= HINT_PREV_IS_ITALIC;
118    if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
119      flags |= HINT_NEXT_IS_ITALIC;
120    if (flags)
121      list.p[i]->hint(flags);
122  }
123  is_script = (style <= SCRIPT_STYLE);
124  int total_spacing = 0;
125  for (i = 1; i < list.len; i++)
126    total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
127				     list.p[i]->spacing_type);
128  int res = 0;
129  for (i = 0; i < list.len; i++)
130    if (!list.p[i]->is_simple()) {
131      int r = list.p[i]->compute_metrics(style);
132      if (r) {
133	if (res)
134	  error("multiple marks and lineups");
135	else {
136	  compute_sublist_width(i);
137	  printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
138	  res = r;
139	}
140      }
141    }
142  printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
143  for (i = 0; i < list.len; i++)
144    if (!list.p[i]->is_simple())
145      printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
146  printf("\n");
147  printf(".nr " HEIGHT_FORMAT " 0", uid);
148  for (i = 0; i < list.len; i++)
149    if (!list.p[i]->is_simple())
150      printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
151  printf("\n");
152  printf(".nr " DEPTH_FORMAT " 0", uid);
153  for (i = 0; i < list.len; i++)
154    if (!list.p[i]->is_simple())
155      printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
156  printf("\n");
157  int have_simple = 0;
158  for (i = 0; i < list.len && !have_simple; i++)
159    have_simple = list.p[i]->is_simple();
160  if (have_simple) {
161    printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
162    for (i = 0; i < list.len; i++)
163      if (list.p[i]->is_simple())
164	list.p[i]->output();
165    printf(DELIMITER_CHAR "\n");
166    printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
167	   uid, uid);
168    printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
169	   uid, uid);
170  }
171  return res;
172}
173
174void list_box::compute_sublist_width(int n)
175{
176  int total_spacing = 0;
177  int i;
178  for (i = 1; i < n + 1 && i < list.len; i++)
179    total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
180				     list.p[i]->spacing_type);
181  printf(".nr " TEMP_REG " %dM", total_spacing);
182  for (i = 0; i < n; i++)
183    if (!list.p[i]->is_simple())
184      printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
185  int have_simple = 0;
186  for (i = 0; i < n && !have_simple; i++)
187    have_simple = list.p[i]->is_simple();
188  if (have_simple) {
189    printf("+\\w" DELIMITER_CHAR);
190    for (i = 0; i < n; i++)
191      if (list.p[i]->is_simple())
192	list.p[i]->output();
193    printf(DELIMITER_CHAR);
194  }
195  printf("\n");
196}
197
198void list_box::compute_subscript_kern()
199{
200  // We can only call compute_subscript_kern if we have called
201  // compute_metrics first.
202  if (list.p[list.len-1]->is_simple())
203    list.p[list.len-1]->compute_metrics(sty);
204  list.p[list.len-1]->compute_subscript_kern();
205  printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
206	 uid, list.p[list.len-1]->uid);
207}
208
209void list_box::output()
210{
211  for (int i = 0; i < list.len; i++) {
212    if (i > 0) {
213      int n = compute_spacing(is_script,
214			      list.p[i-1]->spacing_type,
215			      list.p[i]->spacing_type);
216      if (n > 0)
217	printf("\\h'%dM'", n);
218    }
219    list.p[i]->output();
220  }
221}
222
223void list_box::handle_char_type(int st, int ft)
224{
225  for (int i = 0; i < list.len; i++)
226    list.p[i]->handle_char_type(st, ft);
227}
228
229void list_box::debug_print()
230{
231  list.list_debug_print(" ");
232}
233
234void list_box::check_tabs(int level)
235{
236  list.list_check_tabs(level);
237}