home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / groff-1.08 / troff / node.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-02  |  93.1 KB  |  4,846 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include "troff.h"
  22. #include "symbol.h"
  23. #include "dictionary.h"
  24. #include "hvunits.h"
  25. #include "env.h"
  26. #include "request.h"
  27. #include "node.h"
  28. #include "token.h"
  29. #include "charinfo.h"
  30. #include "font.h"
  31. #include "reg.h"
  32.  
  33. #define STORE_WIDTH 1
  34.  
  35. symbol HYPHEN_SYMBOL("hy");
  36.  
  37. // Character used when a hyphen is inserted at a line break.
  38. static charinfo *soft_hyphen_char;
  39.  
  40. enum constant_space_type { 
  41.   CONSTANT_SPACE_NONE,
  42.   CONSTANT_SPACE_RELATIVE,
  43.   CONSTANT_SPACE_ABSOLUTE
  44.   };
  45.  
  46. struct special_font_list {
  47.   int n;
  48.   special_font_list *next;
  49. };
  50.  
  51. special_font_list *global_special_fonts;
  52. static int global_ligature_mode = 1;
  53. static int global_kern_mode = 1;
  54.  
  55. class track_kerning_function {
  56.   int non_zero;
  57.   units min_size;
  58.   hunits min_amount;
  59.   units max_size;
  60.   hunits max_amount;
  61. public:
  62.   track_kerning_function();
  63.   track_kerning_function(units, hunits, units, hunits);
  64.   int operator==(const track_kerning_function &);
  65.   int operator!=(const track_kerning_function &);
  66.   hunits compute(int point_size);
  67. };
  68.  
  69. // embolden fontno when this is the current font
  70.  
  71. struct conditional_bold {
  72.   conditional_bold *next;
  73.   int fontno;
  74.   hunits offset;
  75.   conditional_bold(int, hunits, conditional_bold * = 0);
  76. };
  77.  
  78. struct tfont;
  79.  
  80. class font_info {
  81.   tfont *last_tfont;
  82.   int number;
  83.   font_size last_size;
  84.   int last_height;
  85.   int last_slant;
  86.   symbol internal_name;
  87.   symbol external_name;
  88.   font *fm;
  89.   char is_bold;
  90.   hunits bold_offset;
  91.   track_kerning_function track_kern;
  92.   constant_space_type is_constant_spaced;
  93.   units constant_space;
  94.   int last_ligature_mode;
  95.   int last_kern_mode;
  96.   conditional_bold *cond_bold_list;
  97.   void flush();
  98. public:
  99.   special_font_list *sf;
  100.   
  101.   font_info(symbol nm, int n, symbol enm, font *f);
  102.   int contains(charinfo *);
  103.   void set_bold(hunits);
  104.   void unbold();
  105.   void set_conditional_bold(int, hunits);
  106.   void conditional_unbold(int);
  107.   void set_track_kern(track_kerning_function &);
  108.   void set_constant_space(constant_space_type, units = 0);
  109.   int is_named(symbol);
  110.   symbol get_name();
  111.   tfont *get_tfont(font_size, int, int, int);
  112.   hunits get_space_width(font_size, int);
  113.   hunits get_narrow_space_width(font_size);
  114.   hunits get_half_narrow_space_width(font_size);
  115.   int get_bold(hunits *);
  116.   int is_special();
  117.   int is_style();
  118. };
  119.  
  120. class tfont_spec {
  121. protected:
  122.   symbol name;
  123.   int input_position;
  124.   font *fm;
  125.   font_size size;
  126.   char is_bold;
  127.   char is_constant_spaced;
  128.   int ligature_mode;
  129.   int kern_mode;
  130.   hunits bold_offset;
  131.   hunits track_kern;            // add this to the width
  132.   hunits constant_space_width;
  133.   int height;
  134.   int slant;
  135. public:
  136.   tfont_spec(symbol nm, int pos, font *, font_size, int, int);
  137.   tfont_spec plain();
  138.   int operator==(const tfont_spec &);
  139.   friend tfont *font_info::get_tfont(font_size fs, int, int, int);
  140. };
  141.  
  142. class tfont : public tfont_spec {
  143.   static tfont *tfont_list;
  144.   tfont *next;
  145.   tfont *plain_version;
  146. public:
  147.   tfont(tfont_spec &);
  148.   int contains(charinfo *);
  149.   hunits get_width(charinfo *c);
  150.   int get_bold(hunits *);
  151.   int get_constant_space(hunits *);
  152.   hunits get_track_kern();
  153.   tfont *get_plain();
  154.   font_size get_size();
  155.   symbol get_name();
  156.   charinfo *get_lig(charinfo *c1, charinfo *c2);
  157.   int get_kern(charinfo *c1, charinfo *c2, hunits *res);
  158.   int get_input_position();
  159.   int get_character_type(charinfo *);
  160.   int get_height();
  161.   int get_slant();
  162.   vunits get_char_height(charinfo *);
  163.   vunits get_char_depth(charinfo *);
  164.   hunits get_char_skew(charinfo *);
  165.   hunits get_italic_correction(charinfo *);
  166.   hunits get_left_italic_correction(charinfo *);
  167.   hunits get_subscript_correction(charinfo *);
  168.   friend tfont *make_tfont(tfont_spec &);
  169. };
  170.  
  171. inline int env_definite_font(environment *env)
  172. {
  173.   return env->get_family()->make_definite(env->get_font());
  174. }
  175.  
  176. static void invalidate_fontno(int n);
  177.  
  178. /* font_info functions */
  179.  
  180. static font_info **font_table = 0;
  181. static int font_table_size = 0;
  182.  
  183. font_info::font_info(symbol nm, int n, symbol enm, font *f)
  184. : internal_name(nm), external_name(enm), fm(f), number(n),
  185.   is_constant_spaced(CONSTANT_SPACE_NONE),
  186.   sf(0), is_bold(0), cond_bold_list(0),
  187.   last_ligature_mode(1), last_kern_mode(1),
  188.   last_tfont(0), last_size(0)
  189. {
  190. }
  191.  
  192. inline int font_info::contains(charinfo *ci)
  193. {
  194.   return fm != 0 && fm->contains(ci->get_index());
  195. }
  196.  
  197. inline int font_info::is_special()
  198. {
  199.   return fm != 0 && fm->is_special();
  200. }
  201.  
  202. inline int font_info::is_style()
  203. {
  204.   return fm == 0;
  205. }
  206.  
  207. // this is the current_font, fontno is where we found the character,
  208. // presumably a special font
  209.  
  210. tfont *font_info::get_tfont(font_size fs, int height, int slant, int fontno)
  211. {
  212.   if (last_tfont == 0 || fs != last_size
  213.       || height != last_height || slant != last_slant
  214.       || global_ligature_mode != last_ligature_mode
  215.       || global_kern_mode != last_kern_mode
  216.       || fontno != number) {
  217.     font_info *f = font_table[fontno];
  218.     tfont_spec spec(f->external_name, f->number, f->fm, fs, height, slant);
  219.     for (conditional_bold *p = cond_bold_list; p; p = p->next)
  220.       if (p->fontno == fontno) {
  221.         spec.is_bold = 1;
  222.         spec.bold_offset = p->offset;
  223.         break;
  224.       }
  225.     if (!spec.is_bold && is_bold) {
  226.       spec.is_bold = 1;
  227.       spec.bold_offset = bold_offset;
  228.     }
  229.     spec.track_kern = track_kern.compute(fs.to_scaled_points());
  230.     spec.ligature_mode = global_ligature_mode;
  231.     spec.kern_mode = global_kern_mode;
  232.     switch (is_constant_spaced) {
  233.     case CONSTANT_SPACE_NONE:
  234.       break;
  235.     case CONSTANT_SPACE_ABSOLUTE:
  236.       spec.is_constant_spaced = 1;
  237.       spec.constant_space_width = constant_space;
  238.       break;
  239.     case CONSTANT_SPACE_RELATIVE:
  240.       spec.is_constant_spaced = 1;
  241.       spec.constant_space_width
  242.         = scale(constant_space*fs.to_scaled_points(),
  243.             units_per_inch,
  244.             36*72*sizescale);
  245.       break;
  246.     default:
  247.       assert(0);
  248.     }
  249.     if (fontno != number)
  250.       return make_tfont(spec);
  251.     last_tfont = make_tfont(spec);
  252.     last_size = fs;
  253.     last_height = height;
  254.     last_slant = slant;
  255.     last_ligature_mode = global_ligature_mode;
  256.     last_kern_mode = global_kern_mode;
  257.       }
  258.   return last_tfont;
  259. }
  260.  
  261. int font_info::get_bold(hunits *res)
  262. {
  263.   if (is_bold) {
  264.     *res = bold_offset;
  265.     return 1;
  266.   }
  267.   else
  268.     return 0;
  269. }
  270.  
  271. void font_info::unbold()
  272. {
  273.   if (is_bold) {
  274.     is_bold = 0;
  275.     flush();
  276.   }
  277. }
  278.  
  279. void font_info::set_bold(hunits offset)
  280. {
  281.   if (!is_bold || offset != bold_offset) {
  282.     is_bold = 1;
  283.     bold_offset = offset;
  284.     flush();
  285.   }
  286. }
  287.  
  288. void font_info::set_conditional_bold(int fontno, hunits offset)
  289. {
  290.   for (conditional_bold *p = cond_bold_list; p; p = p->next)
  291.     if (p->fontno == fontno) {
  292.       if (offset != p->offset) {
  293.     p->offset = offset;
  294.     flush();
  295.       }
  296.       return;
  297.     }
  298.   cond_bold_list = new conditional_bold(fontno, offset, cond_bold_list);
  299. }
  300.  
  301. conditional_bold::conditional_bold(int f, hunits h, conditional_bold *x)
  302.      : fontno(f), offset(h), next(x)
  303. {
  304. }
  305.  
  306. void font_info::conditional_unbold(int fontno)
  307. {
  308.   for (conditional_bold **p = &cond_bold_list; *p; p = &(*p)->next)
  309.     if ((*p)->fontno == fontno) {
  310.       conditional_bold *tem = *p;
  311.       *p = (*p)->next;
  312.       delete tem;
  313.       flush();
  314.       return;
  315.     }
  316. }
  317.                  
  318. void font_info::set_constant_space(constant_space_type type, units x)
  319. {
  320.   if (type != is_constant_spaced
  321.       || (type != CONSTANT_SPACE_NONE && x != constant_space)) {
  322.     flush();
  323.     is_constant_spaced = type;
  324.     constant_space = x;
  325.       }
  326. }
  327.  
  328. void font_info::set_track_kern(track_kerning_function  &tk)
  329. {
  330.   if (track_kern != tk) {
  331.     track_kern = tk;
  332.     flush();
  333.   }
  334. }
  335.  
  336. void font_info::flush()
  337. {
  338.   last_tfont = 0;
  339. }
  340.  
  341. int font_info::is_named(symbol s)
  342. {
  343.   return internal_name == s;
  344. }
  345.  
  346. symbol font_info::get_name()
  347. {
  348.   return internal_name;
  349. }
  350.  
  351. hunits font_info::get_space_width(font_size fs, int space_size)
  352. {
  353.   if (is_constant_spaced == CONSTANT_SPACE_NONE)
  354.     return scale(hunits(fm->get_space_width(fs.to_scaled_points())),
  355.             space_size, 12);
  356.   else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE)
  357.     return constant_space;
  358.   else
  359.     return scale(constant_space*fs.to_scaled_points(),
  360.          units_per_inch, 36*72*sizescale);
  361. }
  362.  
  363. hunits font_info::get_narrow_space_width(font_size fs)
  364. {
  365.   charinfo *ci = get_charinfo(symbol("|"));
  366.   if (fm->contains(ci->get_index()))
  367.     return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
  368.   else
  369.     return hunits(fs.to_units()/6);
  370. }
  371.  
  372. hunits font_info::get_half_narrow_space_width(font_size fs)
  373. {
  374.   charinfo *ci = get_charinfo(symbol("^"));
  375.   if (fm->contains(ci->get_index()))
  376.     return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
  377.   else
  378.     return hunits(fs.to_units()/12);
  379. }
  380.  
  381. /* tfont */
  382.  
  383. tfont_spec::tfont_spec(symbol nm, int n, font *f, 
  384.                font_size s, int h, int sl)
  385.      : name(nm), input_position(n), fm(f), size(s),
  386.      is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1),
  387.      height(h), slant(sl)
  388. {
  389.   if (height == size.to_scaled_points())
  390.     height = 0;
  391. }
  392.  
  393. int tfont_spec::operator==(const tfont_spec &spec)
  394. {
  395.   if (fm == spec.fm 
  396.       && size == spec.size
  397.       && input_position == spec.input_position
  398.       && name == spec.name
  399.       && height == spec.height
  400.       && slant == spec.slant
  401.       && (is_bold 
  402.       ? (spec.is_bold && bold_offset == spec.bold_offset)
  403.       : !spec.is_bold)
  404.       && track_kern == spec.track_kern
  405.       && (is_constant_spaced
  406.       ? (spec.is_constant_spaced 
  407.          && constant_space_width == spec.constant_space_width)
  408.       : !spec.is_constant_spaced)
  409.       && ligature_mode == spec.ligature_mode
  410.       && kern_mode == spec.kern_mode)
  411.     return 1;
  412.   else
  413.     return 0;
  414. }
  415.  
  416. tfont_spec tfont_spec::plain()
  417. {
  418.   return tfont_spec(name, input_position, fm, size, height, slant);
  419. }
  420.  
  421. hunits tfont::get_width(charinfo *c)
  422. {
  423.   if (is_constant_spaced)
  424.     return constant_space_width;
  425.   else if (is_bold)
  426.     return (hunits(fm->get_width(c->get_index(), size.to_scaled_points()))
  427.         + track_kern + bold_offset);
  428.   else
  429.     return (hunits(fm->get_width(c->get_index(), size.to_scaled_points())) + track_kern);
  430. }
  431.  
  432. vunits tfont::get_char_height(charinfo *c)
  433. {
  434.   vunits v = fm->get_height(c->get_index(), size.to_scaled_points());
  435.   if (height != 0 && height != size.to_scaled_points())
  436.     return scale(v, height, size.to_scaled_points());
  437.   else
  438.     return v;
  439. }
  440.  
  441. vunits tfont::get_char_depth(charinfo *c)
  442. {
  443.   vunits v = fm->get_depth(c->get_index(), size.to_scaled_points());
  444.   if (height != 0 && height != size.to_scaled_points())
  445.     return scale(v, height, size.to_scaled_points());
  446.   else
  447.     return v;
  448. }
  449.  
  450. hunits tfont::get_char_skew(charinfo *c)
  451. {
  452.   return hunits(fm->get_skew(c->get_index(), size.to_scaled_points(), slant));
  453. }
  454.  
  455. hunits tfont::get_italic_correction(charinfo *c)
  456. {
  457.   return hunits(fm->get_italic_correction(c->get_index(), size.to_scaled_points()));
  458. }
  459.  
  460. hunits tfont::get_left_italic_correction(charinfo *c)
  461. {
  462.   return hunits(fm->get_left_italic_correction(c->get_index(),
  463.                            size.to_scaled_points()));
  464. }
  465.  
  466. hunits tfont::get_subscript_correction(charinfo *c)
  467. {
  468.   return hunits(fm->get_subscript_correction(c->get_index(),
  469.                          size.to_scaled_points()));
  470. }
  471.  
  472. inline int tfont::get_input_position()
  473. {
  474.   return input_position;
  475. }
  476.  
  477. inline int tfont::contains(charinfo *ci)
  478. {
  479.   return fm->contains(ci->get_index());
  480. }
  481.  
  482. inline int tfont::get_character_type(charinfo *ci)
  483. {
  484.   return fm->get_character_type(ci->get_index());
  485. }
  486.  
  487. inline int tfont::get_bold(hunits *res)
  488. {
  489.   if (is_bold) {
  490.     *res = bold_offset;
  491.     return 1;
  492.   }
  493.   else
  494.     return 0;
  495. }
  496.  
  497. inline int tfont::get_constant_space(hunits *res)
  498. {
  499.   if (is_constant_spaced) {
  500.     *res = constant_space_width;
  501.     return 1;
  502.   }
  503.   else
  504.     return 0;
  505. }
  506.  
  507. inline hunits tfont::get_track_kern()
  508. {
  509.   return track_kern;
  510. }
  511.  
  512. inline tfont *tfont::get_plain()
  513. {
  514.   return plain_version;
  515. }
  516.  
  517. inline font_size tfont::get_size()
  518. {
  519.   return size;
  520. }
  521.  
  522. inline symbol tfont::get_name()
  523. {
  524.   return name;
  525. }
  526.  
  527. inline int tfont::get_height()
  528. {
  529.   return height;
  530. }
  531.  
  532. inline int tfont::get_slant()
  533. {
  534.   return slant;
  535. }
  536.  
  537. symbol SYMBOL_ff("ff");
  538. symbol SYMBOL_fi("fi");
  539. symbol SYMBOL_fl("fl");
  540. symbol SYMBOL_Fi("Fi");
  541. symbol SYMBOL_Fl("Fl");
  542.  
  543. charinfo *tfont::get_lig(charinfo *c1, charinfo *c2)
  544. {
  545.   if (ligature_mode == 0)
  546.     return 0;
  547.   charinfo *ci = 0;
  548.   if (c1->get_ascii_code() == 'f') {
  549.     switch (c2->get_ascii_code()) {
  550.     case 'f':
  551.       if (fm->has_ligature(font::LIG_ff))
  552.     ci = get_charinfo(SYMBOL_ff);
  553.       break;
  554.     case 'i':
  555.       if (fm->has_ligature(font::LIG_fi))
  556.     ci = get_charinfo(SYMBOL_fi);
  557.       break;
  558.     case 'l':
  559.       if (fm->has_ligature(font::LIG_fl))
  560.     ci = get_charinfo(SYMBOL_fl);
  561.       break;
  562.     }
  563.   }
  564.   else if (ligature_mode != 2 && c1->nm == SYMBOL_ff) {
  565.     switch (c2->get_ascii_code()) {
  566.     case 'i':
  567.       if (fm->has_ligature(font::LIG_ffi))
  568.     ci = get_charinfo(SYMBOL_Fi);
  569.       break;
  570.     case 'l':
  571.       if (fm->has_ligature(font::LIG_ffl))
  572.     ci = get_charinfo(SYMBOL_Fl);
  573.       break;
  574.     }
  575.   }
  576.   if (ci != 0 && fm->contains(ci->get_index()))
  577.     return ci;
  578.   return 0;
  579. }
  580.  
  581. inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res)
  582. {
  583.   if (kern_mode == 0)
  584.     return 0;
  585.   else {
  586.     int n = fm->get_kern(c1->get_index(),
  587.              c2->get_index(),
  588.              size.to_scaled_points());
  589.     if (n) {
  590.       *res = hunits(n);
  591.       return 1;
  592.     }
  593.     else
  594.       return 0;
  595.   }
  596. }
  597.  
  598. tfont *make_tfont(tfont_spec &spec)
  599. {
  600.   for (tfont *p = tfont::tfont_list; p; p = p->next)
  601.     if (*p == spec)
  602.       return p;
  603.   return new tfont(spec);
  604. }
  605.  
  606. tfont *tfont::tfont_list = 0;
  607.  
  608. tfont::tfont(tfont_spec &spec) : tfont_spec(spec)
  609. {
  610.   next = tfont_list;
  611.   tfont_list = this;
  612.   tfont_spec plain_spec = plain();
  613.   for (tfont *p = tfont_list; p; p = p->next)
  614.     if (*p == plain_spec) {
  615.       plain_version = p;
  616.       break;
  617.     }
  618.   if (!p)
  619.     plain_version = new tfont(plain_spec);
  620. }
  621.  
  622. /* output_file */
  623.  
  624. class real_output_file : public output_file {
  625.   int piped;
  626.   int printing;
  627.   virtual void really_transparent_char(unsigned char) = 0;
  628.   virtual void really_print_line(hunits x, vunits y, node *n,
  629.                  vunits before, vunits after) = 0;
  630.   virtual void really_begin_page(int pageno, vunits page_length) = 0;
  631.   virtual void really_copy_file(hunits x, vunits y, const char *filename);
  632. protected:
  633.   FILE *fp;
  634. public:
  635.   real_output_file();
  636.   ~real_output_file();
  637.   void flush();
  638.   void transparent_char(unsigned char);
  639.   void print_line(hunits x, vunits y, node *n, vunits before, vunits after);
  640.   void begin_page(int pageno, vunits page_length);
  641.   int is_printing();
  642.   void copy_file(hunits x, vunits y, const char *filename);
  643. };
  644.  
  645. class suppress_output_file : public real_output_file {
  646. public:
  647.   suppress_output_file();
  648.   void really_transparent_char(unsigned char);
  649.   void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
  650.   void really_begin_page(int pageno, vunits page_length);
  651. };
  652.  
  653. class ascii_output_file : public real_output_file {
  654. public:
  655.   ascii_output_file();
  656.   void really_transparent_char(unsigned char);
  657.   void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
  658.   void really_begin_page(int pageno, vunits page_length);
  659.   void outc(unsigned char c);
  660.   void outs(const char *s);
  661. };
  662.  
  663. void ascii_output_file::outc(unsigned char c)
  664. {
  665.   fputc(c, fp);
  666. }
  667.  
  668. void ascii_output_file::outs(const char *s)
  669. {
  670.   fputc('<', fp);
  671.   if (s)
  672.     fputs(s, fp);
  673.   fputc('>', fp);
  674. }
  675.  
  676. struct hvpair;
  677.       
  678. class troff_output_file : public real_output_file {
  679.   units hpos;
  680.   units vpos;
  681.   units output_vpos;
  682.   units output_hpos;
  683.   int force_motion;
  684.   int current_size;
  685.   int current_slant;
  686.   int current_height;
  687.   tfont *current_tfont;
  688.   int current_font_number;
  689.   symbol *font_position;
  690.   int nfont_positions;
  691.   enum { TBUF_SIZE = 256 };
  692.   char tbuf[TBUF_SIZE];
  693.   int tbuf_len;
  694.   int tbuf_kern;
  695.   int begun_page;
  696.   void do_motion();
  697.   void put(char c);
  698.   void put(unsigned char c);
  699.   void put(int i);
  700.   void put(const char *s);
  701.   void set_font(tfont *tf);
  702.   void flush_tbuf();
  703. public:
  704.   troff_output_file();
  705.   ~troff_output_file();
  706.   void trailer(vunits page_length);
  707.   void put_char(charinfo *ci, tfont *tf);
  708.   void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k);
  709.   void right(hunits);
  710.   void down(vunits);
  711.   void moveto(hunits, vunits);
  712.   void start_special();
  713.   void special_char(unsigned char c);
  714.   void end_special();
  715.   void word_marker();
  716.   void really_transparent_char(unsigned char c);
  717.   void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after);
  718.   void really_begin_page(int pageno, vunits page_length);
  719.   void really_copy_file(hunits x, vunits y, const char *filename);
  720.   void draw(char, hvpair *, int, font_size);
  721.   int get_hpos() { return hpos; }
  722.   int get_vpos() { return vpos; }
  723. };
  724.  
  725. static void put_string(const char *s, FILE *fp)
  726. {
  727.   for (; *s != '\0'; ++s)
  728.     putc(*s, fp);
  729. }
  730.  
  731. inline void troff_output_file::put(char c)
  732. {
  733.   putc(c, fp);
  734. }
  735.  
  736. inline void troff_output_file::put(unsigned char c)
  737. {
  738.   putc(c, fp);
  739. }
  740.  
  741. inline void troff_output_file::put(const char *s)
  742. {
  743.   put_string(s, fp);
  744. }
  745.  
  746. inline void troff_output_file::put(int i)
  747. {
  748.   put_string(itoa(i), fp);
  749. }
  750.  
  751. void troff_output_file::start_special()
  752. {
  753.   flush_tbuf();
  754.   do_motion();
  755.   put("x X ");
  756. }
  757.  
  758. void troff_output_file::special_char(unsigned char c)
  759. {
  760.   put(c);
  761.   if (c == '\n')
  762.     put('+');
  763. }
  764.  
  765. void troff_output_file::end_special()
  766. {
  767.   put('\n');
  768. }
  769.  
  770. inline void troff_output_file::moveto(hunits h, vunits v)
  771. {
  772.   hpos = h.to_units();
  773.   vpos = v.to_units();
  774. }
  775.  
  776. void troff_output_file::really_print_line(hunits x, vunits y, node *n,
  777.                       vunits before, vunits after)
  778. {
  779.   moveto(x, y);
  780.   while (n != 0) {
  781.     n->tprint(this);
  782.     n = n->next;
  783.   }
  784.   flush_tbuf();
  785.   // This ensures that transparent throughput will have a more predictable
  786.   // position.
  787.   do_motion();
  788.   force_motion = 1;
  789.   hpos = 0;
  790.   put('n');
  791.   put(before.to_units());
  792.   put(' ');
  793.   put(after.to_units());
  794.   put('\n');
  795. }
  796.  
  797. inline void troff_output_file::word_marker()
  798. {
  799.   flush_tbuf();
  800.   put('w');
  801. }
  802.  
  803. inline void troff_output_file::right(hunits n)
  804. {
  805.   hpos += n.to_units();
  806. }
  807.  
  808. inline void troff_output_file::down(vunits n)
  809. {
  810.   vpos += n.to_units();
  811. }
  812.  
  813. void troff_output_file::do_motion()
  814. {
  815.   if (force_motion) {
  816.     put('V');
  817.     put(vpos);
  818.     put('\n');
  819.     put('H');
  820.     put(hpos);
  821.     put('\n');
  822.   }
  823.   else {
  824.     if (hpos != output_hpos) {
  825.       units n = hpos - output_hpos;
  826.       if (n > 0 && n < hpos) {
  827.     put('h');
  828.     put(n);
  829.       }
  830.       else {
  831.     put('H');
  832.     put(hpos);
  833.       }
  834.       put('\n');
  835.     }
  836.     if (vpos != output_vpos) {
  837.       units n = vpos - output_vpos;
  838.       if (n > 0 && n < vpos) {
  839.     put('v');
  840.     put(n);
  841.       }
  842.       else {
  843.     put('V');
  844.     put(vpos);
  845.       }
  846.       put('\n');
  847.     }
  848.   }
  849.   output_vpos = vpos;
  850.   output_hpos = hpos;
  851.   force_motion = 0;
  852. }
  853.  
  854. void troff_output_file::flush_tbuf()
  855. {
  856.   if (tbuf_len == 0)
  857.     return;
  858.   if (tbuf_kern == 0)
  859.     put('t');
  860.   else {
  861.     put('u');
  862.     put(tbuf_kern);
  863.     put(' ');
  864.   }
  865.   for (int i = 0; i < tbuf_len; i++)
  866.     put(tbuf[i]);
  867.   put('\n');
  868.   tbuf_len = 0;
  869. }
  870.  
  871. void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
  872.                        hunits k)
  873. {
  874.   if (tf != current_tfont) {
  875.     flush_tbuf();
  876.     set_font(tf);
  877.   }
  878.   char c = ci->get_ascii_code();
  879.   int kk = k.to_units();
  880.   if (c == '\0') {
  881.     flush_tbuf();
  882.     do_motion();
  883.     if (ci->numbered()) {
  884.       put('N');
  885.       put(ci->get_number());
  886.     }
  887.     else {
  888.       put('C');
  889.       const char *s = ci->nm.contents();
  890.       if (s[1] == 0) {
  891.     put('\\');
  892.     put(s[0]);
  893.       }
  894.       else
  895.     put(s);
  896.     }
  897.     put('\n');
  898.     hpos += w.to_units() + kk;
  899.   }
  900.   else if (tcommand_flag) {
  901.     if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos
  902.     && kk == tbuf_kern
  903.     && tbuf_len < TBUF_SIZE) {
  904.       tbuf[tbuf_len++] = c;
  905.       output_hpos += w.to_units() + kk;
  906.       hpos = output_hpos;
  907.       return;
  908.     }
  909.     flush_tbuf();
  910.     do_motion();
  911.     tbuf[tbuf_len++] = c;
  912.     output_hpos += w.to_units() + kk;
  913.     tbuf_kern = kk;
  914.     hpos = output_hpos;
  915.   }
  916.   else {
  917.     // flush_tbuf();
  918.     int n = hpos - output_hpos;
  919.     if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) {
  920.       put(char(n/10 + '0'));
  921.       put(char(n%10 + '0'));
  922.       put(c);
  923.       output_hpos = hpos;
  924.     }
  925.     else {
  926.       do_motion();
  927.       put('c');
  928.       put(c);
  929.     }
  930.     hpos += w.to_units() + kk;
  931.   }
  932. }
  933.  
  934. void troff_output_file::put_char(charinfo *ci, tfont *tf)
  935. {
  936.   flush_tbuf();
  937.   if (tf != current_tfont)
  938.     set_font(tf);
  939.   char c = ci->get_ascii_code();
  940.   if (c == '\0') {
  941.     do_motion();
  942.     if (ci->numbered()) {
  943.       put('N');
  944.       put(ci->get_number());
  945.     }
  946.     else {
  947.       put('C');
  948.       const char *s = ci->nm.contents();
  949.       if (s[1] == 0) {
  950.     put('\\');
  951.     put(s[0]);
  952.       }
  953.       else
  954.     put(s);
  955.     }
  956.     put('\n');
  957.   }
  958.   else {
  959.     int n = hpos - output_hpos;
  960.     if (vpos == output_vpos && n > 0 && n < 100) {
  961.       put(char(n/10 + '0'));
  962.       put(char(n%10 + '0'));
  963.       put(c);
  964.       output_hpos = hpos;
  965.     }
  966.     else {
  967.       do_motion();
  968.       put('c');
  969.       put(c);
  970.     }
  971.   }
  972. }
  973.  
  974. void troff_output_file::set_font(tfont *tf)
  975. {
  976.   if (current_tfont == tf)
  977.     return;
  978.   int n = tf->get_input_position();
  979.   symbol nm = tf->get_name();
  980.   if (n >= nfont_positions || font_position[n] != nm) {
  981.     put("x font ");
  982.     put(n);
  983.     put(' ');
  984.     put(nm.contents());
  985.     put('\n');
  986.     if (n >= nfont_positions) {
  987.       int old_nfont_positions = nfont_positions;
  988.       symbol *old_font_position = font_position;
  989.       nfont_positions *= 3;
  990.       nfont_positions /= 2;
  991.       if (nfont_positions <= n)
  992.     nfont_positions = n + 10;
  993.       font_position = new symbol[nfont_positions];
  994.       memcpy(font_position, old_font_position,
  995.          old_nfont_positions*sizeof(symbol));
  996.       a_delete old_font_position;
  997.     }
  998.     font_position[n] = nm;
  999.   }
  1000.   if (current_font_number != n) {
  1001.     put('f');
  1002.     put(n);
  1003.     put('\n');
  1004.     current_font_number = n;
  1005.   }
  1006.   int size = tf->get_size().to_scaled_points();
  1007.   if (current_size != size) {
  1008.     put('s');
  1009.     put(size);
  1010.     put('\n');
  1011.     current_size = size;
  1012.   }
  1013.   int slant = tf->get_slant();
  1014.   if (current_slant != slant) {
  1015.     put("x Slant ");
  1016.     put(slant);
  1017.     put('\n');
  1018.     current_slant = slant;
  1019.   }
  1020.   int height = tf->get_height();
  1021.   if (current_height != height) {
  1022.     put("x Height ");
  1023.     put(height == 0 ? current_size : height);
  1024.     put('\n');
  1025.     current_height = height;
  1026.   }
  1027.   current_tfont = tf;
  1028. }
  1029.  
  1030. void troff_output_file::draw(char code, hvpair *point, int npoints,
  1031.                  font_size fsize)
  1032. {
  1033.   flush_tbuf();
  1034.   do_motion();
  1035.   int size = fsize.to_scaled_points();
  1036.   if (current_size != size) {
  1037.     put('s');
  1038.     put(size);
  1039.     put('\n');
  1040.     current_size = size;
  1041.     current_tfont = 0;
  1042.   }
  1043.   put('D');
  1044.   put(code);
  1045.   int i;
  1046.   if (code == 'c') {
  1047.     put(' ');
  1048.     put(point[0].h.to_units());
  1049.   }
  1050.   else
  1051.     for (i = 0; i < npoints; i++) {
  1052.       put(' ');
  1053.       put(point[i].h.to_units());
  1054.       put(' ');
  1055.       put(point[i].v.to_units());
  1056.     }
  1057.   for (i = 0; i < npoints; i++)
  1058.     output_hpos += point[i].h.to_units();
  1059.   hpos = output_hpos;
  1060.   if (code != 'e') {
  1061.     for (i = 0; i < npoints; i++)
  1062.       output_vpos += point[i].v.to_units();
  1063.     vpos = output_vpos;
  1064.   }
  1065.   put('\n');
  1066. }
  1067.  
  1068. void troff_output_file::really_begin_page(int pageno, vunits page_length)
  1069. {
  1070.   flush_tbuf();
  1071.   if (begun_page) {
  1072.     if (page_length > V0) {
  1073.       put('V');
  1074.       put(page_length.to_units());
  1075.       put('\n');
  1076.     }
  1077.   }
  1078.   else
  1079.     begun_page = 1;
  1080.   current_tfont = 0;
  1081.   current_font_number = -1;
  1082.   current_size = 0;
  1083.   // current_height = 0;
  1084.   // current_slant = 0;
  1085.   hpos = 0;
  1086.   vpos = 0;
  1087.   output_hpos = 0;
  1088.   output_vpos = 0;
  1089.   force_motion = 1;
  1090.   for (int i = 0; i < nfont_positions; i++)
  1091.     font_position[i] = NULL_SYMBOL;
  1092.   put('p');
  1093.   put(pageno);
  1094.   put('\n');
  1095. }
  1096.  
  1097. void troff_output_file::really_copy_file(hunits x, vunits y, const char *filename)
  1098. {
  1099.   moveto(x, y);
  1100.   flush_tbuf();
  1101.   do_motion();
  1102.   errno = 0;
  1103.   FILE *ifp = fopen(filename, "r");
  1104.   if (ifp == 0)
  1105.     error("can't open `%1': %2", filename, strerror(errno));
  1106.   else {
  1107.     int c;
  1108.     while ((c = getc(ifp)) != EOF)
  1109.       put(char(c));
  1110.     fclose(ifp);
  1111.   }
  1112.   force_motion = 1;
  1113.   current_size = 0;
  1114.   current_tfont = 0;
  1115.   current_font_number = -1;
  1116.   for (int i = 0; i < nfont_positions; i++)
  1117.     font_position[i] = NULL_SYMBOL;
  1118. }
  1119.   
  1120. void troff_output_file::really_transparent_char(unsigned char c)
  1121. {
  1122.   put(c);
  1123. }
  1124.  
  1125. troff_output_file::~troff_output_file()
  1126. {
  1127.   a_delete font_position;
  1128. }
  1129.  
  1130. void troff_output_file::trailer(vunits page_length)
  1131. {
  1132.   flush_tbuf();
  1133.   if (page_length > V0) {
  1134.     put("x trailer\n");
  1135.     put('V');
  1136.     put(page_length.to_units());
  1137.     put('\n');
  1138.   }
  1139.   put("x stop\n");
  1140. }
  1141.  
  1142. troff_output_file::troff_output_file()
  1143. : current_height(0), current_slant(0), tbuf_len(0), nfont_positions(10),
  1144.   begun_page(0)
  1145. {
  1146.   font_position = new symbol[nfont_positions];
  1147.   put("x T ");
  1148.   put(device);
  1149.   put('\n');
  1150.   put("x res ");
  1151.   put(units_per_inch);
  1152.   put(' ');
  1153.   put(hresolution);
  1154.   put(' ');
  1155.   put(vresolution);
  1156.   put('\n');
  1157.   put("x init\n");
  1158. }
  1159.  
  1160. /* output_file */
  1161.  
  1162. output_file *the_output = 0;
  1163.  
  1164. output_file::output_file()
  1165. {
  1166. }
  1167.  
  1168. output_file::~output_file()
  1169. {
  1170. }
  1171.  
  1172. void output_file::trailer(vunits)
  1173. {
  1174. }
  1175.  
  1176. real_output_file::real_output_file()
  1177. : printing(0)
  1178. {
  1179.   if (pipe_command) {
  1180.     if ((fp = popen(pipe_command, "w")) != 0) {
  1181.       piped = 1;
  1182.       return;
  1183.     }
  1184.     error("pipe open failed: %1", strerror(errno));
  1185.   }
  1186.   piped = 0;
  1187.   fp = stdout;
  1188. }
  1189.  
  1190. real_output_file::~real_output_file()
  1191. {
  1192.   if (!fp)
  1193.     return;
  1194.   // To avoid looping, set fp to 0 before calling fatal().
  1195.   if (ferror(fp) || fflush(fp) < 0) {
  1196.     fp = 0;
  1197.     fatal("error writing output file");
  1198.   }
  1199.   if (piped) {
  1200.     int result = pclose(fp);
  1201.     fp = 0;
  1202.     if (result < 0)
  1203.       fatal("pclose failed");
  1204.     if ((result & 0x7f) != 0)
  1205.       error("output process `%1' got fatal signal %2",
  1206.         pipe_command, result & 0x7f);
  1207.     else {
  1208.       int exit_status = (result >> 8) & 0xff;
  1209.       if (exit_status != 0)
  1210.     error("output process `%1' exited with status %2",
  1211.           pipe_command, exit_status);
  1212.     }
  1213.   }
  1214.   else if (fclose(fp) < 0) {
  1215.     fp = 0;
  1216.     fatal("error closing output file");
  1217.   }
  1218. }
  1219.  
  1220. void real_output_file::flush()
  1221. {
  1222.   if (fflush(fp) < 0)
  1223.     fatal("error writing output file");
  1224. }
  1225.  
  1226. int real_output_file::is_printing()
  1227. {
  1228.   return printing;
  1229. }
  1230.  
  1231. void real_output_file::begin_page(int pageno, vunits page_length)
  1232. {
  1233.   printing = in_output_page_list(pageno);
  1234.   if (printing)
  1235.     really_begin_page(pageno, page_length);
  1236. }
  1237.  
  1238. void real_output_file::copy_file(hunits x, vunits y, const char *filename)
  1239. {
  1240.   if (printing)
  1241.     really_copy_file(x, y, filename);
  1242. }
  1243.  
  1244. void real_output_file::transparent_char(unsigned char c)
  1245. {
  1246.   if (printing)
  1247.     really_transparent_char(c);
  1248. }
  1249.  
  1250. void real_output_file::print_line(hunits x, vunits y, node *n,
  1251.                  vunits before, vunits after)
  1252. {
  1253.   if (printing)
  1254.     really_print_line(x, y, n, before, after);
  1255.   delete_node_list(n);
  1256. }
  1257.  
  1258. void real_output_file::really_copy_file(hunits, vunits, const char *)
  1259. {
  1260.   // do nothing
  1261. }
  1262.  
  1263.  
  1264. /* ascii_output_file */
  1265.  
  1266. void ascii_output_file::really_transparent_char(unsigned char c)
  1267. {
  1268.   putc(c, fp);
  1269. }
  1270.  
  1271. void ascii_output_file::really_print_line(hunits, vunits, node *n, vunits, vunits)
  1272. {
  1273.   while (n != 0) {
  1274.     n->ascii_print(this);
  1275.     n = n->next;
  1276.   }
  1277.   fputc('\n', fp);
  1278. }
  1279.  
  1280. void ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/)
  1281. {
  1282.   fputs("<beginning of page>\n", fp);
  1283. }
  1284.  
  1285. ascii_output_file::ascii_output_file()
  1286. {
  1287. }
  1288.  
  1289. /* suppress_output_file */
  1290.  
  1291. suppress_output_file::suppress_output_file()
  1292. {
  1293. }
  1294.  
  1295. void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits)
  1296. {
  1297. }
  1298.  
  1299. void suppress_output_file::really_begin_page(int, vunits)
  1300. {
  1301. }
  1302.  
  1303. void suppress_output_file::really_transparent_char(unsigned char)
  1304. {
  1305. }
  1306.  
  1307. /* glyphs, ligatures, kerns, discretionary breaks */
  1308.  
  1309. class glyph_node : public node {
  1310.   static glyph_node *free_list;
  1311. protected:
  1312.   charinfo *ci;
  1313.   tfont *tf;
  1314. #ifdef STORE_WIDTH
  1315.   hunits wid;
  1316.   glyph_node(charinfo *, tfont *, hunits, node * = 0);
  1317. #endif
  1318. public:
  1319.   void *operator new(size_t);
  1320.   void operator delete(void *);
  1321.   glyph_node(charinfo *, tfont *, node * = 0);
  1322.   ~glyph_node() {}
  1323.   node *copy();
  1324.   node *merge_glyph_node(glyph_node *);
  1325.   node *merge_self(node *);
  1326.   hunits width();
  1327.   node *last_char_node();
  1328.   units size();
  1329.   void vertical_extent(vunits *, vunits *);
  1330.   hunits subscript_correction();
  1331.   hunits italic_correction();
  1332.   hunits left_italic_correction();
  1333.   hunits skew();
  1334.   hyphenation_type get_hyphenation_type();
  1335.   tfont *get_tfont();
  1336.   void tprint(troff_output_file *);
  1337.   void zero_width_tprint(troff_output_file *);
  1338.   hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
  1339.   node *add_self(node *, hyphen_list **);
  1340.   int ends_sentence();
  1341.   int overlaps_vertically();
  1342.   int overlaps_horizontally();
  1343.   void ascii_print(ascii_output_file *);
  1344.   void asciify(macro *);
  1345.   int character_type();
  1346.   int same(node *);
  1347.   const char *type();
  1348. };
  1349.  
  1350. glyph_node *glyph_node::free_list = 0;
  1351.  
  1352. class ligature_node : public glyph_node {
  1353.   node *n1;
  1354.   node *n2;
  1355. #ifdef STORE_WIDTH
  1356.   ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0);
  1357. #endif
  1358. public:
  1359.   void *operator new(size_t);
  1360.   void operator delete(void *);
  1361.   ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0);
  1362.   ~ligature_node();
  1363.   node *copy();
  1364.   node *add_self(node *, hyphen_list **);
  1365.   hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
  1366.   void ascii_print(ascii_output_file *);
  1367.   void asciify(macro *);
  1368.   int same(node *);
  1369.   const char *type();
  1370. };
  1371.  
  1372. class kern_pair_node : public node {
  1373.   hunits amount;
  1374.   node *n1;
  1375.   node *n2;
  1376. public:
  1377.   kern_pair_node(hunits n, node *first, node *second, node *x = 0);
  1378.   ~kern_pair_node();
  1379.   node *copy();
  1380.   node *merge_glyph_node(glyph_node *);
  1381.   node *add_self(node *, hyphen_list **);
  1382.   hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
  1383.   node *add_discretionary_hyphen();
  1384.   hunits width();
  1385.   node *last_char_node();
  1386.   hunits italic_correction();
  1387.   hunits subscript_correction();
  1388.   void tprint(troff_output_file *);
  1389.   hyphenation_type get_hyphenation_type();
  1390.   int ends_sentence();
  1391.   void ascii_print(ascii_output_file *);
  1392.   void asciify(macro *);
  1393.   int same(node *);
  1394.   const char *type();
  1395. };
  1396.  
  1397. class dbreak_node : public node {
  1398.   node *none;
  1399.   node *pre;
  1400.   node *post;
  1401. public:
  1402.   dbreak_node(node *n, node *p, node *x = 0);
  1403.   ~dbreak_node();
  1404.   node *copy();
  1405.   node *merge_glyph_node(glyph_node *);
  1406.   node *add_discretionary_hyphen();
  1407.   hunits width();
  1408.   node *last_char_node();
  1409.   hunits italic_correction();
  1410.   hunits subscript_correction();
  1411.   void tprint(troff_output_file *);
  1412.   breakpoint *get_breakpoints(hunits width, int ns, breakpoint *rest = 0,
  1413.                   int is_inner = 0);
  1414.   int nbreaks();
  1415.   int ends_sentence();
  1416.   void split(int, node **, node **);
  1417.   hyphenation_type get_hyphenation_type();
  1418.   void ascii_print(ascii_output_file *);
  1419.   void asciify(macro *);
  1420.   int same(node *);
  1421.   const char *type();
  1422. };
  1423.  
  1424. void *glyph_node::operator new(size_t n)
  1425. {
  1426.   assert(n == sizeof(glyph_node));
  1427.   if (!free_list) {
  1428.     const int BLOCK = 1024;
  1429.     free_list = (glyph_node *)new char[sizeof(glyph_node)*BLOCK];
  1430.     for (int i = 0; i < BLOCK - 1; i++)
  1431.       free_list[i].next = free_list + i + 1;
  1432.     free_list[BLOCK-1].next = 0;
  1433.   }
  1434.   glyph_node *p = free_list;
  1435.   free_list = (glyph_node *)(free_list->next);
  1436.   p->next = 0;
  1437.   return p;
  1438. }
  1439.  
  1440. void *ligature_node::operator new(size_t n)
  1441. {
  1442.   return new char[n];
  1443. }
  1444.  
  1445. void glyph_node::operator delete(void *p)
  1446. {
  1447.   if (p) {
  1448.     ((glyph_node *)p)->next = free_list;
  1449.     free_list = (glyph_node *)p;
  1450.   }
  1451. }
  1452.  
  1453. void ligature_node::operator delete(void *p)
  1454. {
  1455.   delete p;
  1456. }
  1457.  
  1458. glyph_node::glyph_node(charinfo *c, tfont *t, node *x)
  1459.      : ci(c), tf(t), node(x)
  1460. {
  1461. #ifdef STORE_WIDTH
  1462.   wid = tf->get_width(ci);
  1463. #endif
  1464. }
  1465.  
  1466. #ifdef STORE_WIDTH
  1467. glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x)
  1468.      : ci(c), tf(t), wid(w), node(x)
  1469. {
  1470. }
  1471. #endif
  1472.  
  1473. node *glyph_node::copy()
  1474. {
  1475. #ifdef STORE_WIDTH
  1476.   return new glyph_node(ci, tf, wid);
  1477. #else
  1478.   return new glyph_node(ci, tf);
  1479. #endif
  1480. }
  1481.  
  1482. node *glyph_node::merge_self(node *nd)
  1483. {
  1484.   return nd->merge_glyph_node(this);
  1485. }
  1486.  
  1487. int glyph_node::character_type()
  1488. {
  1489.   return tf->get_character_type(ci);
  1490. }
  1491.  
  1492. node *glyph_node::add_self(node *n, hyphen_list **p)
  1493. {
  1494.   assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
  1495.   next = 0;
  1496.   node *nn;
  1497.   if (n == 0 || (nn = n->merge_glyph_node(this)) == 0) {
  1498.     next = n;
  1499.     nn = this;
  1500.   }
  1501.   if ((*p)->hyphen)
  1502.     nn = nn->add_discretionary_hyphen();
  1503.   hyphen_list *pp = *p;
  1504.   *p = (*p)->next;
  1505.   delete pp;
  1506.   return nn;
  1507. }
  1508.  
  1509. int glyph_node::overlaps_horizontally()
  1510. {
  1511.   return ci->overlaps_horizontally();
  1512. }
  1513.  
  1514. int glyph_node::overlaps_vertically()
  1515. {
  1516.   return ci->overlaps_vertically();
  1517. }
  1518.  
  1519. units glyph_node::size()
  1520. {
  1521.   return tf->get_size().to_units();
  1522. }
  1523.  
  1524. hyphen_list *glyph_node::get_hyphen_list(hyphen_list *tail)
  1525. {
  1526.   return new hyphen_list(ci->get_hyphenation_code(), tail);
  1527. }
  1528.  
  1529.  
  1530. tfont *node::get_tfont()
  1531. {
  1532.   return 0;
  1533. }
  1534.  
  1535. tfont *glyph_node::get_tfont()
  1536. {
  1537.   return tf;
  1538. }
  1539.  
  1540. node *node::merge_glyph_node(glyph_node * /*gn*/)
  1541. {
  1542.   return 0;
  1543. }
  1544.  
  1545. node *glyph_node::merge_glyph_node(glyph_node *gn)
  1546. {
  1547.   if (tf == gn->tf) {
  1548.     charinfo *lig;
  1549.     if ((lig = tf->get_lig(ci, gn->ci)) != 0) {
  1550.       node *next1 = next;
  1551.       next = 0;
  1552.       return new ligature_node(lig, tf, this, gn, next1);
  1553.     }
  1554.     hunits kern;
  1555.     if (tf->get_kern(ci, gn->ci, &kern)) {
  1556.       node *next1 = next;
  1557.       next = 0;
  1558.       return new kern_pair_node(kern, this, gn, next1);
  1559.     }
  1560.   }
  1561.   return 0;
  1562. }
  1563.  
  1564. #ifdef STORE_WIDTH
  1565. inline
  1566. #endif
  1567. hunits glyph_node::width()
  1568. {
  1569. #ifdef STORE_WIDTH
  1570.   return wid;
  1571. #else
  1572.   return tf->get_width(ci);
  1573. #endif
  1574. }
  1575.  
  1576. node *glyph_node::last_char_node()
  1577. {
  1578.   return this;
  1579. }
  1580.  
  1581. void glyph_node::vertical_extent(vunits *min, vunits *max)
  1582. {
  1583.   *min = -tf->get_char_height(ci);
  1584.   *max = tf->get_char_depth(ci);
  1585. }
  1586.  
  1587. hunits glyph_node::skew()
  1588. {
  1589.   return tf->get_char_skew(ci);
  1590. }
  1591.  
  1592. hunits glyph_node::subscript_correction()
  1593. {
  1594.   return tf->get_subscript_correction(ci);
  1595. }
  1596.  
  1597. hunits glyph_node::italic_correction()
  1598. {
  1599.   return tf->get_italic_correction(ci);
  1600. }
  1601.  
  1602. hunits glyph_node::left_italic_correction()
  1603. {
  1604.   return tf->get_left_italic_correction(ci);
  1605. }
  1606.  
  1607. hyphenation_type glyph_node::get_hyphenation_type()
  1608. {
  1609.   return HYPHEN_MIDDLE;
  1610. }
  1611.  
  1612. int glyph_node::ends_sentence()
  1613. {
  1614.   if (ci->ends_sentence())
  1615.     return 1;
  1616.   else if (ci->transparent())
  1617.     return 2;
  1618.   else
  1619.     return 0;
  1620. }
  1621.  
  1622. void glyph_node::ascii_print(ascii_output_file *ascii)
  1623. {
  1624.   unsigned char c = ci->get_ascii_code();
  1625.   if (c != 0)
  1626.     ascii->outc(c);
  1627.   else
  1628.     ascii->outs(ci->nm.contents());
  1629. }
  1630.  
  1631. ligature_node::ligature_node(charinfo *c, tfont *t, 
  1632.                  node *gn1, node *gn2, node *x)
  1633.      : glyph_node(c, t, x), n1(gn1), n2(gn2)
  1634. {
  1635. }
  1636.  
  1637. #ifdef STORE_WIDTH
  1638. ligature_node::ligature_node(charinfo *c, tfont *t, hunits w,
  1639.                    node *gn1, node *gn2, node *x)
  1640.      : glyph_node(c, t, w, x), n1(gn1), n2(gn2)
  1641. {
  1642. }
  1643. #endif
  1644.  
  1645. ligature_node::~ligature_node()
  1646. {
  1647.   delete n1;
  1648.   delete n2;
  1649. }
  1650.  
  1651. node *ligature_node::copy()
  1652. {
  1653. #ifdef STORE_WIDTH
  1654.   return new ligature_node(ci, tf, wid, n1->copy(), n2->copy());
  1655. #else
  1656.   return new ligature_node(ci, tf, n1->copy(), n2->copy());
  1657. #endif
  1658. }
  1659.  
  1660. void ligature_node::ascii_print(ascii_output_file *ascii)
  1661. {
  1662.   n1->ascii_print(ascii);
  1663.   n2->ascii_print(ascii);
  1664. }
  1665.  
  1666. hyphen_list *ligature_node::get_hyphen_list(hyphen_list *tail)
  1667. {
  1668.   return n1->get_hyphen_list(n2->get_hyphen_list(tail));
  1669. }
  1670.  
  1671. node *ligature_node::add_self(node *n, hyphen_list **p)
  1672. {
  1673.   n = n1->add_self(n, p);
  1674.   n = n2->add_self(n, p);
  1675.   n1 = n2 = 0;
  1676.   delete this;
  1677.   return n;
  1678. }
  1679.  
  1680. kern_pair_node::kern_pair_node(hunits n, node *first, node *second, node *x)
  1681.      : node(x), n1(first), n2(second), amount(n)
  1682. {
  1683. }
  1684.  
  1685. dbreak_node::dbreak_node(node *n, node *p, node *x) 
  1686.      : node(x), none(n), pre(p), post(0)
  1687. {
  1688. }
  1689.  
  1690. node *dbreak_node::merge_glyph_node(glyph_node *gn)
  1691. {
  1692.   glyph_node *gn2 = (glyph_node *)gn->copy();
  1693.   node *new_none = none ? none->merge_glyph_node(gn) : 0;
  1694.   node *new_post = post ? post->merge_glyph_node(gn2) : 0;
  1695.   if (new_none == 0 && new_post == 0) {
  1696.     delete gn2;
  1697.     return 0;
  1698.   }
  1699.   if (new_none != 0)
  1700.     none = new_none;
  1701.   else {
  1702.     gn->next = none;
  1703.     none = gn;
  1704.   }
  1705.   if (new_post != 0)
  1706.     post = new_post;
  1707.   else {
  1708.     gn2->next = post;
  1709.     post = gn2;
  1710.   }
  1711.   return this;
  1712. }
  1713.  
  1714. node *kern_pair_node::merge_glyph_node(glyph_node *gn)
  1715. {
  1716.   node *nd = n2->merge_glyph_node(gn);
  1717.   if (nd == 0)
  1718.     return 0;
  1719.   n2 = nd;
  1720.   nd = n2->merge_self(n1);
  1721.   if (nd) {
  1722.     nd->next = next;
  1723.     n1 = 0;
  1724.     n2 = 0;
  1725.     delete this;
  1726.     return nd;
  1727.   }
  1728.   return this;
  1729. }
  1730.  
  1731.  
  1732. hunits kern_pair_node::italic_correction()
  1733. {
  1734.   return n2->italic_correction();
  1735. }
  1736.  
  1737. hunits kern_pair_node::subscript_correction()
  1738. {
  1739.   return n2->subscript_correction();
  1740. }
  1741.  
  1742. node *kern_pair_node::add_discretionary_hyphen()
  1743. {
  1744.   tfont *tf = n2->get_tfont();
  1745.   if (tf) {
  1746.     if (tf->contains(soft_hyphen_char)) {
  1747.       node *next1 = next;
  1748.       next = 0;
  1749.       node *n = copy();
  1750.       glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
  1751.       node *nn = n->merge_glyph_node(gn);
  1752.       if (nn == 0) {
  1753.     gn->next = n;
  1754.     nn = gn;
  1755.       }
  1756.       return new dbreak_node(this, nn, next1);
  1757.     }
  1758.   }
  1759.   return this;
  1760. }
  1761.  
  1762.  
  1763. kern_pair_node::~kern_pair_node()
  1764. {
  1765.   if (n1 != 0)
  1766.     delete n1;
  1767.   if (n2 != 0)
  1768.     delete n2;
  1769. }
  1770.  
  1771. dbreak_node::~dbreak_node()
  1772. {
  1773.   delete_node_list(pre);
  1774.   delete_node_list(post);
  1775.   delete_node_list(none);
  1776. }
  1777.  
  1778. node *kern_pair_node::copy()
  1779. {
  1780.   return new kern_pair_node(amount, n1->copy(), n2->copy());
  1781. }
  1782.  
  1783. node *copy_node_list(node *n)
  1784. {
  1785.   node *p = 0;
  1786.   while (n != 0) {
  1787.     node *nn = n->copy();
  1788.     nn->next = p;
  1789.     p = nn;
  1790.     n = n->next;
  1791.   }
  1792.   while (p != 0) {
  1793.     node *pp = p->next;
  1794.     p->next = n;
  1795.     n = p;
  1796.     p = pp;
  1797.   }
  1798.   return n;
  1799. }
  1800.  
  1801. void delete_node_list(node *n)
  1802. {
  1803.   while (n != 0) {
  1804.     node *tem = n;
  1805.     n = n->next;
  1806.     delete tem;
  1807.   }
  1808. }
  1809.  
  1810. node *dbreak_node::copy()
  1811. {
  1812.   dbreak_node *p = new dbreak_node(copy_node_list(none), copy_node_list(pre));
  1813.   p->post = copy_node_list(post);
  1814.   return p;
  1815. }
  1816.  
  1817. hyphen_list *node::get_hyphen_list(hyphen_list *tail)
  1818. {
  1819.   return tail;
  1820. }
  1821.  
  1822.  
  1823. hyphen_list *kern_pair_node::get_hyphen_list(hyphen_list *tail)
  1824. {
  1825.   return n1->get_hyphen_list(n2->get_hyphen_list(tail));
  1826. }
  1827.  
  1828. class hyphen_inhibitor_node : public node {
  1829. public:
  1830.   hyphen_inhibitor_node(node *nd = 0);
  1831.   node *copy();
  1832.   int same(node *);
  1833.   const char *type();
  1834.   hyphenation_type get_hyphenation_type();
  1835. };
  1836.  
  1837. hyphen_inhibitor_node::hyphen_inhibitor_node(node *nd) : node(nd)
  1838. {
  1839. }
  1840.  
  1841. node *hyphen_inhibitor_node::copy()
  1842. {
  1843.   return new hyphen_inhibitor_node;
  1844. }
  1845.  
  1846. int hyphen_inhibitor_node::same(node *)
  1847. {
  1848.   return 1;
  1849. }
  1850.  
  1851. const char *hyphen_inhibitor_node::type()
  1852. {
  1853.   return "hyphen_inhibitor_node";
  1854. }
  1855.  
  1856. hyphenation_type hyphen_inhibitor_node::get_hyphenation_type()
  1857. {
  1858.   return HYPHEN_INHIBIT;
  1859. }
  1860.  
  1861. /* add_discretionary_hyphen methods */
  1862.  
  1863. node *dbreak_node::add_discretionary_hyphen()
  1864. {
  1865.   if (post)
  1866.     post = post->add_discretionary_hyphen();
  1867.   if (none)
  1868.     none = none->add_discretionary_hyphen();
  1869.   return this;
  1870. }
  1871.  
  1872.  
  1873. node *node::add_discretionary_hyphen()
  1874. {
  1875.   tfont *tf = get_tfont();
  1876.   if (!tf)
  1877.     return new hyphen_inhibitor_node(this);
  1878.   if (tf->contains(soft_hyphen_char)) {
  1879.     node *next1 = next;
  1880.     next = 0;
  1881.     node *n = copy();
  1882.     glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
  1883.     node *n1 = n->merge_glyph_node(gn);
  1884.     if (n1 == 0) {
  1885.       gn->next = n;
  1886.       n1 = gn;
  1887.     }
  1888.     return new dbreak_node(this, n1, next1);
  1889.   }
  1890.   return this;
  1891. }
  1892.  
  1893.  
  1894. node *node::merge_self(node *)
  1895. {
  1896.   return 0;
  1897. }
  1898.  
  1899. node *node::add_self(node *n, hyphen_list ** /*p*/)
  1900. {
  1901.   next = n;
  1902.   return this;
  1903. }
  1904.  
  1905. node *kern_pair_node::add_self(node *n, hyphen_list **p)
  1906. {
  1907.   n = n1->add_self(n, p);
  1908.   n = n2->add_self(n, p);
  1909.   n1 = n2 = 0;
  1910.   delete this;
  1911.   return n;
  1912. }
  1913.  
  1914.  
  1915. hunits node::width()
  1916. {
  1917.   return H0;
  1918. }
  1919.  
  1920. node *node::last_char_node()
  1921. {
  1922.   return 0;
  1923. }
  1924.  
  1925. hunits hmotion_node::width()
  1926. {
  1927.   return n;
  1928. }
  1929.  
  1930. units node::size()
  1931. {
  1932.   return points_to_units(10);
  1933. }
  1934.  
  1935. hunits kern_pair_node::width()
  1936. {
  1937.   return n1->width() + n2->width() + amount;
  1938. }
  1939.  
  1940. node *kern_pair_node::last_char_node()
  1941. {
  1942.   node *nd = n2->last_char_node();
  1943.   if (nd)
  1944.     return nd;
  1945.   return n1->last_char_node();
  1946. }
  1947.  
  1948. hunits dbreak_node::width()
  1949. {
  1950.   hunits x = H0;
  1951.   for (node *n = none; n != 0; n = n->next)
  1952.     x += n->width();
  1953.   return x;
  1954. }
  1955.  
  1956. node *dbreak_node::last_char_node()
  1957. {
  1958.   for (node *n = none; n; n = n->next) {
  1959.     node *last = n->last_char_node();
  1960.     if (last)
  1961.       return last;
  1962.   }
  1963.   return 0;
  1964. }
  1965.  
  1966. hunits dbreak_node::italic_correction()
  1967. {
  1968.   return none ? none->italic_correction() : H0;
  1969. }
  1970.  
  1971. hunits dbreak_node::subscript_correction()
  1972. {
  1973.   return none ? none->subscript_correction() : H0;
  1974. }
  1975.  
  1976. class italic_corrected_node : public node {
  1977.   node *n;
  1978.   hunits x;
  1979. public:
  1980.   italic_corrected_node(node *, hunits, node * = 0);
  1981.   ~italic_corrected_node();
  1982.   node *copy();
  1983.   void ascii_print(ascii_output_file *);
  1984.   void asciify(macro *m);
  1985.   hunits width();
  1986.   node *last_char_node();
  1987.   void vertical_extent(vunits *, vunits *);
  1988.   int ends_sentence();
  1989.   int overlaps_horizontally();
  1990.   int overlaps_vertically();
  1991.   int same(node *);
  1992.   hyphenation_type get_hyphenation_type();
  1993.   tfont *get_tfont();
  1994.   hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
  1995.   int character_type();
  1996.   void tprint(troff_output_file *);
  1997.   hunits subscript_correction();
  1998.   hunits skew();
  1999.   node *add_self(node *, hyphen_list **);
  2000.   const char *type();
  2001. };
  2002.  
  2003. node *node::add_italic_correction(hunits *width)
  2004. {
  2005.   hunits ic = italic_correction();
  2006.   if (ic.is_zero())
  2007.     return this;
  2008.   else {
  2009.     node *next1 = next;
  2010.     next = 0;
  2011.     *width += ic;
  2012.     return new italic_corrected_node(this, ic, next1);
  2013.   }
  2014. }
  2015.  
  2016. italic_corrected_node::italic_corrected_node(node *nn, hunits xx, node *p)
  2017. : n(nn), x(xx), node(p)
  2018. {
  2019.   assert(n != 0);
  2020. }
  2021.  
  2022. italic_corrected_node::~italic_corrected_node()
  2023. {
  2024.   delete n;
  2025. }
  2026.  
  2027. node *italic_corrected_node::copy()
  2028. {
  2029.   return new italic_corrected_node(n->copy(), x);
  2030. }
  2031.  
  2032. hunits italic_corrected_node::width()
  2033. {
  2034.   return n->width() + x;
  2035. }
  2036.  
  2037. void italic_corrected_node::vertical_extent(vunits *min, vunits *max)
  2038. {
  2039.   n->vertical_extent(min, max);
  2040. }
  2041.  
  2042. void italic_corrected_node::tprint(troff_output_file *out)
  2043. {
  2044.   n->tprint(out);
  2045.   out->right(x);
  2046. }
  2047.  
  2048. hunits italic_corrected_node::skew()
  2049. {
  2050.   return n->skew() - x/2;
  2051. }
  2052.  
  2053. hunits italic_corrected_node::subscript_correction()
  2054. {
  2055.   return n->subscript_correction() - x;
  2056. }
  2057.  
  2058. void italic_corrected_node::ascii_print(ascii_output_file *out)
  2059. {
  2060.   n->ascii_print(out);
  2061. }
  2062.  
  2063. int italic_corrected_node::ends_sentence()
  2064. {
  2065.   return n->ends_sentence();
  2066. }
  2067.  
  2068. int italic_corrected_node::overlaps_horizontally()
  2069. {
  2070.   return n->overlaps_horizontally();
  2071. }
  2072.  
  2073. int italic_corrected_node::overlaps_vertically()
  2074. {
  2075.   return n->overlaps_vertically();
  2076. }
  2077.  
  2078. node *italic_corrected_node::last_char_node()
  2079. {
  2080.   return n->last_char_node();
  2081. }
  2082.  
  2083. tfont *italic_corrected_node::get_tfont()
  2084. {
  2085.   return n->get_tfont();
  2086. }
  2087.  
  2088. hyphenation_type italic_corrected_node::get_hyphenation_type()
  2089. {
  2090.   return n->get_hyphenation_type();
  2091. }
  2092.  
  2093. node *italic_corrected_node::add_self(node *nd, hyphen_list **p)
  2094. {
  2095.   nd = n->add_self(nd, p);
  2096.   hunits not_interested;
  2097.   nd = nd->add_italic_correction(¬_interested);
  2098.   n = 0;
  2099.   delete this;
  2100.   return nd;
  2101. }
  2102.  
  2103. hyphen_list *italic_corrected_node::get_hyphen_list(hyphen_list *tail)
  2104. {
  2105.   return n->get_hyphen_list(tail);
  2106. }
  2107.  
  2108. int italic_corrected_node::character_type()
  2109. {
  2110.   return n->character_type();
  2111. }
  2112.  
  2113. class break_char_node : public node {
  2114.   node *ch;
  2115.   char break_code;
  2116. public:
  2117.   break_char_node(node *, int, node * = 0);
  2118.   ~break_char_node();
  2119.   node *copy();
  2120.   hunits width();
  2121.   vunits vertical_width();
  2122.   node *last_char_node();
  2123.   int character_type();
  2124.   int ends_sentence();
  2125.   node *add_self(node *, hyphen_list **);
  2126.   hyphen_list *get_hyphen_list(hyphen_list *s = 0);
  2127.   void tprint(troff_output_file *);
  2128.   void zero_width_tprint(troff_output_file *);
  2129.   void ascii_print(ascii_output_file *);
  2130.   void asciify(macro *m);
  2131.   hyphenation_type get_hyphenation_type();
  2132.   int overlaps_vertically();
  2133.   int overlaps_horizontally();
  2134.   units size();
  2135.   tfont *get_tfont();
  2136.   int same(node *);
  2137.   const char *type();
  2138. };
  2139.  
  2140. break_char_node::break_char_node(node *n, int c, node *x)
  2141. : node(x), ch(n), break_code(c)
  2142. {
  2143. }
  2144.  
  2145. break_char_node::~break_char_node()
  2146. {
  2147.   delete ch;
  2148. }
  2149.  
  2150. node *break_char_node::copy()
  2151. {
  2152.   return new break_char_node(ch->copy(), break_code);
  2153. }
  2154.  
  2155. hunits break_char_node::width()
  2156. {
  2157.   return ch->width();
  2158. }
  2159.  
  2160. vunits break_char_node::vertical_width()
  2161. {
  2162.   return ch->vertical_width();
  2163. }
  2164.  
  2165. node *break_char_node::last_char_node()
  2166. {
  2167.   return ch->last_char_node();
  2168. }
  2169.  
  2170. int break_char_node::character_type()
  2171. {
  2172.   return ch->character_type();
  2173. }
  2174.  
  2175. int break_char_node::ends_sentence()
  2176. {
  2177.   return ch->ends_sentence();
  2178. }
  2179.  
  2180. node *break_char_node::add_self(node *n, hyphen_list **p)
  2181. {
  2182.   assert((*p)->hyphenation_code == 0);
  2183.   if ((*p)->breakable && (break_code & 1)) {
  2184.     n = new space_node(H0, n);
  2185.     n->freeze_space();
  2186.   }
  2187.   next = n;
  2188.   n = this;
  2189.   if ((*p)->breakable && (break_code & 2)) {
  2190.     n = new space_node(H0, n);
  2191.     n->freeze_space();
  2192.   }
  2193.   hyphen_list *pp = *p;
  2194.   *p = (*p)->next;
  2195.   delete pp;
  2196.   return n;
  2197. }
  2198.  
  2199. hyphen_list *break_char_node::get_hyphen_list(hyphen_list *tail)
  2200. {
  2201.   return new hyphen_list(0, tail);
  2202. }
  2203.  
  2204. hyphenation_type break_char_node::get_hyphenation_type()
  2205. {
  2206.   return HYPHEN_MIDDLE;
  2207. }
  2208.  
  2209. void break_char_node::ascii_print(ascii_output_file *ascii)
  2210. {
  2211.   ch->ascii_print(ascii);
  2212. }
  2213.  
  2214. int break_char_node::overlaps_vertically()
  2215. {
  2216.   return ch->overlaps_vertically();
  2217. }
  2218.  
  2219. int break_char_node::overlaps_horizontally()
  2220. {
  2221.   return ch->overlaps_horizontally();
  2222. }
  2223.  
  2224. units break_char_node::size()
  2225. {
  2226.   return ch->size();
  2227. }
  2228.  
  2229. tfont *break_char_node::get_tfont()
  2230. {
  2231.   return ch->get_tfont();
  2232. }
  2233.  
  2234. node *extra_size_node::copy()
  2235.   return new extra_size_node(n); 
  2236. }
  2237.  
  2238. node *vertical_size_node::copy()
  2239.   return new vertical_size_node(n); 
  2240. }
  2241.  
  2242. node *hmotion_node::copy()
  2243.   return new hmotion_node(n);
  2244. }
  2245.  
  2246. node *space_char_hmotion_node::copy()
  2247. {
  2248.   return new space_char_hmotion_node(n);
  2249. }
  2250.  
  2251. node *vmotion_node::copy()
  2252.   return new vmotion_node(n);
  2253. }
  2254.   
  2255. node *dummy_node::copy()
  2256.   return new dummy_node;
  2257. }
  2258.  
  2259. node *transparent_dummy_node::copy()
  2260.   return new transparent_dummy_node;
  2261. }
  2262.  
  2263. hline_node::~hline_node()
  2264. {
  2265.   if (n)
  2266.     delete n;
  2267. }
  2268.  
  2269. node *hline_node::copy()
  2270. {
  2271.   return new hline_node(x, n ? n->copy() : 0);
  2272. }
  2273.  
  2274. hunits hline_node::width()
  2275. {
  2276.   return x < H0 ? H0 : x;
  2277. }
  2278.  
  2279.  
  2280. vline_node::~vline_node()
  2281. {
  2282.   if (n)
  2283.     delete n;
  2284. }
  2285.  
  2286. node *vline_node::copy()
  2287. {
  2288.   return new vline_node(x, n ? n->copy() : 0);
  2289. }
  2290.  
  2291. hunits vline_node::width()
  2292. {
  2293.   return n == 0 ? H0 : n->width();
  2294. }
  2295.  
  2296.  
  2297. zero_width_node::zero_width_node(node *nd) : n(nd)
  2298. {
  2299. }
  2300.  
  2301. zero_width_node::~zero_width_node()
  2302. {
  2303.   delete_node_list(n);
  2304. }
  2305.  
  2306. node *zero_width_node::copy()
  2307. {
  2308.   return new zero_width_node(copy_node_list(n));
  2309. }
  2310.  
  2311. int node_list_character_type(node *p)
  2312. {
  2313.   int t = 0;
  2314.   for (; p; p = p->next)
  2315.     t |= p->character_type();
  2316.   return t;
  2317. }
  2318.  
  2319. int zero_width_node::character_type()
  2320. {
  2321.   return node_list_character_type(n);
  2322. }
  2323.  
  2324. void node_list_vertical_extent(node *p, vunits *min, vunits *max)
  2325. {
  2326.   *min = V0;
  2327.   *max = V0;
  2328.   vunits cur_vpos = V0;
  2329.   vunits v1, v2;
  2330.   for (; p; p = p->next) {
  2331.     p->vertical_extent(&v1, &v2);
  2332.     v1 += cur_vpos;
  2333.     if (v1 < *min)
  2334.       *min = v1;
  2335.     v2 += cur_vpos;
  2336.     if (v2 > *max)
  2337.       *max = v2;
  2338.     cur_vpos += p->vertical_width();
  2339.   }
  2340. }
  2341.  
  2342. void zero_width_node::vertical_extent(vunits *min, vunits *max)
  2343. {
  2344.   node_list_vertical_extent(n, min, max);
  2345. }
  2346.  
  2347. overstrike_node::overstrike_node() : max_width(H0), list(0)
  2348. {
  2349. }
  2350.  
  2351. overstrike_node::~overstrike_node()
  2352. {
  2353.   delete_node_list(list);
  2354. }
  2355.  
  2356. node *overstrike_node::copy()
  2357. {
  2358.   overstrike_node *on = new overstrike_node;
  2359.   for (node *tem = list; tem; tem = tem->next)
  2360.     on->overstrike(tem->copy());
  2361.   return on;
  2362. }
  2363.  
  2364. void overstrike_node::overstrike(node *n)
  2365. {
  2366.   if (n == 0)
  2367.     return;
  2368.   hunits w = n->width();
  2369.   if (w > max_width)
  2370.     max_width = w;
  2371.   for (node **p = &list; *p; p = &(*p)->next)
  2372.     ;
  2373.   n->next = 0;
  2374.   *p = n;
  2375. }
  2376.  
  2377. hunits overstrike_node::width()
  2378. {
  2379.   return max_width;
  2380. }
  2381.  
  2382. bracket_node::bracket_node() : max_width(H0), list(0)
  2383. {
  2384. }
  2385.  
  2386. bracket_node::~bracket_node()
  2387. {
  2388.   delete_node_list(list);
  2389. }
  2390.  
  2391. node *bracket_node::copy()
  2392. {
  2393.   bracket_node *on = new bracket_node;
  2394.   for (node *tem = list; tem; tem = tem->next)
  2395.     on->bracket(tem->copy());
  2396.   return on;
  2397. }
  2398.  
  2399.  
  2400. void bracket_node::bracket(node *n)
  2401. {
  2402.   if (n == 0)
  2403.     return;
  2404.   hunits w = n->width();
  2405.   if (w > max_width)
  2406.     max_width = w;
  2407.   n->next = list;
  2408.   list = n;
  2409. }
  2410.  
  2411. hunits bracket_node::width()
  2412. {
  2413.   return max_width;
  2414. }
  2415.  
  2416. int node::nspaces()
  2417. {
  2418.   return 0;
  2419. }
  2420.  
  2421. int node::merge_space(hunits)
  2422. {
  2423.   return 0;
  2424. }
  2425.  
  2426. #if 0
  2427. space_node *space_node::free_list = 0;
  2428.  
  2429. void *space_node::operator new(size_t n)
  2430. {
  2431.   assert(n == sizeof(space_node));
  2432.   if (!free_list) {
  2433.     free_list = (space_node *)new char[sizeof(space_node)*BLOCK];
  2434.     for (int i = 0; i < BLOCK - 1; i++)
  2435.       free_list[i].next = free_list + i + 1;
  2436.     free_list[BLOCK-1].next = 0;
  2437.   }
  2438.   space_node *p = free_list;
  2439.   free_list = (space_node *)(free_list->next);
  2440.   p->next = 0;
  2441.   return p;
  2442. }
  2443.  
  2444. inline void space_node::operator delete(void *p)
  2445. {
  2446.   if (p) {
  2447.     ((space_node *)p)->next = free_list;
  2448.     free_list = (space_node *)p;
  2449.   }
  2450. }
  2451. #endif
  2452.  
  2453. space_node::space_node(hunits nn, node *p) : node(p), n(nn), set(0)
  2454. {
  2455. }
  2456.  
  2457. space_node::space_node(hunits nn, int s, node *p) : node(p), n(nn), set(s)
  2458. {
  2459. }
  2460.  
  2461. #if 0
  2462. space_node::~space_node()
  2463. {
  2464. }
  2465. #endif
  2466.  
  2467. node *space_node::copy()
  2468. {
  2469.   return new space_node(n, set);
  2470. }
  2471.  
  2472. int space_node::nspaces()
  2473. {
  2474.   return set ? 0 : 1;
  2475. }
  2476.  
  2477. int space_node::merge_space(hunits h)
  2478. {
  2479.   n += h;
  2480.   return 1;
  2481. }
  2482.  
  2483. hunits space_node::width()
  2484. {
  2485.   return n;
  2486. }
  2487.  
  2488. void node::spread_space(int*, hunits*)
  2489. {
  2490. }
  2491.  
  2492. void space_node::spread_space(int *nspaces, hunits *desired_space)
  2493. {
  2494.   if (!set) {
  2495.     assert(*nspaces > 0);
  2496.     if (*nspaces == 1) {
  2497.       n += *desired_space;
  2498.       *desired_space = H0;
  2499.     }
  2500.     else {
  2501.       hunits extra = *desired_space / *nspaces;
  2502.       *desired_space -= extra;
  2503.       n += extra;
  2504.     }
  2505.     *nspaces -= 1;
  2506.     set = 1;
  2507.   }
  2508. }
  2509.  
  2510. void node::freeze_space()
  2511. {
  2512. }
  2513.  
  2514. void space_node::freeze_space()
  2515. {
  2516.   set = 1;
  2517. }
  2518.  
  2519. diverted_space_node::diverted_space_node(vunits d, node *p)
  2520. : node(p), n(d)
  2521. {
  2522. }
  2523.  
  2524. node *diverted_space_node::copy()
  2525. {
  2526.   return new diverted_space_node(n);
  2527. }
  2528.  
  2529. diverted_copy_file_node::diverted_copy_file_node(symbol s, node *p)
  2530. : node(p), filename(s)
  2531. {
  2532. }
  2533.  
  2534. node *diverted_copy_file_node::copy()
  2535. {
  2536.   return new diverted_copy_file_node(filename);
  2537. }
  2538.  
  2539. int node::ends_sentence()
  2540. {
  2541.   return 0;
  2542. }
  2543.  
  2544. int kern_pair_node::ends_sentence()
  2545. {
  2546.   switch (n2->ends_sentence()) {
  2547.   case 0:
  2548.     return 0;
  2549.   case 1:
  2550.     return 1;
  2551.   case 2:
  2552.     break;
  2553.   default:
  2554.     assert(0);
  2555.   }
  2556.   return n1->ends_sentence();
  2557. }
  2558.  
  2559. int node_list_ends_sentence(node *n)
  2560. {
  2561.   for (; n != 0; n = n->next)
  2562.     switch (n->ends_sentence()) {
  2563.     case 0:
  2564.       return 0;
  2565.     case 1:
  2566.       return 1;
  2567.     case 2:
  2568.       break;
  2569.     default:
  2570.       assert(0);
  2571.     }
  2572.   return 2;
  2573. }
  2574.  
  2575.     
  2576. int dbreak_node::ends_sentence()
  2577. {
  2578.   return node_list_ends_sentence(none);
  2579. }
  2580.  
  2581.  
  2582. int node::overlaps_horizontally()
  2583. {
  2584.   return 0;
  2585. }
  2586.  
  2587. int node::overlaps_vertically()
  2588. {
  2589.   return 0;
  2590. }
  2591.  
  2592. int node::discardable()
  2593. {
  2594.   return 0;
  2595. }
  2596.  
  2597. int space_node::discardable()
  2598. {
  2599.   return set ? 0 : 1;
  2600. }
  2601.  
  2602.  
  2603. vunits node::vertical_width()
  2604. {
  2605.   return V0;
  2606. }
  2607.  
  2608. vunits vline_node::vertical_width()
  2609. {
  2610.   return x;
  2611. }
  2612.  
  2613. vunits vmotion_node::vertical_width()
  2614. {
  2615.   return n;
  2616. }
  2617.  
  2618. int node::character_type()
  2619. {
  2620.   return 0;
  2621. }
  2622.  
  2623. hunits node::subscript_correction()
  2624. {
  2625.   return H0;
  2626. }
  2627.  
  2628. hunits node::italic_correction()
  2629. {
  2630.   return H0;
  2631. }
  2632.  
  2633. hunits node::left_italic_correction()
  2634. {
  2635.   return H0;
  2636. }
  2637.  
  2638. hunits node::skew()
  2639. {
  2640.   return H0;
  2641. }
  2642.  
  2643.  
  2644. /* vertical_extent methods */
  2645.  
  2646. void node::vertical_extent(vunits *min, vunits *max)
  2647. {
  2648.   vunits v = vertical_width();
  2649.   if (v < V0) {
  2650.     *min = v;
  2651.     *max = V0;
  2652.   }
  2653.   else {
  2654.     *max = v;
  2655.     *min = V0;
  2656.   }
  2657. }
  2658.  
  2659. void vline_node::vertical_extent(vunits *min, vunits *max)
  2660. {
  2661.   if (n == 0)
  2662.     node::vertical_extent(min, max);
  2663.   else {
  2664.     vunits cmin, cmax;
  2665.     n->vertical_extent(&cmin, &cmax);
  2666.     vunits h = n->size();
  2667.     if (x < V0) {
  2668.       if (-x < h) {
  2669.     *min = x;
  2670.     *max = V0;
  2671.       }
  2672.       else {
  2673.     // we print the first character and then move up, so
  2674.     *max = cmax;
  2675.     // we print the last character and then move up h
  2676.     *min = cmin + h;
  2677.     if (*min > V0)
  2678.       *min = V0;
  2679.     *min += x;
  2680.       }
  2681.     }
  2682.     else {
  2683.       if (x < h) {
  2684.     *max = x;
  2685.     *min = V0;
  2686.       }
  2687.       else {
  2688.     // we move down by h and then print the first character, so
  2689.     *min = cmin + h;
  2690.     if (*min > V0)
  2691.       *min = V0;
  2692.     *max = x + cmax;
  2693.       }
  2694.     }
  2695.   }
  2696. }
  2697.  
  2698. /* ascii_print methods */
  2699.  
  2700.  
  2701. static void ascii_print_reverse_node_list(ascii_output_file *ascii, node *n)
  2702. {
  2703.   if (n == 0)
  2704.     return;
  2705.   ascii_print_reverse_node_list(ascii, n->next);
  2706.   n->ascii_print(ascii);
  2707. }
  2708.  
  2709. void dbreak_node::ascii_print(ascii_output_file *ascii)
  2710. {
  2711.   ascii_print_reverse_node_list(ascii, none);
  2712. }
  2713.  
  2714. void kern_pair_node::ascii_print(ascii_output_file *ascii)
  2715. {
  2716.   n1->ascii_print(ascii);
  2717.   n2->ascii_print(ascii);
  2718. }
  2719.  
  2720.  
  2721. void node::ascii_print(ascii_output_file *)
  2722. {
  2723. }
  2724.  
  2725. void space_node::ascii_print(ascii_output_file *ascii)
  2726. {
  2727.   if (!n.is_zero())
  2728.     ascii->outc(' ');
  2729. }
  2730.  
  2731. void hmotion_node::ascii_print(ascii_output_file *ascii)
  2732. {
  2733.   // this is pretty arbitrary
  2734.   if (n >= points_to_units(2))
  2735.     ascii->outc(' ');
  2736. }
  2737.  
  2738. void space_char_hmotion_node::ascii_print(ascii_output_file *ascii)
  2739. {
  2740.   ascii->outc(' ');
  2741. }
  2742.  
  2743. /* asciify methods */
  2744.  
  2745. void node::asciify(macro *m)
  2746. {
  2747.   m->append(this);
  2748. }
  2749.       
  2750. void glyph_node::asciify(macro *m)
  2751. {
  2752.   unsigned char c = ci->get_ascii_code();
  2753.   if (c != 0) {
  2754.     m->append(c);
  2755.     delete this;
  2756.   }
  2757.   else
  2758.     m->append(this);
  2759. }
  2760.  
  2761. void kern_pair_node::asciify(macro *m)
  2762. {
  2763.   n1->asciify(m);
  2764.   n2->asciify(m);
  2765.   n1 = n2 = 0;
  2766.   delete this;
  2767. }
  2768.  
  2769. static void asciify_reverse_node_list(macro *m, node *n)
  2770. {
  2771.   if (n == 0)
  2772.     return;
  2773.   asciify_reverse_node_list(m, n->next);
  2774.   n->asciify(m);
  2775. }
  2776.  
  2777. void dbreak_node::asciify(macro *m)
  2778. {
  2779.   asciify_reverse_node_list(m, none);
  2780.   none = 0;
  2781.   delete this;
  2782. }
  2783.  
  2784. void ligature_node::asciify(macro *m)
  2785. {
  2786.   n1->asciify(m);
  2787.   n2->asciify(m);
  2788.   n1 = n2 = 0;
  2789.   delete this;
  2790. }
  2791.  
  2792. void break_char_node::asciify(macro *m)
  2793. {
  2794.   ch->asciify(m);
  2795.   ch = 0;
  2796.   delete this;
  2797. }
  2798.  
  2799. void italic_corrected_node::asciify(macro *m)
  2800. {
  2801.   n->asciify(m);
  2802.   n = 0;
  2803.   delete this;
  2804. }
  2805.  
  2806. void left_italic_corrected_node::asciify(macro *m)
  2807. {
  2808.   if (n) {
  2809.     n->asciify(m);
  2810.     n = 0;
  2811.   }
  2812.   delete this;
  2813. }
  2814.  
  2815. space_char_hmotion_node::space_char_hmotion_node(hunits i, node *next)
  2816. : hmotion_node(i, next)
  2817. {
  2818. }
  2819.  
  2820. void space_char_hmotion_node::asciify(macro *m)
  2821. {
  2822.   m->append(' ');
  2823.   delete this;
  2824. }
  2825.  
  2826. void line_start_node::asciify(macro *)
  2827. {
  2828.   delete this;
  2829. }
  2830.  
  2831. void vertical_size_node::asciify(macro *)
  2832. {
  2833.   delete this;
  2834. }
  2835.  
  2836. breakpoint *node::get_breakpoints(hunits /*width*/, int /*nspaces*/,
  2837.                   breakpoint *rest, int /*is_inner*/)
  2838. {
  2839.   return rest;
  2840. }
  2841.  
  2842. int node::nbreaks()
  2843. {
  2844.   return 0;
  2845. }
  2846.  
  2847. breakpoint *space_node::get_breakpoints(hunits width, int ns, breakpoint *rest,
  2848.                 int is_inner)
  2849. {
  2850.   if (next->discardable())
  2851.     return rest;
  2852.   breakpoint *bp = new breakpoint;
  2853.   bp->next = rest;
  2854.   bp->width = width;
  2855.   bp->nspaces = ns;
  2856.   bp->hyphenated = 0;
  2857.   if (is_inner) {
  2858.     assert(rest != 0);
  2859.     bp->index = rest->index + 1;
  2860.     bp->nd = rest->nd;
  2861.   }
  2862.   else {
  2863.     bp->nd = this;
  2864.     bp->index = 0;
  2865.   }
  2866.   return bp;
  2867. }
  2868.  
  2869. int space_node::nbreaks()
  2870. {
  2871.   if (next->discardable())
  2872.     return 0;
  2873.   else
  2874.     return 1;
  2875. }
  2876.  
  2877. static breakpoint *node_list_get_breakpoints(node *p, hunits *widthp,
  2878.                          int ns, breakpoint *rest)
  2879. {
  2880.   if (p != 0) {
  2881.     rest = p->get_breakpoints(*widthp, 
  2882.                   ns, 
  2883.                   node_list_get_breakpoints(p->next, widthp, ns,
  2884.                             rest),
  2885.                   1);
  2886.     *widthp += p->width();
  2887.   }
  2888.   return rest;
  2889. }
  2890.  
  2891.  
  2892. breakpoint *dbreak_node::get_breakpoints(hunits width, int ns,
  2893.                      breakpoint *rest, int is_inner)
  2894. {
  2895.   breakpoint *bp = new breakpoint;
  2896.   bp->next = rest;
  2897.   bp->width = width;
  2898.   for (node *tem = pre; tem != 0; tem = tem->next)
  2899.     bp->width += tem->width();
  2900.   bp->nspaces = ns;
  2901.   bp->hyphenated = 1;
  2902.   if (is_inner) {
  2903.     assert(rest != 0);
  2904.     bp->index = rest->index + 1;
  2905.     bp->nd = rest->nd;
  2906.   }
  2907.   else {
  2908.     bp->nd = this;
  2909.     bp->index = 0;
  2910.   }
  2911.   return node_list_get_breakpoints(none, &width, ns, bp);
  2912. }
  2913.  
  2914. int dbreak_node::nbreaks()
  2915. {
  2916.   int i = 1;
  2917.   for (node *tem = none; tem != 0; tem = tem->next)
  2918.     i += tem->nbreaks();
  2919.   return i;
  2920. }
  2921.  
  2922. void node::split(int /*where*/, node ** /*prep*/, node ** /*postp*/)
  2923. {
  2924.   assert(0);
  2925. }
  2926.  
  2927. void space_node::split(int where, node **pre, node **post)
  2928. {
  2929.   assert(where == 0);
  2930.   *pre = next;
  2931.   *post = 0;
  2932.   delete this;
  2933. }
  2934.  
  2935. static void node_list_split(node *p, int *wherep, node **prep, node **postp)
  2936. {
  2937.   if (p == 0)
  2938.     return;
  2939.   int nb = p->nbreaks();
  2940.   node_list_split(p->next, wherep, prep, postp);
  2941.   if (*wherep < 0) {
  2942.     p->next = *postp;
  2943.     *postp = p;
  2944.   }
  2945.   else if (*wherep < nb) {
  2946.     p->next = *prep;
  2947.     p->split(*wherep, prep, postp);
  2948.   }
  2949.   else {
  2950.     p->next = *prep;
  2951.     *prep = p;
  2952.   }
  2953.   *wherep -= nb;
  2954. }
  2955.  
  2956. void dbreak_node::split(int where, node **prep, node **postp)
  2957. {
  2958.   assert(where >= 0);
  2959.   if (where == 0) {
  2960.     *postp = post;
  2961.     post = 0;
  2962.     if (pre == 0)
  2963.       *prep = next;
  2964.     else {
  2965.       for (node *tem = pre; tem->next != 0; tem = tem->next)
  2966.     ;
  2967.       tem->next = next;
  2968.       *prep = pre;
  2969.     }
  2970.     pre = 0;
  2971.     delete this;
  2972.   }
  2973.   else {
  2974.     *prep = next;
  2975.     where -= 1;
  2976.     node_list_split(none, &where, prep, postp);
  2977.     none = 0;
  2978.     delete this;
  2979.   }
  2980. }
  2981.   
  2982.  
  2983. hyphenation_type node::get_hyphenation_type()
  2984. {
  2985.   return HYPHEN_BOUNDARY;
  2986. }
  2987.  
  2988.  
  2989. hyphenation_type dbreak_node::get_hyphenation_type()
  2990. {
  2991.   return HYPHEN_INHIBIT;
  2992. }
  2993.  
  2994. hyphenation_type kern_pair_node::get_hyphenation_type()
  2995. {
  2996.   return HYPHEN_MIDDLE;
  2997. }
  2998.  
  2999. hyphenation_type dummy_node::get_hyphenation_type()
  3000. {
  3001.   return HYPHEN_MIDDLE;
  3002. }
  3003.  
  3004. hyphenation_type transparent_dummy_node::get_hyphenation_type()
  3005. {
  3006.   return HYPHEN_MIDDLE;
  3007. }
  3008.  
  3009. int node::interpret(macro *)
  3010. {
  3011.   return 0;
  3012. }
  3013.  
  3014. special_node::special_node(const macro &m)
  3015. : mac(m)
  3016. {
  3017. }
  3018.  
  3019. int special_node::same(node *n)
  3020. {
  3021.   return mac == ((special_node *)n)->mac;
  3022. }
  3023.  
  3024. const char *special_node::type()
  3025. {
  3026.   return "special_node";
  3027. }
  3028.  
  3029. node *special_node::copy()
  3030. {
  3031.   return new special_node(mac);
  3032. }
  3033.  
  3034. void special_node::tprint_start(troff_output_file *out)
  3035. {
  3036.   out->start_special();
  3037. }
  3038.  
  3039. void special_node::tprint_char(troff_output_file *out, unsigned char c)
  3040. {
  3041.   out->special_char(c);
  3042. }
  3043.  
  3044. void special_node::tprint_end(troff_output_file *out)
  3045. {
  3046.   out->end_special();
  3047. }
  3048.  
  3049. /* composite_node */
  3050.  
  3051. class composite_node : public node {
  3052.   charinfo *ci;
  3053.   node *n;
  3054.   tfont *tf;
  3055. public:
  3056.   composite_node(node *, charinfo *, tfont *, node * = 0);
  3057.   ~composite_node();
  3058.   node *copy();
  3059.   hunits width();
  3060.   node *last_char_node();
  3061.   units size();
  3062.   void tprint(troff_output_file *);
  3063.   hyphenation_type get_hyphenation_type();
  3064.   int overlaps_horizontally();
  3065.   int overlaps_vertically();
  3066.   void ascii_print(ascii_output_file *);
  3067.   void asciify(macro *);
  3068.   hyphen_list *get_hyphen_list(hyphen_list *tail);
  3069.   node *add_self(node *, hyphen_list **);
  3070.   tfont *get_tfont();
  3071.   int same(node *);
  3072.   const char *type();
  3073.   void vertical_extent(vunits *, vunits *);
  3074.   vunits vertical_width();
  3075. };
  3076.  
  3077. composite_node::composite_node(node *p, charinfo *c, tfont *t, node *x)
  3078. : node(x), n(p), ci(c), tf(t)
  3079. {
  3080. }
  3081.  
  3082. composite_node::~composite_node()
  3083. {
  3084.   delete_node_list(n);
  3085. }
  3086.  
  3087. node *composite_node::copy()
  3088. {
  3089.   return new composite_node(copy_node_list(n), ci, tf);
  3090. }
  3091.  
  3092. hunits composite_node::width()
  3093. {
  3094.   hunits x;
  3095.   if (tf->get_constant_space(&x))
  3096.     return x;
  3097.   x = H0;
  3098.   for (node *tem = n; tem; tem = tem->next)
  3099.     x += tem->width();
  3100.   hunits offset;
  3101.   if (tf->get_bold(&offset))
  3102.     x += offset;
  3103.   x += tf->get_track_kern();
  3104.   return x;
  3105. }
  3106.  
  3107. node *composite_node::last_char_node()
  3108. {
  3109.   return this;
  3110. }
  3111.  
  3112. vunits composite_node::vertical_width()
  3113. {
  3114.   vunits v = V0;
  3115.   for (node *tem = n; tem; tem = tem->next)
  3116.     v += tem->vertical_width();
  3117.   return v;
  3118. }
  3119.  
  3120. units composite_node::size()
  3121. {
  3122.   return tf->get_size().to_units();
  3123. }
  3124.  
  3125. hyphenation_type composite_node::get_hyphenation_type()
  3126. {
  3127.   return HYPHEN_MIDDLE;
  3128. }
  3129.  
  3130. int composite_node::overlaps_horizontally()
  3131. {
  3132.   return ci->overlaps_horizontally();
  3133. }
  3134.  
  3135. int composite_node::overlaps_vertically()
  3136. {
  3137.   return ci->overlaps_vertically();
  3138. }
  3139.  
  3140. void composite_node::asciify(macro *m)
  3141. {
  3142.   unsigned char c = ci->get_ascii_code();
  3143.   if (c != 0) {
  3144.     m->append(c);
  3145.     delete this;
  3146.   }
  3147.   else
  3148.     m->append(this);
  3149. }
  3150.  
  3151. void composite_node::ascii_print(ascii_output_file *ascii)
  3152. {
  3153.   unsigned char c = ci->get_ascii_code();
  3154.   if (c != 0)
  3155.     ascii->outc(c);
  3156.   else
  3157.     ascii->outs(ci->nm.contents());
  3158.  
  3159. }
  3160.  
  3161. hyphen_list *composite_node::get_hyphen_list(hyphen_list *tail)
  3162. {
  3163.   return new hyphen_list(ci->get_hyphenation_code(), tail);
  3164.  
  3165. }
  3166.  
  3167. node *composite_node::add_self(node *nn, hyphen_list **p)
  3168. {
  3169.   assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
  3170.   next = nn;
  3171.   nn = this;
  3172.   if ((*p)->hyphen)
  3173.     nn = nn->add_discretionary_hyphen();
  3174.   hyphen_list *pp = *p;
  3175.   *p = (*p)->next;
  3176.   delete pp;
  3177.   return nn;
  3178. }
  3179.  
  3180. tfont *composite_node::get_tfont()
  3181. {
  3182.   return tf;
  3183. }
  3184.  
  3185. node *reverse_node_list(node *n)
  3186. {
  3187.   node *r = 0;
  3188.   while (n) {
  3189.     node *tem = n;
  3190.     n = n->next;
  3191.     tem->next = r;
  3192.     r = tem;
  3193.   }
  3194.   return r;
  3195. }
  3196.  
  3197. void composite_node::vertical_extent(vunits *min, vunits *max)
  3198. {
  3199.   n = reverse_node_list(n);
  3200.   node_list_vertical_extent(n, min, max);
  3201.   n = reverse_node_list(n);
  3202. }
  3203.  
  3204. word_space_node::word_space_node(hunits d, node *x) : space_node(d, x)
  3205. {
  3206. }
  3207.  
  3208. word_space_node::word_space_node(hunits d, int s, node *x)
  3209. : space_node(d, s, x)
  3210. {
  3211. }
  3212.  
  3213. node *word_space_node::copy()
  3214. {
  3215.   return new word_space_node(n, set);
  3216. }
  3217.  
  3218. void word_space_node::tprint(troff_output_file *out)
  3219. {
  3220.   out->word_marker();
  3221.   space_node::tprint(out);
  3222. }
  3223.  
  3224. unbreakable_space_node::unbreakable_space_node(hunits d, node *x)
  3225. : word_space_node(d, x)
  3226. {
  3227. }
  3228.  
  3229. unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x)
  3230. : word_space_node(d, s, x)
  3231. {
  3232. }
  3233.  
  3234. node *unbreakable_space_node::copy()
  3235. {
  3236.   return new unbreakable_space_node(n, set);
  3237. }
  3238.  
  3239. breakpoint *unbreakable_space_node::get_breakpoints(hunits, int,
  3240.                             breakpoint *rest, int)
  3241. {
  3242.   return rest;
  3243. }
  3244.  
  3245. int unbreakable_space_node::nbreaks()
  3246. {
  3247.   return 0;
  3248. }
  3249.  
  3250. void unbreakable_space_node::split(int, node **, node **)
  3251. {
  3252.   assert(0);
  3253. }
  3254.  
  3255. int unbreakable_space_node::merge_space(hunits)
  3256. {
  3257.   return 0;
  3258. }
  3259.  
  3260. hvpair::hvpair()
  3261. {
  3262. }
  3263.  
  3264. draw_node::draw_node(char c, hvpair *p, int np, font_size s)
  3265.      : code(c), npoints(np), sz(s)
  3266. {
  3267.   point = new hvpair[npoints];
  3268.   for (int i = 0; i < npoints; i++)
  3269.     point[i] = p[i];
  3270. }
  3271.  
  3272. int draw_node::same(node *n)
  3273. {
  3274.   draw_node *nd = (draw_node *)n;
  3275.   if (code != nd->code || npoints != nd->npoints || sz != nd->sz)
  3276.     return 0;
  3277.   for (int i = 0; i < npoints; i++)
  3278.     if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v)
  3279.       return 0;
  3280.   return 1;
  3281. }
  3282.  
  3283. const char *draw_node::type()
  3284. {
  3285.   return "draw_node";
  3286. }
  3287.  
  3288. draw_node::~draw_node()
  3289. {
  3290.   if (point)
  3291.     a_delete point;
  3292. }
  3293.  
  3294. hunits draw_node::width()
  3295. {
  3296.   hunits x = H0;
  3297.   for (int i = 0; i < npoints; i++)
  3298.     x += point[i].h;
  3299.   return x;
  3300. }
  3301.  
  3302. vunits draw_node::vertical_width()
  3303. {
  3304.   if (code == 'e')
  3305.     return V0;
  3306.   vunits x = V0;
  3307.   for (int i = 0; i < npoints; i++)
  3308.     x += point[i].v;
  3309.   return x;
  3310. }
  3311.  
  3312. node *draw_node::copy()
  3313. {
  3314.   return new draw_node(code, point, npoints, sz);
  3315. }
  3316.  
  3317. void draw_node::tprint(troff_output_file *out)
  3318. {
  3319.   out->draw(code, point, npoints, sz);
  3320. }
  3321.   
  3322. /* tprint methods */
  3323.  
  3324. void glyph_node::tprint(troff_output_file *out)
  3325. {
  3326.   tfont *ptf = tf->get_plain();
  3327.   if (ptf == tf)
  3328.     out->put_char_width(ci, ptf, width(), H0);
  3329.   else {
  3330.     hunits offset;
  3331.     int bold = tf->get_bold(&offset);
  3332.     hunits w = ptf->get_width(ci);
  3333.     hunits k = H0;
  3334.     hunits x;
  3335.     int cs = tf->get_constant_space(&x);
  3336.     if (cs) {
  3337.       x -= w;
  3338.       if (bold)
  3339.     x -= offset;
  3340.       hunits x2 = x/2;
  3341.       out->right(x2);
  3342.       k = x - x2;
  3343.     }
  3344.     else
  3345.       k = tf->get_track_kern();
  3346.     if (bold) {
  3347.       out->put_char(ci, ptf);
  3348.       out->right(offset);
  3349.     }
  3350.     out->put_char_width(ci, ptf, w, k);
  3351.   }
  3352. }
  3353.  
  3354. void glyph_node::zero_width_tprint(troff_output_file *out)
  3355. {
  3356.   tfont *ptf = tf->get_plain();
  3357.   hunits offset;
  3358.   int bold = tf->get_bold(&offset);
  3359.   hunits x;
  3360.   int cs = tf->get_constant_space(&x);
  3361.   if (cs) {
  3362.     x -= ptf->get_width(ci);
  3363.     if (bold)
  3364.       x -= offset;
  3365.     x = x/2;
  3366.     out->right(x);
  3367.   }
  3368.   out->put_char(ci, ptf);
  3369.   if (bold) {
  3370.     out->right(offset);
  3371.     out->put_char(ci, ptf);
  3372.     out->right(-offset);
  3373.   }
  3374.   if (cs)
  3375.     out->right(-x);
  3376. }
  3377.  
  3378. void break_char_node::tprint(troff_output_file *t)
  3379. {
  3380.   ch->tprint(t);
  3381. }
  3382.  
  3383. void break_char_node::zero_width_tprint(troff_output_file *t)
  3384. {
  3385.   ch->zero_width_tprint(t);
  3386. }
  3387.  
  3388. void hline_node::tprint(troff_output_file *out)
  3389. {
  3390.   if (x < H0) {
  3391.     out->right(x);
  3392.     x = -x;
  3393.   }
  3394.   if (n == 0) {
  3395.     out->right(x);
  3396.     return;
  3397.   }
  3398.   hunits w = n->width();
  3399.   if (w <= H0) {
  3400.     error("horizontal line drawing character must have positive width");
  3401.     out->right(x);
  3402.     return;
  3403.   }
  3404.   int i = int(x/w);
  3405.   if (i == 0) {
  3406.     hunits xx = x - w;
  3407.     hunits xx2 = xx/2;
  3408.     out->right(xx2);
  3409.     n->tprint(out);
  3410.     out->right(xx - xx2);
  3411.   }
  3412.   else {
  3413.     hunits rem = x - w*i;
  3414.     if (rem > H0)
  3415.       if (n->overlaps_horizontally()) {
  3416.     n->tprint(out);
  3417.     out->right(rem - w);
  3418.       }
  3419.       else
  3420.     out->right(rem);
  3421.     while (--i >= 0)
  3422.       n->tprint(out);
  3423.   }
  3424. }
  3425.  
  3426. void vline_node::tprint(troff_output_file *out)
  3427. {
  3428.   if (n == 0) {
  3429.     out->down(x);
  3430.     return;
  3431.   }
  3432.   vunits h = n->size();
  3433.   int overlaps = n->overlaps_vertically();
  3434.   vunits y = x;
  3435.   if (y < V0) {
  3436.     y = -y;
  3437.     int i = y / h;
  3438.     vunits rem = y - i*h;
  3439.     if (i == 0) {
  3440.       out->right(n->width());
  3441.       out->down(-rem);
  3442.     }
  3443.     else {
  3444.       while (--i > 0) {
  3445.     n->zero_width_tprint(out);
  3446.     out->down(-h);
  3447.       }
  3448.       if (overlaps) {
  3449.     n->zero_width_tprint(out);
  3450.     out->down(-rem);
  3451.     n->tprint(out);
  3452.     out->down(-h);
  3453.       }
  3454.       else {
  3455.     n->tprint(out);
  3456.     out->down(-h - rem);
  3457.       }
  3458.     }
  3459.   }
  3460.   else {
  3461.     int i = y / h;
  3462.     vunits rem = y - i*h;
  3463.     if (i == 0) {
  3464.       out->down(rem);
  3465.       out->right(n->width());
  3466.     }
  3467.     else {
  3468.       out->down(h);
  3469.       if (overlaps)
  3470.     n->zero_width_tprint(out);
  3471.       out->down(rem);
  3472.       while (--i > 0) {
  3473.     n->zero_width_tprint(out);
  3474.     out->down(h);
  3475.       }
  3476.       n->tprint(out);
  3477.     }
  3478.   }
  3479. }
  3480.  
  3481. void zero_width_node::tprint(troff_output_file *out)
  3482. {
  3483.   if (!n)
  3484.     return;
  3485.   if (!n->next) {
  3486.     n->zero_width_tprint(out);
  3487.     return;
  3488.   }
  3489.   int hpos = out->get_hpos();
  3490.   int vpos = out->get_vpos();
  3491.   node *tem = n;
  3492.   while (tem) {
  3493.     tem->tprint(out);
  3494.     tem = tem->next;
  3495.   }
  3496.   out->moveto(hpos, vpos);
  3497. }
  3498.  
  3499. void overstrike_node::tprint(troff_output_file *out)
  3500. {
  3501.   hunits pos = H0;
  3502.   for (node *tem = list; tem; tem = tem->next) {
  3503.     hunits x = (max_width - tem->width())/2;
  3504.     out->right(x - pos);
  3505.     pos = x;
  3506.     tem->zero_width_tprint(out);
  3507.   }
  3508.   out->right(max_width - pos);
  3509. }
  3510.  
  3511. void bracket_node::tprint(troff_output_file *out)
  3512. {
  3513.   if (list == 0)
  3514.     return;
  3515.   int npieces = 0;
  3516.   for (node *tem = list; tem; tem = tem->next)
  3517.     ++npieces;
  3518.   vunits h = list->size();
  3519.   vunits totalh = h*npieces;
  3520.   vunits y = (totalh - h)/2;
  3521.   out->down(y);
  3522.   for (tem = list; tem; tem = tem->next) {
  3523.     tem->zero_width_tprint(out);
  3524.     out->down(-h);
  3525.   }
  3526.   out->right(max_width);
  3527.   out->down(totalh - y);
  3528. }
  3529.  
  3530. void node::tprint(troff_output_file *)
  3531. {
  3532. }
  3533.  
  3534. void node::zero_width_tprint(troff_output_file *out)
  3535. {
  3536.   int hpos = out->get_hpos();
  3537.   int vpos = out->get_vpos();
  3538.   tprint(out);
  3539.   out->moveto(hpos, vpos);
  3540. }
  3541.  
  3542. void space_node::tprint(troff_output_file *out)
  3543. {
  3544.   out->right(n);
  3545. }
  3546.  
  3547. void hmotion_node::tprint(troff_output_file *out)
  3548. {
  3549.   out->right(n);
  3550. }
  3551.  
  3552. void vmotion_node::tprint(troff_output_file *out)
  3553. {
  3554.   out->down(n);
  3555. }
  3556.  
  3557. void kern_pair_node::tprint(troff_output_file *out)
  3558. {
  3559.   n1->tprint(out);
  3560.   out->right(amount);
  3561.   n2->tprint(out);
  3562. }
  3563.  
  3564. static void tprint_reverse_node_list(troff_output_file *out, node *n)
  3565. {
  3566.   if (n == 0)
  3567.     return;
  3568.   tprint_reverse_node_list(out, n->next);
  3569.   n->tprint(out);
  3570. }
  3571.  
  3572. void dbreak_node::tprint(troff_output_file *out)
  3573. {
  3574.   tprint_reverse_node_list(out, none);
  3575. }
  3576.  
  3577. void composite_node::tprint(troff_output_file *out)
  3578. {
  3579.   hunits bold_offset;
  3580.   int is_bold = tf->get_bold(&bold_offset);
  3581.   hunits track_kern = tf->get_track_kern();
  3582.   hunits constant_space;
  3583.   int is_constant_spaced = tf->get_constant_space(&constant_space);
  3584.   hunits x = H0;
  3585.   if (is_constant_spaced) {
  3586.     x = constant_space;
  3587.     for (node *tem = n; tem; tem = tem->next)
  3588.       x -= tem->width();
  3589.     if (is_bold)
  3590.       x -= bold_offset;
  3591.     hunits x2 = x/2;
  3592.     out->right(x2);
  3593.     x -= x2;
  3594.   }
  3595.   if (is_bold) {
  3596.     int hpos = out->get_hpos();
  3597.     int vpos = out->get_vpos();
  3598.     tprint_reverse_node_list(out, n);
  3599.     out->moveto(hpos, vpos);
  3600.     out->right(bold_offset);
  3601.   }
  3602.   tprint_reverse_node_list(out, n);
  3603.   if (is_constant_spaced)
  3604.     out->right(x);
  3605.   else
  3606.     out->right(track_kern);
  3607. }
  3608.  
  3609. node *make_composite_node(charinfo *s, environment *env)
  3610. {
  3611.   int fontno = env_definite_font(env);
  3612.   if (fontno < 0) {
  3613.     error("no current font");
  3614.     return 0;
  3615.   }
  3616.   assert(fontno < font_table_size && font_table[fontno] != 0);
  3617.   node *n = charinfo_to_node_list(s, env);
  3618.   font_size fs = env->get_font_size();
  3619.   int char_height = env->get_char_height();
  3620.   int char_slant = env->get_char_slant();
  3621.   tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
  3622.                         fontno);
  3623.   if (env->is_composite())
  3624.     tf = tf->get_plain();
  3625.   return new composite_node(n, s, tf);
  3626. }
  3627.  
  3628. node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
  3629. {
  3630.   int fontno = env_definite_font(env);
  3631.   if (fontno < 0) {
  3632.     error("no current font");
  3633.     return 0;
  3634.   }
  3635.   assert(fontno < font_table_size && font_table[fontno] != 0);
  3636.   int fn = fontno;
  3637.   int found = font_table[fontno]->contains(s);
  3638.   if (!found) {
  3639.     if (s->numbered()) {
  3640.       if (!no_error_message)
  3641.     warning(WARN_CHAR, "can't find numbered character %1",
  3642.         s->get_number());
  3643.       return 0;
  3644.     }
  3645.     special_font_list *sf = font_table[fontno]->sf;
  3646.     while (sf != 0 && !found) {
  3647.       fn = sf->n;
  3648.       if (font_table[fn])
  3649.     found = font_table[fn]->contains(s);
  3650.       sf = sf->next;
  3651.     }
  3652.     if (!found) {
  3653.       sf = global_special_fonts;
  3654.       while (sf != 0 && !found) {
  3655.     fn = sf->n;
  3656.     if (font_table[fn])
  3657.       found = font_table[fn]->contains(s);
  3658.     sf = sf->next;
  3659.       }
  3660.     }
  3661.     if (!found
  3662. #if 0    
  3663.     && global_special_fonts == 0 && font_table[fontno]->sf == 0
  3664. #endif
  3665.     ) {
  3666.       for (fn = 0; fn < font_table_size; fn++)
  3667.     if (font_table[fn] 
  3668.         && font_table[fn]->is_special()
  3669.         && font_table[fn]->contains(s)) {
  3670.           found = 1;
  3671.           break;
  3672.         }
  3673.     }
  3674.     if (!found) {
  3675.       if (!no_error_message && s->first_time_not_found()) {
  3676.     unsigned char input_code = s->get_ascii_code();
  3677.     if (input_code != 0) {
  3678.       if (csgraph(input_code))
  3679.         warning(WARN_CHAR, "can't find character `%1'", input_code);
  3680.       else
  3681.         warning(WARN_CHAR, "can't find character with input code %1",
  3682.             int(input_code));
  3683.     }
  3684.     else
  3685.       warning(WARN_CHAR, "can't find special character `%1'",
  3686.           s->nm.contents());
  3687.       }
  3688.       return 0;
  3689.     }
  3690.   }
  3691.   font_size fs = env->get_font_size();
  3692.   int char_height = env->get_char_height();
  3693.   int char_slant = env->get_char_slant();
  3694.   tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn);
  3695.   if (env->is_composite())
  3696.     tf = tf->get_plain();
  3697.   return new glyph_node(s, tf);
  3698. }
  3699.  
  3700. node *make_node(charinfo *ci, environment *env)
  3701. {
  3702.   switch (ci->get_special_translation()) {
  3703.   case charinfo::TRANSLATE_SPACE:
  3704.     return new space_char_hmotion_node(env->get_space_width());
  3705.   case charinfo::TRANSLATE_DUMMY:
  3706.     return new dummy_node;
  3707.   case charinfo::TRANSLATE_HYPHEN_INDICATOR:
  3708.     error("translation to \\% ignored in this context");
  3709.     break;
  3710.   }
  3711.   charinfo *tem = ci->get_translation();
  3712.   if (tem)
  3713.     ci = tem;
  3714.   macro *mac = ci->get_macro();
  3715.   if (mac)
  3716.     return make_composite_node(ci, env);
  3717.   else
  3718.     return make_glyph_node(ci, env);
  3719. }
  3720.  
  3721. int character_exists(charinfo *ci, environment *env)
  3722. {
  3723.   if (ci->get_special_translation() != charinfo::TRANSLATE_NONE)
  3724.     return 1;
  3725.   charinfo *tem = ci->get_translation();
  3726.   if (tem)
  3727.     ci = tem;
  3728.   if (ci->get_macro())
  3729.     return 1;
  3730.   node *nd = make_glyph_node(ci, env, 1);
  3731.   if (nd) {
  3732.     delete nd;
  3733.     return 1;
  3734.   }
  3735.   return 0;
  3736. }
  3737.  
  3738. node *node::add_char(charinfo *ci, environment *env, hunits *widthp)
  3739. {
  3740.   node *res;
  3741.   switch (ci->get_special_translation()) {
  3742.   case charinfo::TRANSLATE_SPACE:
  3743.     res = new space_char_hmotion_node(env->get_space_width(), this);
  3744.     *widthp += res->width();
  3745.     return res;
  3746.   case charinfo::TRANSLATE_DUMMY:
  3747.     return new dummy_node(this);
  3748.   case charinfo::TRANSLATE_HYPHEN_INDICATOR:
  3749.     return add_discretionary_hyphen();
  3750.   }
  3751.   charinfo *tem = ci->get_translation();
  3752.   if (tem)
  3753.     ci = tem;
  3754.   macro *mac = ci->get_macro();
  3755.   if (mac) {
  3756.     res = make_composite_node(ci, env);
  3757.     if (res) {
  3758.       res->next = this;
  3759.       *widthp += res->width();
  3760.     }
  3761.     else
  3762.       return this;
  3763.   }
  3764.   else {
  3765.     node *gn = make_glyph_node(ci, env);
  3766.     if (gn == 0)
  3767.       return this;
  3768.     else {
  3769.       hunits old_width = width();
  3770.       node *p = gn->merge_self(this);
  3771.       if (p == 0) {
  3772.     *widthp += gn->width();
  3773.     gn->next = this;
  3774.     res = gn;
  3775.       }
  3776.       else {
  3777.     *widthp += p->width() - old_width;
  3778.     res = p;
  3779.       }
  3780.     }
  3781.   }
  3782.   int break_code = 0;
  3783.   if (ci->can_break_before())
  3784.     break_code = 1;
  3785.   if (ci->can_break_after())
  3786.     break_code |= 2;
  3787.   if (break_code) {
  3788.     node *next1 = res->next;
  3789.     res->next = 0;
  3790.     res = new break_char_node(res, break_code, next1);
  3791.   }
  3792.   return res;
  3793. }
  3794.  
  3795.  
  3796. #ifdef __GNUG__
  3797. inline
  3798. #endif
  3799. int same_node(node *n1, node *n2)
  3800. {
  3801.   if (n1 != 0) {
  3802.     if (n2 != 0)
  3803.       return n1->type() == n2->type() && n1->same(n2);
  3804.     else
  3805.       return 0;
  3806.   }
  3807.   else
  3808.     return n2 == 0;
  3809. }
  3810.  
  3811. int same_node_list(node *n1, node *n2)
  3812. {
  3813.   while (n1 && n2) {
  3814.     if (n1->type() != n2->type() || !n1->same(n2))
  3815.       return 0;
  3816.     n1 = n1->next;
  3817.     n2 = n2->next;
  3818.   }
  3819.   return !n1 && !n2;
  3820. }
  3821.  
  3822. int extra_size_node::same(node *nd)
  3823. {
  3824.   return n == ((extra_size_node *)nd)->n;
  3825. }
  3826.  
  3827. const char *extra_size_node::type()
  3828. {
  3829.   return "extra_size_node";
  3830. }
  3831.  
  3832. int vertical_size_node::same(node *nd)
  3833. {
  3834.   return n == ((vertical_size_node *)nd)->n;
  3835. }
  3836.  
  3837. const char *vertical_size_node::type()
  3838. {
  3839.   return "vertical_size_node";
  3840. }
  3841.  
  3842. int hmotion_node::same(node *nd)
  3843. {
  3844.   return n == ((hmotion_node *)nd)->n;
  3845. }
  3846.  
  3847. const char *hmotion_node::type()
  3848. {
  3849.   return "hmotion_node";
  3850. }
  3851.  
  3852. int space_char_hmotion_node::same(node *nd)
  3853. {
  3854.   return n == ((space_char_hmotion_node *)nd)->n;
  3855. }
  3856.  
  3857. const char *space_char_hmotion_node::type()
  3858. {
  3859.   return "space_char_hmotion_node";
  3860. }
  3861.  
  3862. int vmotion_node::same(node *nd)
  3863. {
  3864.   return n == ((vmotion_node *)nd)->n;
  3865. }
  3866.  
  3867. const char *vmotion_node::type()
  3868. {
  3869.   return "vmotion_node";
  3870. }
  3871.  
  3872. int hline_node::same(node *nd)
  3873. {
  3874.   return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n);
  3875. }
  3876.  
  3877. const char *hline_node::type()
  3878. {
  3879.   return "hline_node";
  3880. }
  3881.  
  3882. int vline_node::same(node *nd)
  3883. {
  3884.   return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n);
  3885. }
  3886.  
  3887. const char *vline_node::type()
  3888. {
  3889.   return "vline_node";
  3890. }
  3891.  
  3892. int dummy_node::same(node * /*nd*/)
  3893. {
  3894.   return 1;
  3895. }
  3896.  
  3897. const char *dummy_node::type()
  3898. {
  3899.   return "dummy_node";
  3900. }
  3901.  
  3902. int transparent_dummy_node::same(node * /*nd*/)
  3903. {
  3904.   return 1;
  3905. }
  3906.  
  3907. const char *transparent_dummy_node::type()
  3908. {
  3909.   return "transparent_dummy_node";
  3910. }
  3911.  
  3912. int transparent_dummy_node::ends_sentence()
  3913. {
  3914.   return 2;
  3915. }
  3916.  
  3917. int zero_width_node::same(node *nd)
  3918. {
  3919.   return same_node_list(n, ((zero_width_node *)nd)->n);
  3920. }
  3921.  
  3922. const char *zero_width_node::type()
  3923. {
  3924.   return "zero_width_node";
  3925. }
  3926.  
  3927. int italic_corrected_node::same(node *nd)
  3928. {
  3929.   return (x == ((italic_corrected_node *)nd)->x
  3930.       && same_node(n, ((italic_corrected_node *)nd)->n));
  3931. }
  3932.  
  3933. const char *italic_corrected_node::type()
  3934. {
  3935.   return "italic_corrected_node";
  3936. }
  3937.  
  3938.  
  3939. left_italic_corrected_node::left_italic_corrected_node(node *x)
  3940. : n(0), node(x)
  3941. {
  3942. }
  3943.  
  3944. left_italic_corrected_node::~left_italic_corrected_node()
  3945. {
  3946.   delete n;
  3947. }
  3948.  
  3949. node *left_italic_corrected_node::merge_glyph_node(glyph_node *gn)
  3950. {
  3951.   if (n == 0) {
  3952.     hunits lic = gn->left_italic_correction();
  3953.     if (!lic.is_zero()) {
  3954.       x = lic;
  3955.       n = gn;
  3956.       return this;
  3957.     }
  3958.   }
  3959.   else {
  3960.     node *nd = n->merge_glyph_node(gn);
  3961.     if (nd) {
  3962.       n = nd;
  3963.       x = n->left_italic_correction();
  3964.       return this;
  3965.     }
  3966.   }
  3967.   return 0;
  3968. }
  3969.  
  3970. node *left_italic_corrected_node::copy()
  3971. {
  3972.   left_italic_corrected_node *nd = new left_italic_corrected_node;
  3973.   if (n) {
  3974.     nd->n = n->copy();
  3975.     nd->x = x;
  3976.   }
  3977.   return nd;
  3978. }
  3979.  
  3980. void left_italic_corrected_node::tprint(troff_output_file *out)
  3981. {
  3982.   if (n) {
  3983.     out->right(x);
  3984.     n->tprint(out);
  3985.   }
  3986. }
  3987.  
  3988. const char *left_italic_corrected_node::type()
  3989. {
  3990.   return "left_italic_corrected_node";
  3991. }
  3992.  
  3993. int left_italic_corrected_node::same(node *nd)
  3994. {
  3995.   return (x == ((left_italic_corrected_node *)nd)->x
  3996.       && same_node(n, ((left_italic_corrected_node *)nd)->n));
  3997. }
  3998.  
  3999. void left_italic_corrected_node::ascii_print(ascii_output_file *out)
  4000. {
  4001.   if (n)
  4002.     n->ascii_print(out);
  4003. }
  4004.  
  4005. hunits left_italic_corrected_node::width()
  4006. {
  4007.   return n ? n->width() + x : H0;
  4008. }
  4009.  
  4010. void left_italic_corrected_node::vertical_extent(vunits *min, vunits *max)
  4011. {
  4012.   if (n)
  4013.     n->vertical_extent(min, max);
  4014.   else
  4015.     node::vertical_extent(min, max);
  4016. }
  4017.  
  4018. hunits left_italic_corrected_node::skew()
  4019. {
  4020.   return n ? n->skew() + x/2 : H0;
  4021. }
  4022.  
  4023. hunits left_italic_corrected_node::subscript_correction()
  4024. {
  4025.   return n ? n->subscript_correction() : H0;
  4026. }
  4027.  
  4028. hunits left_italic_corrected_node::italic_correction()
  4029. {
  4030.   return n ? n->italic_correction() : H0;
  4031. }
  4032.  
  4033. int left_italic_corrected_node::ends_sentence()
  4034. {
  4035.   return n ? n->ends_sentence() : 0;
  4036. }
  4037.  
  4038. int left_italic_corrected_node::overlaps_horizontally()
  4039. {
  4040.   return n ? n->overlaps_horizontally() : 0;
  4041. }
  4042.  
  4043. int left_italic_corrected_node::overlaps_vertically()
  4044. {
  4045.   return n ? n->overlaps_vertically() : 0;
  4046. }
  4047.  
  4048. node *left_italic_corrected_node::last_char_node()
  4049. {
  4050.   return n ? n->last_char_node() : 0;
  4051. }
  4052.  
  4053. tfont *left_italic_corrected_node::get_tfont()
  4054. {
  4055.   return n ? n->get_tfont() : 0;
  4056. }
  4057.  
  4058. hyphenation_type left_italic_corrected_node::get_hyphenation_type()
  4059. {
  4060.   if (n)
  4061.     return n->get_hyphenation_type();
  4062.   else
  4063.     return HYPHEN_MIDDLE;
  4064. }
  4065.  
  4066. hyphen_list *left_italic_corrected_node::get_hyphen_list(hyphen_list *tail)
  4067. {
  4068.   return n ? n->get_hyphen_list(tail) : tail;
  4069. }
  4070.  
  4071. node *left_italic_corrected_node::add_self(node *nd, hyphen_list **p)
  4072. {
  4073.   if (n) {
  4074.     nd = new left_italic_corrected_node(nd);
  4075.     nd = n->add_self(nd, p);
  4076.     n = 0;
  4077.     delete this;
  4078.   }
  4079.   return nd;
  4080. }
  4081.  
  4082. int left_italic_corrected_node::character_type()
  4083. {
  4084.   return n ? n->character_type() : 0;
  4085. }
  4086.  
  4087. int overstrike_node::same(node *nd)
  4088. {
  4089.   return same_node_list(list, ((overstrike_node *)nd)->list);
  4090. }
  4091.  
  4092. const char *overstrike_node::type()
  4093. {
  4094.   return "overstrike_node";
  4095. }
  4096.  
  4097. int bracket_node::same(node *nd)
  4098. {
  4099.   return same_node_list(list, ((bracket_node *)nd)->list);
  4100. }
  4101.  
  4102. const char *bracket_node::type()
  4103. {
  4104.   return "bracket_node";
  4105. }
  4106.  
  4107. int composite_node::same(node *nd)
  4108. {
  4109.   return ci == ((composite_node *)nd)->ci
  4110.     && same_node_list(n, ((composite_node *)nd)->n);
  4111. }
  4112.  
  4113. const char *composite_node::type()
  4114. {
  4115.   return "composite_node";
  4116. }
  4117.  
  4118. int glyph_node::same(node *nd)
  4119. {
  4120.   return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf;
  4121. }
  4122.  
  4123. const char *glyph_node::type()
  4124. {
  4125.   return "glyph_node";
  4126. }
  4127.  
  4128. int ligature_node::same(node *nd)
  4129. {
  4130.   return (same_node(n1, ((ligature_node *)nd)->n1) 
  4131.       && same_node(n2, ((ligature_node *)nd)->n2)
  4132.       && glyph_node::same(nd));
  4133. }
  4134.  
  4135. const char *ligature_node::type()
  4136. {
  4137.   return "ligature_node";
  4138. }
  4139.  
  4140. int kern_pair_node::same(node *nd)
  4141. {
  4142.   return (amount == ((kern_pair_node *)nd)->amount
  4143.       && same_node(n1, ((kern_pair_node *)nd)->n1)
  4144.       && same_node(n2, ((kern_pair_node *)nd)->n2));
  4145. }
  4146.  
  4147. const char *kern_pair_node::type()
  4148. {
  4149.   return "kern_pair_node";
  4150. }
  4151.  
  4152. int dbreak_node::same(node *nd)
  4153. {
  4154.   return (same_node_list(none, ((dbreak_node *)nd)->none)
  4155.       && same_node_list(pre, ((dbreak_node *)nd)->pre)
  4156.       && same_node_list(post, ((dbreak_node *)nd)->post));
  4157. }
  4158.  
  4159. const char *dbreak_node::type()
  4160. {
  4161.   return "dbreak_node";
  4162. }
  4163.  
  4164. int break_char_node::same(node *nd)
  4165. {
  4166.   return (break_code == ((break_char_node *)nd)->break_code
  4167.       && same_node(ch, ((break_char_node *)nd)->ch));
  4168. }
  4169.  
  4170. const char *break_char_node::type()
  4171. {
  4172.   return "break_char_node";
  4173. }
  4174.  
  4175. int line_start_node::same(node * /*nd*/)
  4176. {
  4177.   return 1;
  4178. }
  4179.  
  4180. const char *line_start_node::type()
  4181. {
  4182.   return "line_start_node";
  4183. }
  4184.  
  4185. int space_node::same(node *nd)
  4186. {
  4187.   return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set;
  4188. }
  4189.  
  4190. const char *space_node::type()
  4191. {
  4192.   return "space_node";
  4193. }
  4194.  
  4195. int word_space_node::same(node *nd)
  4196. {
  4197.   return (n == ((word_space_node *)nd)->n
  4198.       && set == ((word_space_node *)nd)->set);
  4199. }
  4200.  
  4201. const char *word_space_node::type()
  4202. {
  4203.   return "word_space_node";
  4204. }
  4205.  
  4206. int unbreakable_space_node::same(node *nd)
  4207. {
  4208.   return (n == ((unbreakable_space_node *)nd)->n
  4209.       && set == ((unbreakable_space_node *)nd)->set);
  4210. }
  4211.  
  4212. const char *unbreakable_space_node::type()
  4213. {
  4214.   return "unbreakable_space_node";
  4215. }
  4216.  
  4217. int diverted_space_node::same(node *nd)
  4218. {
  4219.   return n == ((diverted_space_node *)nd)->n;
  4220. }
  4221.  
  4222. const char *diverted_space_node::type()
  4223. {
  4224.   return "diverted_space_node";
  4225. }
  4226.  
  4227. int diverted_copy_file_node::same(node *nd)
  4228. {
  4229.   return filename == ((diverted_copy_file_node *)nd)->filename;
  4230. }
  4231.  
  4232. const char *diverted_copy_file_node::type()
  4233. {
  4234.   return "diverted_copy_file_node";
  4235. }
  4236.  
  4237. // Grow the font_table so that its size is > n.
  4238.  
  4239. static void grow_font_table(int n)
  4240. {
  4241.   assert(n >= font_table_size);
  4242.   font_info **old_font_table = font_table;
  4243.   int old_font_table_size = font_table_size;
  4244.   font_table_size = font_table_size ? (font_table_size*3)/2 : 10;
  4245.   if (font_table_size <= n)
  4246.     font_table_size = n + 10;
  4247.   font_table = new font_info *[font_table_size];
  4248.   if (old_font_table_size)
  4249.     memcpy(font_table, old_font_table,
  4250.        old_font_table_size*sizeof(font_info *));
  4251.   a_delete old_font_table;
  4252.   for (int i = old_font_table_size; i < font_table_size; i++)
  4253.     font_table[i] = 0;
  4254. }
  4255.  
  4256. dictionary font_translation_dictionary(17);
  4257.  
  4258. static symbol get_font_translation(symbol nm)
  4259. {
  4260.   void *p = font_translation_dictionary.lookup(nm);
  4261.   return p ? symbol((char *)p) : nm;
  4262. }
  4263.  
  4264. dictionary font_dictionary(50);
  4265.  
  4266. static int mount_font_no_translate(int n, symbol name, symbol external_name)
  4267. {
  4268.   assert(n >= 0);
  4269.   // We store the address of this char in font_dictionary to indicate
  4270.   // that we've previously tried to mount the font and failed.
  4271.   static char a_char;
  4272.   font *fm = 0;
  4273.   void *p = font_dictionary.lookup(external_name);
  4274.   if (p == 0) {
  4275.     int not_found;
  4276.     fm = font::load_font(external_name.contents(), ¬_found);
  4277.     if (!fm) {
  4278.       if (not_found)
  4279.     warning(WARN_FONT, "can't find font `%1'", external_name.contents());
  4280.       font_dictionary.lookup(external_name, &a_char);
  4281.       return 0;
  4282.     }
  4283.     font_dictionary.lookup(name, fm);
  4284.   }
  4285.   else if (p == &a_char) {
  4286. #if 0
  4287.     error("invalid font `%1'", external_name.contents());
  4288. #endif
  4289.     return 0;
  4290.   }
  4291.   else
  4292.     fm = (font*)p;
  4293.   if (n >= font_table_size) {
  4294.     if (n - font_table_size > 1000) {
  4295.       error("font position too much larger than first unused position");
  4296.       return 0;
  4297.     }
  4298.     grow_font_table(n);
  4299.   }
  4300.   else if (font_table[n] != 0)
  4301.     delete font_table[n];
  4302.   font_table[n] = new font_info(name, n, external_name, fm);
  4303.   invalidate_fontno(n);
  4304.   return 1;
  4305. }
  4306.  
  4307. int mount_font(int n, symbol name, symbol external_name)
  4308. {
  4309.   assert(n >= 0);
  4310.   name = get_font_translation(name);
  4311.   if (external_name.is_null())
  4312.     external_name = name;
  4313.   else
  4314.     external_name = get_font_translation(external_name);
  4315.   return mount_font_no_translate(n, name, external_name);
  4316. }
  4317.  
  4318. void mount_style(int n, symbol name)
  4319. {
  4320.   assert(n >= 0);
  4321.   if (n >= font_table_size) {
  4322.     if (n - font_table_size > 1000) {
  4323.       error("font position too much larger than first unused position");
  4324.       return;
  4325.     }
  4326.     grow_font_table(n);
  4327.   }
  4328.   else if (font_table[n] != 0)
  4329.     delete font_table[n];
  4330.   font_table[n] = new font_info(get_font_translation(name), n, NULL_SYMBOL, 0);
  4331.   invalidate_fontno(n);
  4332. }
  4333.  
  4334. /* global functions */
  4335.  
  4336. void font_translate()
  4337. {
  4338.   symbol from = get_name(1);
  4339.   if (!from.is_null()) {
  4340.     symbol to = get_name();
  4341.     if (to.is_null() || from == to)
  4342.       font_translation_dictionary.remove(from);
  4343.     else
  4344.       font_translation_dictionary.lookup(from, (void *)to.contents());
  4345.   }
  4346.   skip_line();
  4347. }
  4348.  
  4349. void font_position()
  4350. {
  4351.   int n;
  4352.   if (get_integer(&n)) {
  4353.     if (n < 0)
  4354.       error("negative font position");
  4355.     else {
  4356.       symbol internal_name = get_name(1);
  4357.       if (!internal_name.is_null()) {
  4358.     symbol external_name = get_long_name(0);
  4359.     mount_font(n, internal_name, external_name); // ignore error
  4360.       }
  4361.     }
  4362.   }
  4363.   skip_line();
  4364. }
  4365.  
  4366. font_family::font_family(symbol s)
  4367. : nm(s), map_size(10)
  4368. {
  4369.   map = new int[map_size];
  4370.   for (int i = 0; i < map_size; i++)
  4371.     map[i] = -1;
  4372. }
  4373.  
  4374. font_family::~font_family()
  4375. {
  4376.   a_delete map;
  4377. }
  4378.  
  4379. int font_family::make_definite(int i)
  4380. {
  4381.   if (i >= 0) {
  4382.     if (i < map_size && map[i] >= 0)
  4383.       return map[i];
  4384.     else {
  4385.       if (i < font_table_size && font_table[i] != 0) {
  4386.     if (i >= map_size) {
  4387.       int old_map_size = map_size;
  4388.       int *old_map = map;
  4389.       map_size *= 3;
  4390.       map_size /= 2;
  4391.       if (i >= map_size)
  4392.         map_size = i + 10;
  4393.       map = new int[map_size];
  4394.       memcpy(map, old_map, old_map_size*sizeof(int));
  4395.       a_delete old_map;
  4396.       for (int j = old_map_size; j < map_size; j++)
  4397.         map[j] = -1;
  4398.     }
  4399.     if (font_table[i]->is_style()) {
  4400.       symbol sty = font_table[i]->get_name();
  4401.       symbol f = concat(nm, sty);
  4402.       int n;
  4403.       // don't use symbol_fontno, because that might return a style
  4404.       // and because we don't want to translate the name
  4405.       for (n = 0; n < font_table_size; n++)
  4406.         if (font_table[n] != 0 && font_table[n]->is_named(f)
  4407.         && !font_table[n]->is_style())
  4408.           break;
  4409.       if (n >= font_table_size) {
  4410.         n = next_available_font_position();
  4411.         if (!mount_font_no_translate(n, f, f))
  4412.           return -1;
  4413.       }
  4414.       return map[i] = n;
  4415.     }
  4416.     else
  4417.       return map[i] = i;
  4418.       }
  4419.       else
  4420.     return -1;
  4421.     }
  4422.   }
  4423.   else
  4424.     return -1;
  4425. }
  4426.  
  4427. dictionary family_dictionary(5);
  4428.  
  4429. font_family *lookup_family(symbol nm)
  4430. {
  4431.   font_family *f = (font_family *)family_dictionary.lookup(nm);
  4432.   if (!f) {
  4433.     f = new font_family(nm);
  4434.     (void)family_dictionary.lookup(nm, f);
  4435.   }
  4436.   return f;
  4437.  
  4438. static void invalidate_fontno(int n)
  4439. {
  4440.   assert(n >= 0 && n < font_table_size);
  4441.   dictionary_iterator iter(family_dictionary);
  4442.   symbol nm;
  4443.   font_family *fam;
  4444.   while (iter.get(&nm, (void **)&fam)) {
  4445.     int map_size = fam->map_size;
  4446.     if (n < map_size)
  4447.       fam->map[n] = -1;
  4448.     for (int i = 0; i < map_size; i++)
  4449.       if (fam->map[i] == n)
  4450.     fam->map[i] = -1;
  4451.   }
  4452. }
  4453.  
  4454. void style()
  4455. {
  4456.   int n;
  4457.   if (get_integer(&n)) {
  4458.     if (n < 0)
  4459.       error("negative font position");
  4460.     else {
  4461.       symbol internal_name = get_name(1);
  4462.       if (!internal_name.is_null())
  4463.     mount_style(n, internal_name);
  4464.     }
  4465.   }
  4466.   skip_line();
  4467. }
  4468.  
  4469. static int get_fontno()
  4470. {
  4471.   int n;
  4472.   tok.skip();
  4473.   if (tok.delimiter()) {
  4474.     symbol s = get_name(1);
  4475.     if (!s.is_null()) {
  4476.       n = symbol_fontno(s);
  4477.       if (n < 0) {
  4478.     n = next_available_font_position();
  4479.     if (!mount_font(n, s))
  4480.       return -1;
  4481.       }
  4482.       return curenv->get_family()->make_definite(n);
  4483.     }
  4484.   }
  4485.   else if (get_integer(&n)) {
  4486.     if (n < 0 || n >= font_table_size || font_table[n] == 0)
  4487.       error("bad font number");
  4488.     else
  4489.       return curenv->get_family()->make_definite(n);
  4490.   }
  4491.   return -1;
  4492. }
  4493.  
  4494. static int underline_fontno = 2;
  4495.  
  4496. void underline_font()
  4497. {
  4498.   int n = get_fontno();
  4499.   if (n >= 0)
  4500.     underline_fontno = n;
  4501.   skip_line();
  4502. }
  4503.  
  4504. int get_underline_fontno()
  4505. {
  4506.   return underline_fontno;
  4507. }
  4508.     
  4509. static void read_special_fonts(special_font_list **sp)
  4510. {
  4511.   special_font_list *s = *sp;
  4512.   *sp = 0;
  4513.   while (s != 0) {
  4514.     special_font_list *tem = s;
  4515.     s = s->next;
  4516.     delete tem;
  4517.   }
  4518.   special_font_list **p = sp;
  4519.   while (has_arg()) {
  4520.     int i = get_fontno();
  4521.     if (i >= 0) {
  4522.       special_font_list *tem = new special_font_list;
  4523.       tem->n = i;
  4524.       tem->next = 0;
  4525.       *p = tem;
  4526.       p = &(tem->next);
  4527.     }
  4528.   }
  4529. }
  4530.  
  4531. void font_special_request()
  4532. {
  4533.   int n = get_fontno();
  4534.   if (n >= 0)
  4535.     read_special_fonts(&font_table[n]->sf); 
  4536.   skip_line();
  4537. }
  4538.  
  4539.   
  4540. void special_request()
  4541. {
  4542.   read_special_fonts(&global_special_fonts);
  4543.   skip_line();
  4544. }
  4545.  
  4546. int next_available_font_position()
  4547. {
  4548.   for (int i = 1; i < font_table_size && font_table[i] != 0; i++)
  4549.     ;
  4550.   return i;
  4551. }
  4552.  
  4553. int symbol_fontno(symbol s)
  4554. {
  4555.   s = get_font_translation(s);
  4556.   for (int i = 0; i < font_table_size; i++)
  4557.     if (font_table[i] != 0 && font_table[i]->is_named(s))
  4558.       return i;
  4559.   return -1;
  4560. }
  4561.  
  4562. int is_good_fontno(int n)
  4563. {
  4564.   return n >= 0 && n < font_table_size && font_table[n] != NULL;
  4565. }
  4566.  
  4567. int get_bold_fontno(int n)
  4568. {
  4569.   if (n >= 0 && n < font_table_size && font_table[n] != 0) {
  4570.     hunits offset;
  4571.     if (font_table[n]->get_bold(&offset))
  4572.       return offset.to_units() + 1;
  4573.     else
  4574.       return 0;
  4575.   }
  4576.   else
  4577.     return 0;
  4578. }
  4579.  
  4580. hunits env_digit_width(environment *env)
  4581. {
  4582.   node *n = make_glyph_node(charset_table['0'], env);
  4583.   if (n) {
  4584.     hunits x = n->width();
  4585.     delete n;
  4586.     return x;
  4587.   }
  4588.   else
  4589.     return H0;
  4590. }
  4591.  
  4592. hunits env_space_width(environment *env)
  4593. {
  4594.   int fn = env_definite_font(env);
  4595.   font_size fs = env->get_font_size();
  4596.   if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
  4597.     return scale(fs.to_units()/3, env->get_space_size(), 12);
  4598.   else
  4599.     return font_table[fn]->get_space_width(fs, env->get_space_size());
  4600. }
  4601.  
  4602. hunits env_sentence_space_width(environment *env)
  4603. {
  4604.   int fn = env_definite_font(env);
  4605.   font_size fs = env->get_font_size();
  4606.   if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
  4607.     return scale(fs.to_units()/3, env->get_sentence_space_size(), 12);
  4608.   else
  4609.     return font_table[fn]->get_space_width(fs, env->get_sentence_space_size());
  4610. }
  4611.  
  4612. hunits env_half_narrow_space_width(environment *env)
  4613. {
  4614.   int fn = env_definite_font(env);
  4615.   font_size fs = env->get_font_size();
  4616.   if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
  4617.     return 0;
  4618.   else
  4619.     return font_table[fn]->get_half_narrow_space_width(fs);
  4620. }
  4621.  
  4622. hunits env_narrow_space_width(environment *env)
  4623. {
  4624.   int fn = env_definite_font(env);
  4625.   font_size fs = env->get_font_size();
  4626.   if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
  4627.     return 0;
  4628.   else
  4629.     return font_table[fn]->get_narrow_space_width(fs);
  4630. }
  4631.  
  4632. void bold_font()
  4633. {
  4634.   int n = get_fontno();
  4635.   if (n >= 0) {
  4636.     if (has_arg()) {
  4637.       if (tok.delimiter()) {
  4638.     int f = get_fontno();
  4639.     if (f >= 0) {
  4640.       units offset;
  4641.       if (has_arg() && get_number(&offset, 'u') && offset >= 1)
  4642.         font_table[f]->set_conditional_bold(n, hunits(offset - 1));
  4643.       else
  4644.         font_table[f]->conditional_unbold(n);
  4645.     }
  4646.       }
  4647.       else {
  4648.     units offset;
  4649.     if (get_number(&offset, 'u') && offset >= 1)
  4650.       font_table[n]->set_bold(hunits(offset - 1));
  4651.     else
  4652.       font_table[n]->unbold();
  4653.       }
  4654.     }
  4655.     else
  4656.       font_table[n]->unbold();
  4657.   }
  4658.   skip_line();
  4659. }
  4660.  
  4661. track_kerning_function::track_kerning_function() : non_zero(0)
  4662. {
  4663. }
  4664.  
  4665. track_kerning_function::track_kerning_function(int min_s, hunits min_a, 
  4666.                            int max_s, hunits max_a)
  4667.      : non_zero(1), 
  4668.      min_size(min_s), min_amount(min_a),
  4669.      max_size(max_s), max_amount(max_a)
  4670. {
  4671. }
  4672.  
  4673. int track_kerning_function::operator==(const track_kerning_function &tk)
  4674. {
  4675.   if (non_zero)
  4676.     return (tk.non_zero
  4677.         && min_size == tk.min_size
  4678.         && min_amount == tk.min_amount
  4679.         && max_size == tk.max_size
  4680.         && max_amount == tk.max_amount);
  4681.   else
  4682.     return !tk.non_zero;
  4683. }
  4684.  
  4685. int track_kerning_function::operator!=(const track_kerning_function &tk)
  4686. {
  4687.   if (non_zero)
  4688.     return (!tk.non_zero
  4689.         || min_size != tk.min_size
  4690.         || min_amount != tk.min_amount
  4691.         || max_size != tk.max_size
  4692.         || max_amount != tk.max_amount);
  4693.   else
  4694.     return tk.non_zero;
  4695. }
  4696.  
  4697. hunits track_kerning_function::compute(int size)
  4698. {
  4699.   if (non_zero) {
  4700.     if (max_size <= min_size)
  4701.       return min_amount;
  4702.     else if (size <= min_size)
  4703.       return min_amount;
  4704.     else if (size >= max_size)
  4705.       return max_amount;
  4706.     else
  4707.       return (scale(max_amount, size - min_size, max_size - min_size)
  4708.           + scale(min_amount, max_size - size, max_size - min_size));
  4709.   }
  4710.   else
  4711.     return H0;
  4712. }
  4713.  
  4714. void track_kern()
  4715. {
  4716.   int n = get_fontno();
  4717.   if (n >= 0) {
  4718.     int min_s, max_s;
  4719.     hunits min_a, max_a;
  4720.     if (has_arg()
  4721.     && get_number(&min_s, 'z')
  4722.     && get_hunits(&min_a, 'p')
  4723.     && get_number(&max_s, 'z')
  4724.     && get_hunits(&max_a, 'p')) {
  4725.       track_kerning_function tk(min_s, min_a, max_s, max_a);
  4726.       font_table[n]->set_track_kern(tk);
  4727.     }
  4728.     else {
  4729.       track_kerning_function tk;
  4730.       font_table[n]->set_track_kern(tk);
  4731.     }
  4732.   }
  4733.   skip_line();
  4734. }
  4735.  
  4736. void constant_space()
  4737. {
  4738.   int n = get_fontno();
  4739.   if (n >= 0) {
  4740.     int x, y;
  4741.     if (!has_arg() || !get_integer(&x))
  4742.       font_table[n]->set_constant_space(CONSTANT_SPACE_NONE);
  4743.     else {
  4744.       if (!has_arg() || !get_number(&y, 'z'))
  4745.     font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x);
  4746.       else
  4747.     font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE, 
  4748.                       scale(y*x,
  4749.                         units_per_inch,
  4750.                         36*72*sizescale));
  4751.     }
  4752.   }
  4753.   skip_line();
  4754. }
  4755.  
  4756. void ligature()
  4757. {
  4758.   int lig;
  4759.   if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2)
  4760.     global_ligature_mode = lig;
  4761.   else
  4762.     global_ligature_mode = 1;
  4763.   skip_line();
  4764. }
  4765.  
  4766. void kern_request()
  4767. {
  4768.   int k;
  4769.   if (has_arg() && get_integer(&k))
  4770.     global_kern_mode = k != 0;
  4771.   else
  4772.     global_kern_mode = 1;
  4773.   skip_line();
  4774. }
  4775.  
  4776. void set_soft_hyphen_char()
  4777. {
  4778.   soft_hyphen_char = get_optional_char();
  4779.   if (!soft_hyphen_char)
  4780.     soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
  4781.   skip_line();
  4782. }
  4783.  
  4784. void init_output()
  4785. {
  4786.   if (suppress_output_flag)
  4787.     the_output = new suppress_output_file;
  4788.   else if (ascii_output_flag)
  4789.     the_output = new ascii_output_file;
  4790.   else
  4791.     the_output = new troff_output_file;
  4792. }
  4793.  
  4794. class next_available_font_position_reg : public reg {
  4795. public:
  4796.   const char *get_string();
  4797. };
  4798.  
  4799. const char *next_available_font_position_reg::get_string()
  4800. {
  4801.   return itoa(next_available_font_position());
  4802. }
  4803.  
  4804. class printing_reg : public reg {
  4805. public:
  4806.   const char *get_string();
  4807. };
  4808.  
  4809. const char *printing_reg::get_string()
  4810. {
  4811.   if (the_output)
  4812.     return the_output->is_printing() ? "1" : "0";
  4813.   else
  4814.     return "0";
  4815. }
  4816.  
  4817. void init_node_requests()
  4818. {
  4819.   init_request("fp", font_position);
  4820.   init_request("sty", style);
  4821.   init_request("cs", constant_space);
  4822.   init_request("bd", bold_font);
  4823.   init_request("uf", underline_font);
  4824.   init_request("lg", ligature);
  4825.   init_request("kern", kern_request);
  4826.   init_request("tkf", track_kern);
  4827.   init_request("special", special_request);
  4828.   init_request("fspecial", font_special_request);
  4829.   init_request("ftr", font_translate);
  4830.   init_request("shc", set_soft_hyphen_char);
  4831.   number_reg_dictionary.define(".fp", new next_available_font_position_reg);
  4832.   number_reg_dictionary.define(".kern",
  4833.                    new constant_int_reg(&global_kern_mode));
  4834.   number_reg_dictionary.define(".lg",
  4835.                    new constant_int_reg(&global_ligature_mode));
  4836.   number_reg_dictionary.define(".P", new printing_reg);
  4837.   soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
  4838. }
  4839.