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