LCOV - code coverage report
Current view: top level - preproc/eqn - list.cpp (source / functions) Hit Total Coverage
Test: GNU roff Lines: 117 166 70.5 %
Date: 2026-01-16 17:51:41 Functions: 8 12 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14