home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / eqn / list.cc < prev    next >
C/C++ Source or Header  |  1995-06-22  |  6KB  |  238 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 2, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  20.  
  21. #include "eqn.h"
  22. #include "pbox.h"
  23.  
  24. list_box *box::to_list_box()
  25. {
  26.   return 0;
  27. }
  28.  
  29. list_box *list_box::to_list_box()
  30. {
  31.   return this;
  32. }
  33.  
  34. void 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.  
  49. list_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.  
  64. static 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.  
  91. int 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 (int 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.  
  174. void 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 (int 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.  
  198. void 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.  
  209. void 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.  
  223. void 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.  
  229. void list_box::debug_print()
  230. {
  231.   list.list_debug_print(" ");
  232. }
  233.  
  234. void list_box::check_tabs(int level)
  235. {
  236.   list.list_check_tabs(level);
  237. }
  238.