LCOV - code coverage report
Current view: top level - preproc/eqn - pile.cpp (source / functions) Hit Total Coverage
Test: GNU roff Lines: 58 257 22.6 %
Date: 2026-01-16 17:51:41 Functions: 6 17 35.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright 1989-2007 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             : // piles and matrices
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : 
      25             : #include <assert.h>
      26             : 
      27             : #include "eqn.h"
      28             : #include "pbox.h"
      29             : 
      30             : // SUP_RAISE_FORMAT gives the first baseline
      31             : // BASELINE_SEP_FORMAT gives the separation between baselines
      32             : 
      33           6 : int pile_box::compute_metrics(int style)
      34             : {
      35             :   int i;
      36          24 :   for (i = 0; i < col.len; i++)
      37          18 :     col.p[i]->compute_metrics(style);
      38           6 :   printf(".nr " WIDTH_FORMAT " 0", uid);
      39          24 :   for (i = 0; i < col.len; i++)
      40          18 :     printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
      41           6 :   printf("\n");
      42           6 :   printf(".nr " BASELINE_SEP_FORMAT " %dM",
      43           6 :          uid, get_param("baseline_sep") + col.space);
      44          18 :   for (i = 1; i < col.len; i++)
      45          12 :     printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
      46          12 :            col.p[i-1]->uid, col.p[i]->uid,
      47          12 :            get_param("default_rule_thickness") * 5);
      48             :   // round it so that it's a multiple of the vertical motion quantum
      49           6 :   printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
      50             : 
      51           6 :   printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
      52             :          "+%dM\n",
      53           6 :          uid, uid, col.len-1, get_param("axis_height")
      54           6 :                               - get_param("shift_down"));
      55           6 :   printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
      56             :          HEIGHT_FORMAT "]\n",
      57           6 :          uid, uid, col.p[0]->uid);
      58           6 :   printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
      59             :          DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
      60           6 :          uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
      61           6 :   return FOUND_NOTHING;
      62             : }
      63             : 
      64           6 : void pile_box::output()
      65             : {
      66           6 :   if (output_format == troff) {
      67             :     int i;
      68           6 :     printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
      69          24 :     for (i = 0; i < col.len; i++) {
      70          18 :       switch (col.align) {
      71           9 :       case LEFT_ALIGN:
      72           9 :         break;
      73           0 :       case CENTER_ALIGN:
      74           0 :         printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
      75           0 :                uid, col.p[i]->uid);
      76           0 :         break;
      77           9 :       case RIGHT_ALIGN:
      78           9 :         printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
      79           9 :                uid, col.p[i]->uid);
      80           9 :         break;
      81           0 :       default:
      82           0 :         assert(0 == "unhandled case of column alignment");
      83             :       }
      84          18 :       col.p[i]->output();
      85          18 :       printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
      86          18 :       switch (col.align) {
      87           9 :       case LEFT_ALIGN:
      88           9 :         break;
      89           0 :       case CENTER_ALIGN:
      90           0 :         printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
      91           0 :                col.p[i]->uid, uid);
      92           0 :         break;
      93           9 :       case RIGHT_ALIGN:
      94           9 :         printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
      95           9 :                col.p[i]->uid, uid);
      96           9 :         break;
      97           0 :       default:
      98           0 :         assert(0 == "unhandled case of column alignment");
      99             :       }
     100          18 :       if (i != col.len - 1)
     101          12 :         printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
     102             :     }
     103           6 :     printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
     104           6 :     printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
     105           6 :     printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
     106             :   }
     107           0 :   else if (output_format == mathml) {
     108             :     const char *av;
     109           0 :     switch (col.align) {
     110           0 :     case LEFT_ALIGN:
     111           0 :       av = "left";
     112           0 :       break;
     113           0 :     case RIGHT_ALIGN:
     114           0 :       av = "right";
     115           0 :       break;
     116           0 :     case CENTER_ALIGN:
     117           0 :       av = "center";
     118           0 :       break;
     119           0 :     default:
     120           0 :       assert(0 == "unhandled case of column alignment");
     121             :     }
     122           0 :     printf("<mtable columnalign='%s'>", av);
     123           0 :     for (int i = 0; i < col.len; i++) {
     124           0 :       printf("<mtr><mtd>");
     125           0 :       col.p[i]->output();
     126           0 :       printf("</mtd></mtr>");
     127             :     }
     128           0 :     printf("</mtable>");
     129             :   }
     130           6 : }
     131             : 
     132           6 : pile_box::pile_box(box *pp) : col(pp)
     133             : {
     134           6 : }
     135             : 
     136           6 : void pile_box::diagnose_tab_stop_usage(int level)
     137             : {
     138           6 :   col.list_diagnose_tab_stop_usage(level);
     139           6 : }
     140             : 
     141           0 : void pile_box::debug_print()
     142             : {
     143           0 :   col.debug_print("pile");
     144           0 : }
     145             : 
     146           0 : int matrix_box::compute_metrics(int style)
     147             : {
     148             :   int i, j;
     149           0 :   int max_len = 0;
     150           0 :   int space = 0;
     151           0 :   for (i = 0; i < len; i++) {
     152           0 :     for (j = 0; j < p[i]->len; j++)
     153           0 :       p[i]->p[j]->compute_metrics(style);
     154           0 :     if (p[i]->len > max_len)
     155           0 :       max_len = p[i]->len;
     156           0 :     if (p[i]->space > space)
     157           0 :       space = p[i]->space;
     158             :   }
     159           0 :   for (i = 0; i < len; i++) {
     160           0 :     printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
     161           0 :     for (j = 0; j < p[i]->len; j++)
     162           0 :       printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
     163           0 :     printf("\n");
     164             :   }
     165           0 :   printf(".nr " WIDTH_FORMAT " %dM",
     166           0 :          uid, get_param("column_sep") * (len - 1) + 2
     167           0 :          * get_param("matrix_side_sep"));
     168           0 :   for (i = 0; i < len; i++)
     169           0 :     printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
     170           0 :   printf("\n");
     171           0 :   printf(".nr " BASELINE_SEP_FORMAT " %dM",
     172           0 :          uid, get_param("baseline_sep") + space);
     173           0 :   for (i = 0; i < len; i++)
     174           0 :     for (j = 1; j < p[i]->len; j++)
     175           0 :       printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
     176           0 :            p[i]->p[j-1]->uid, p[i]->p[j]->uid,
     177           0 :            get_param("default_rule_thickness") * 5);
     178             :   // round it so that it's a multiple of the vertical motion quantum
     179           0 :   printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
     180           0 :   printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
     181             :          "+%dM\n",
     182           0 :          uid, uid, max_len-1, get_param("axis_height")
     183           0 :          - get_param("shift_down"));
     184           0 :   printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
     185           0 :          uid, uid);
     186           0 :   for (i = 0; i < len; i++)
     187           0 :     printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
     188           0 :   printf(")>?0\n");
     189           0 :   printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
     190             :          SUP_RAISE_FORMAT "]+(0",
     191           0 :          uid, uid, max_len-1, uid);
     192           0 :   for (i = 0; i < len; i++)
     193           0 :     if (p[i]->len == max_len)
     194           0 :       printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
     195           0 :   printf(")>?0\n");
     196           0 :   return FOUND_NOTHING;
     197             : }
     198             : 
     199           0 : void matrix_box::output()
     200             : {
     201           0 :   if (output_format == troff) {
     202           0 :     printf("\\h'%dM'", get_param("matrix_side_sep"));
     203           0 :     for (int i = 0; i < len; i++) {
     204             :       int j;
     205           0 :       printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
     206           0 :       for (j = 0; j < p[i]->len; j++) {
     207           0 :         switch (p[i]->align) {
     208           0 :         case LEFT_ALIGN:
     209           0 :           break;
     210           0 :         case CENTER_ALIGN:
     211           0 :           printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
     212           0 :                  uid, i, p[i]->p[j]->uid);
     213           0 :           break;
     214           0 :         case RIGHT_ALIGN:
     215           0 :           printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
     216           0 :                  uid, i, p[i]->p[j]->uid);
     217           0 :           break;
     218           0 :         default:
     219           0 :           assert(0 == "unhandled case of column alignment");
     220             :         }
     221           0 :         p[i]->p[j]->output();
     222           0 :         printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
     223           0 :         switch (p[i]->align) {
     224           0 :         case LEFT_ALIGN:
     225           0 :           break;
     226           0 :         case CENTER_ALIGN:
     227           0 :           printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
     228           0 :                  p[i]->p[j]->uid, uid, i);
     229           0 :           break;
     230           0 :         case RIGHT_ALIGN:
     231           0 :           printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
     232           0 :                  p[i]->p[j]->uid, uid, i);
     233           0 :           break;
     234           0 :         default:
     235           0 :           assert(0 == "unhandled case of column alignment");
     236             :         }
     237           0 :         if (j != p[i]->len - 1)
     238           0 :           printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
     239             :       }
     240           0 :       printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
     241           0 :       printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
     242           0 :       printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
     243           0 :       if (i != len - 1)
     244           0 :         printf("\\h'%dM'", get_param("column_sep"));
     245             :     }
     246           0 :     printf("\\h'%dM'", get_param("matrix_side_sep"));
     247             :   }
     248           0 :   else if (output_format == mathml) {
     249           0 :     int n = p[0]->len;       // Each column must have the same number of rows in it
     250           0 :     printf("<mtable>");
     251           0 :     for (int i = 0; i < n; i++) {
     252           0 :       printf("<mtr>");
     253           0 :       for (int j = 0; j < len; j++) {
     254             :         const char *av;
     255           0 :         switch (p[j]->align) {
     256           0 :         case LEFT_ALIGN:
     257           0 :           av = "left";
     258           0 :           break;
     259           0 :         case RIGHT_ALIGN:
     260           0 :           av = "right";
     261           0 :           break;
     262           0 :         case CENTER_ALIGN:
     263           0 :           av = "center";
     264           0 :           break;
     265           0 :         default:
     266           0 :           assert(0 == "unhandled case of column alignment");
     267             :         }
     268           0 :         printf("<mtd columnalign='%s'>", av);
     269           0 :         p[j]->p[i]->output();
     270           0 :         printf("</mtd>");
     271             :       }
     272           0 :       printf("</mtr>");
     273             :     }
     274           0 :     printf("</mtable>");
     275             :   }
     276           0 : }
     277             : 
     278           0 : matrix_box::matrix_box(column *pp)
     279             : {
     280           0 :   p = new column*[10];
     281           0 :   for (int i = 0; i < 10; i++)
     282           0 :     p[i] = 0;
     283           0 :   maxlen = 10;
     284           0 :   len = 1;
     285           0 :   p[0] = pp;
     286           0 : }
     287             : 
     288           0 : matrix_box::~matrix_box()
     289             : {
     290           0 :   for (int i = 0; i < len; i++)
     291           0 :     delete p[i];
     292           0 :   delete[] p;
     293           0 : }
     294             : 
     295           0 : void matrix_box::append(column *pp)
     296             : {
     297           0 :   if (len + 1 > maxlen) {
     298           0 :     column **oldp = p;
     299           0 :     maxlen *= 2;
     300           0 :     p = new column*[maxlen];
     301           0 :     memcpy(p, oldp, sizeof(column*)*len);
     302           0 :     delete[] oldp;
     303             :   }
     304           0 :   p[len++] = pp;
     305           0 : }
     306             : 
     307           0 : void matrix_box::diagnose_tab_stop_usage(int level)
     308             : {
     309           0 :   for (int i = 0; i < len; i++)
     310           0 :     p[i]->list_diagnose_tab_stop_usage(level);
     311           0 : }
     312             : 
     313           0 : void matrix_box::debug_print()
     314             : {
     315           0 :   fprintf(stderr, "matrix { ");
     316           0 :   p[0]->debug_print("col");
     317           0 :   for (int i = 1; i < len; i++) {
     318           0 :     fprintf(stderr, " ");
     319           0 :     p[i]->debug_print("col");
     320             :   }
     321           0 :   fprintf(stderr, " }");
     322           0 : }
     323             : 
     324           6 : column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
     325             : {
     326           6 : }
     327             : 
     328           6 : void column::set_alignment(alignment a)
     329             : {
     330           6 :   align = a;
     331           6 : }
     332             : 
     333           0 : void column::set_space(int n)
     334             : {
     335           0 :   space = n;
     336           0 : }
     337             : 
     338           0 : void column::debug_print(const char *s)
     339             : {
     340           0 :   char c = '\0';                // shut up -Wall
     341           0 :   switch (align) {
     342           0 :   case LEFT_ALIGN:
     343           0 :     c = 'l';
     344           0 :     break;
     345           0 :   case RIGHT_ALIGN:
     346           0 :     c = 'r';
     347           0 :     break;
     348           0 :   case CENTER_ALIGN:
     349           0 :     c = 'c';
     350           0 :     break;
     351           0 :   default:
     352           0 :     assert(0 == "unhandled case of column alignment");
     353             :   }
     354           0 :   fprintf(stderr, "%c%s %d { ", c, s, space);
     355           0 :   list_debug_print(" above ");
     356           0 :   fprintf(stderr, " }");
     357           0 : }
     358             : 
     359             : // Local Variables:
     360             : // fill-column: 72
     361             : // mode: C++
     362             : // End:
     363             : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:

Generated by: LCOV version 1.14