home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / groff / troff / node.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-30  |  88.9 KB  |  4,689 lines

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